From 0787734848573bda02bc2f512f9d1a26cb1c9c94 Mon Sep 17 00:00:00 2001 From: Christian Findlay <16697547+MelbourneDeveloper@users.noreply.github.com> Date: Sat, 4 Apr 2026 10:23:44 +1100 Subject: [PATCH 01/59] Add gatekeeper --- .../AuthenticationTests.cs | 306 ++++++++ .../AuthorizationTests.cs | 646 ++++++++++++++++ .../Gatekeeper.Api.Tests.csproj | 35 + .../Gatekeeper.Api.Tests/GlobalUsings.cs | 36 + .../Gatekeeper.Api.Tests/TokenServiceTests.cs | 597 +++++++++++++++ .../Gatekeeper.Api/AuthorizationService.cs | 113 +++ Gatekeeper/Gatekeeper.Api/DataProvider.json | 34 + Gatekeeper/Gatekeeper.Api/DatabaseSetup.cs | 148 ++++ .../Gatekeeper.Api/FileLoggerProvider.cs | 109 +++ .../Gatekeeper.Api/Gatekeeper.Api.csproj | 67 ++ .../Gatekeeper.Api/Generated/.timestamp | 0 .../Generated/CheckPermission.g.cs | 107 +++ .../Generated/CheckResourceGrant.g.cs | 151 ++++ .../Generated/CountSystemRoles.g.cs | 70 ++ .../Generated/GetActivePolicies.g.cs | 127 ++++ .../Generated/GetAllPermissions.g.cs | 102 +++ .../Gatekeeper.Api/Generated/GetAllRoles.g.cs | 102 +++ .../Gatekeeper.Api/Generated/GetAllUsers.g.cs | 102 +++ .../Generated/GetChallengeById.g.cs | 112 +++ .../Generated/GetCredentialById.g.cs | 164 ++++ .../Generated/GetCredentialsByUserId.g.cs | 151 ++++ .../Generated/GetPermissionByCode.g.cs | 107 +++ .../Generated/GetRolePermissions.g.cs | 115 +++ .../Generated/GetSessionById.g.cs | 145 ++++ .../Generated/GetSessionForRevoke.g.cs | 127 ++++ .../Generated/GetSessionRevoked.g.cs | 76 ++ .../Generated/GetUserByEmail.g.cs | 113 +++ .../Gatekeeper.Api/Generated/GetUserById.g.cs | 113 +++ .../Generated/GetUserCredentials.g.cs | 150 ++++ .../Generated/GetUserPermissions.g.cs | 152 ++++ .../Generated/GetUserRoles.g.cs | 114 +++ .../Generated/RevokeSession.g.cs | 82 ++ .../Generated/gk_challengeOperations.g.cs | 52 ++ .../Generated/gk_credentialOperations.g.cs | 59 ++ .../Generated/gk_permissionOperations.g.cs | 52 ++ .../gk_resource_grantOperations.g.cs | 54 ++ .../Generated/gk_roleOperations.g.cs | 52 ++ .../gk_role_permissionOperations.g.cs | 49 ++ .../Generated/gk_sessionOperations.g.cs | 90 +++ .../Generated/gk_userOperations.g.cs | 53 ++ .../Generated/gk_user_roleOperations.g.cs | 51 ++ Gatekeeper/Gatekeeper.Api/GlobalUsings.cs | 59 ++ Gatekeeper/Gatekeeper.Api/Program.cs | 716 ++++++++++++++++++ .../Properties/launchSettings.json | 14 + .../Gatekeeper.Api/Sql/CheckPermission.sql | 24 + .../Gatekeeper.Api/Sql/CheckResourceGrant.sql | 10 + .../Gatekeeper.Api/Sql/CountSystemRoles.sql | 2 + .../Gatekeeper.Api/Sql/GetActivePolicies.sql | 7 + .../Gatekeeper.Api/Sql/GetAllPermissions.sql | 4 + Gatekeeper/Gatekeeper.Api/Sql/GetAllRoles.sql | 4 + Gatekeeper/Gatekeeper.Api/Sql/GetAllUsers.sql | 4 + .../Gatekeeper.Api/Sql/GetChallengeById.sql | 4 + .../Gatekeeper.Api/Sql/GetCredentialById.sql | 7 + .../Sql/GetCredentialsByUserId.sql | 6 + .../Sql/GetPermissionByCode.sql | 4 + .../Gatekeeper.Api/Sql/GetRolePermissions.sql | 6 + .../Gatekeeper.Api/Sql/GetSessionById.sql | 7 + .../Sql/GetSessionForRevoke.sql | 6 + .../Gatekeeper.Api/Sql/GetSessionRevoked.sql | 3 + .../Gatekeeper.Api/Sql/GetUserByEmail.sql | 4 + Gatekeeper/Gatekeeper.Api/Sql/GetUserById.sql | 4 + .../Gatekeeper.Api/Sql/GetUserCredentials.sql | 5 + .../Gatekeeper.Api/Sql/GetUserPermissions.sql | 26 + .../Gatekeeper.Api/Sql/GetUserRoles.sql | 6 + .../Gatekeeper.Api/Sql/RevokeSession.sql | 3 + Gatekeeper/Gatekeeper.Api/TokenService.cs | 191 +++++ .../Gatekeeper.Api/gatekeeper-schema.yaml | 397 ++++++++++ Gatekeeper/Gatekeeper.Api/gatekeeper.db | Bin 0 -> 147456 bytes Gatekeeper/README.md | 13 + HealthcareSamples.sln | 145 +++- 70 files changed, 6765 insertions(+), 1 deletion(-) create mode 100644 Gatekeeper/Gatekeeper.Api.Tests/AuthenticationTests.cs create mode 100644 Gatekeeper/Gatekeeper.Api.Tests/AuthorizationTests.cs create mode 100644 Gatekeeper/Gatekeeper.Api.Tests/Gatekeeper.Api.Tests.csproj create mode 100644 Gatekeeper/Gatekeeper.Api.Tests/GlobalUsings.cs create mode 100644 Gatekeeper/Gatekeeper.Api.Tests/TokenServiceTests.cs create mode 100644 Gatekeeper/Gatekeeper.Api/AuthorizationService.cs create mode 100644 Gatekeeper/Gatekeeper.Api/DataProvider.json create mode 100644 Gatekeeper/Gatekeeper.Api/DatabaseSetup.cs create mode 100644 Gatekeeper/Gatekeeper.Api/FileLoggerProvider.cs create mode 100644 Gatekeeper/Gatekeeper.Api/Gatekeeper.Api.csproj create mode 100644 Gatekeeper/Gatekeeper.Api/Generated/.timestamp create mode 100644 Gatekeeper/Gatekeeper.Api/Generated/CheckPermission.g.cs create mode 100644 Gatekeeper/Gatekeeper.Api/Generated/CheckResourceGrant.g.cs create mode 100644 Gatekeeper/Gatekeeper.Api/Generated/CountSystemRoles.g.cs create mode 100644 Gatekeeper/Gatekeeper.Api/Generated/GetActivePolicies.g.cs create mode 100644 Gatekeeper/Gatekeeper.Api/Generated/GetAllPermissions.g.cs create mode 100644 Gatekeeper/Gatekeeper.Api/Generated/GetAllRoles.g.cs create mode 100644 Gatekeeper/Gatekeeper.Api/Generated/GetAllUsers.g.cs create mode 100644 Gatekeeper/Gatekeeper.Api/Generated/GetChallengeById.g.cs create mode 100644 Gatekeeper/Gatekeeper.Api/Generated/GetCredentialById.g.cs create mode 100644 Gatekeeper/Gatekeeper.Api/Generated/GetCredentialsByUserId.g.cs create mode 100644 Gatekeeper/Gatekeeper.Api/Generated/GetPermissionByCode.g.cs create mode 100644 Gatekeeper/Gatekeeper.Api/Generated/GetRolePermissions.g.cs create mode 100644 Gatekeeper/Gatekeeper.Api/Generated/GetSessionById.g.cs create mode 100644 Gatekeeper/Gatekeeper.Api/Generated/GetSessionForRevoke.g.cs create mode 100644 Gatekeeper/Gatekeeper.Api/Generated/GetSessionRevoked.g.cs create mode 100644 Gatekeeper/Gatekeeper.Api/Generated/GetUserByEmail.g.cs create mode 100644 Gatekeeper/Gatekeeper.Api/Generated/GetUserById.g.cs create mode 100644 Gatekeeper/Gatekeeper.Api/Generated/GetUserCredentials.g.cs create mode 100644 Gatekeeper/Gatekeeper.Api/Generated/GetUserPermissions.g.cs create mode 100644 Gatekeeper/Gatekeeper.Api/Generated/GetUserRoles.g.cs create mode 100644 Gatekeeper/Gatekeeper.Api/Generated/RevokeSession.g.cs create mode 100644 Gatekeeper/Gatekeeper.Api/Generated/gk_challengeOperations.g.cs create mode 100644 Gatekeeper/Gatekeeper.Api/Generated/gk_credentialOperations.g.cs create mode 100644 Gatekeeper/Gatekeeper.Api/Generated/gk_permissionOperations.g.cs create mode 100644 Gatekeeper/Gatekeeper.Api/Generated/gk_resource_grantOperations.g.cs create mode 100644 Gatekeeper/Gatekeeper.Api/Generated/gk_roleOperations.g.cs create mode 100644 Gatekeeper/Gatekeeper.Api/Generated/gk_role_permissionOperations.g.cs create mode 100644 Gatekeeper/Gatekeeper.Api/Generated/gk_sessionOperations.g.cs create mode 100644 Gatekeeper/Gatekeeper.Api/Generated/gk_userOperations.g.cs create mode 100644 Gatekeeper/Gatekeeper.Api/Generated/gk_user_roleOperations.g.cs create mode 100644 Gatekeeper/Gatekeeper.Api/GlobalUsings.cs create mode 100644 Gatekeeper/Gatekeeper.Api/Program.cs create mode 100644 Gatekeeper/Gatekeeper.Api/Properties/launchSettings.json create mode 100644 Gatekeeper/Gatekeeper.Api/Sql/CheckPermission.sql create mode 100644 Gatekeeper/Gatekeeper.Api/Sql/CheckResourceGrant.sql create mode 100644 Gatekeeper/Gatekeeper.Api/Sql/CountSystemRoles.sql create mode 100644 Gatekeeper/Gatekeeper.Api/Sql/GetActivePolicies.sql create mode 100644 Gatekeeper/Gatekeeper.Api/Sql/GetAllPermissions.sql create mode 100644 Gatekeeper/Gatekeeper.Api/Sql/GetAllRoles.sql create mode 100644 Gatekeeper/Gatekeeper.Api/Sql/GetAllUsers.sql create mode 100644 Gatekeeper/Gatekeeper.Api/Sql/GetChallengeById.sql create mode 100644 Gatekeeper/Gatekeeper.Api/Sql/GetCredentialById.sql create mode 100644 Gatekeeper/Gatekeeper.Api/Sql/GetCredentialsByUserId.sql create mode 100644 Gatekeeper/Gatekeeper.Api/Sql/GetPermissionByCode.sql create mode 100644 Gatekeeper/Gatekeeper.Api/Sql/GetRolePermissions.sql create mode 100644 Gatekeeper/Gatekeeper.Api/Sql/GetSessionById.sql create mode 100644 Gatekeeper/Gatekeeper.Api/Sql/GetSessionForRevoke.sql create mode 100644 Gatekeeper/Gatekeeper.Api/Sql/GetSessionRevoked.sql create mode 100644 Gatekeeper/Gatekeeper.Api/Sql/GetUserByEmail.sql create mode 100644 Gatekeeper/Gatekeeper.Api/Sql/GetUserById.sql create mode 100644 Gatekeeper/Gatekeeper.Api/Sql/GetUserCredentials.sql create mode 100644 Gatekeeper/Gatekeeper.Api/Sql/GetUserPermissions.sql create mode 100644 Gatekeeper/Gatekeeper.Api/Sql/GetUserRoles.sql create mode 100644 Gatekeeper/Gatekeeper.Api/Sql/RevokeSession.sql create mode 100644 Gatekeeper/Gatekeeper.Api/TokenService.cs create mode 100644 Gatekeeper/Gatekeeper.Api/gatekeeper-schema.yaml create mode 100644 Gatekeeper/Gatekeeper.Api/gatekeeper.db create mode 100644 Gatekeeper/README.md diff --git a/Gatekeeper/Gatekeeper.Api.Tests/AuthenticationTests.cs b/Gatekeeper/Gatekeeper.Api.Tests/AuthenticationTests.cs new file mode 100644 index 0000000..92da28e --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api.Tests/AuthenticationTests.cs @@ -0,0 +1,306 @@ +namespace Gatekeeper.Api.Tests; + +/// +/// Integration tests for Gatekeeper authentication endpoints. +/// Tests WebAuthn/FIDO2 passkey registration and login flows. +/// +public sealed class AuthenticationTests : IClassFixture +{ + private readonly HttpClient _client; + + public AuthenticationTests(GatekeeperTestFixture fixture) + { + _client = fixture.CreateClient(); + } + + [Fact] + public async Task RegisterBegin_WithValidEmail_ReturnsChallenge() + { + var request = new { Email = "test@example.com", DisplayName = "Test User" }; + + var response = await _client.PostAsJsonAsync("/auth/register/begin", request); + + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + var content = await response.Content.ReadAsStringAsync(); + var doc = JsonDocument.Parse(content); + + Assert.True(doc.RootElement.TryGetProperty("ChallengeId", out var challengeId)); + Assert.False(string.IsNullOrEmpty(challengeId.GetString())); + + // API returns OptionsJson as a JSON string (for JS to parse) + Assert.True(doc.RootElement.TryGetProperty("OptionsJson", out var optionsJson)); + var parsedOptions = JsonDocument.Parse(optionsJson.GetString()!); + Assert.True(parsedOptions.RootElement.TryGetProperty("challenge", out _)); + } + + [Fact] + public async Task RegisterBegin_RequiresResidentKey_ForDiscoverableCredentials() + { + // Registration must require resident keys so login works without email + var request = new { Email = "resident@example.com", DisplayName = "Resident User" }; + + var response = await _client.PostAsJsonAsync("/auth/register/begin", request); + + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + var content = await response.Content.ReadAsStringAsync(); + var doc = JsonDocument.Parse(content); + var optionsJson = doc.RootElement.GetProperty("OptionsJson").GetString()!; + var options = JsonDocument.Parse(optionsJson); + + // Verify authenticatorSelection requires resident key + Assert.True( + options.RootElement.TryGetProperty("authenticatorSelection", out var authSelection) + ); + Assert.True(authSelection.TryGetProperty("residentKey", out var residentKey)); + Assert.Equal("required", residentKey.GetString()); + } + + [Fact] + public async Task RegisterBegin_RequiresUserVerification() + { + // Registration must require user verification for security + var request = new { Email = "verify@example.com", DisplayName = "Verify User" }; + + var response = await _client.PostAsJsonAsync("/auth/register/begin", request); + + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + var content = await response.Content.ReadAsStringAsync(); + var doc = JsonDocument.Parse(content); + var optionsJson = doc.RootElement.GetProperty("OptionsJson").GetString()!; + var options = JsonDocument.Parse(optionsJson); + + var authSelection = options.RootElement.GetProperty("authenticatorSelection"); + Assert.True(authSelection.TryGetProperty("userVerification", out var userVerification)); + Assert.Equal("required", userVerification.GetString()); + } + + [Fact] + public async Task LoginBegin_WithEmptyBody_ReturnsChallenge_ForDiscoverableCredentials() + { + // Discoverable credentials flow: no email needed, browser shows all passkeys + // Server returns challenge with empty allowCredentials + var response = await _client.PostAsJsonAsync("/auth/login/begin", new { }); + + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + var content = await response.Content.ReadAsStringAsync(); + var doc = JsonDocument.Parse(content); + + // Should return a valid challenge + Assert.True(doc.RootElement.TryGetProperty("ChallengeId", out var challengeId)); + Assert.False(string.IsNullOrEmpty(challengeId.GetString())); + + // Verify options structure + Assert.True(doc.RootElement.TryGetProperty("OptionsJson", out var optionsJson)); + var options = JsonDocument.Parse(optionsJson.GetString()!); + Assert.True(options.RootElement.TryGetProperty("challenge", out _)); + + // allowCredentials should be empty for discoverable credentials + Assert.True( + options.RootElement.TryGetProperty("allowCredentials", out var allowCredentials) + ); + Assert.Equal(JsonValueKind.Array, allowCredentials.ValueKind); + Assert.Equal(0, allowCredentials.GetArrayLength()); + } + + [Fact] + public async Task LoginBegin_RequiresUserVerification() + { + // Login must require user verification (Touch ID, Face ID, etc.) + var response = await _client.PostAsJsonAsync("/auth/login/begin", new { }); + + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + var content = await response.Content.ReadAsStringAsync(); + var doc = JsonDocument.Parse(content); + var optionsJson = doc.RootElement.GetProperty("OptionsJson").GetString()!; + var options = JsonDocument.Parse(optionsJson); + + Assert.True( + options.RootElement.TryGetProperty("userVerification", out var userVerification) + ); + Assert.Equal("required", userVerification.GetString()); + } + + [Fact] + public async Task LoginComplete_WithInvalidChallengeId_ReturnsError() + { + // Attempting to complete login with invalid challenge should fail + // The endpoint validates the challenge ID and returns an error + var request = new + { + ChallengeId = "non-existent-challenge-id", + OptionsJson = "{}", + AssertionResponse = new + { + Id = "ZmFrZS1jcmVkZW50aWFsLWlk", // base64url encoded + RawId = "ZmFrZS1jcmVkZW50aWFsLWlk", + Type = "public-key", + Response = new + { + AuthenticatorData = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + ClientDataJson = "eyJ0eXBlIjoid2ViYXV0aG4uZ2V0IiwiY2hhbGxlbmdlIjoiYWFhYSIsIm9yaWdpbiI6Imh0dHA6Ly9sb2NhbGhvc3Q6NTE3MyJ9", + Signature = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + UserHandle = (string?)null, + }, + }, + }; + + var response = await _client.PostAsJsonAsync("/auth/login/complete", request); + + // Should return an error (either BadRequest for validation or Problem for processing) + Assert.True( + response.StatusCode is HttpStatusCode.BadRequest or HttpStatusCode.InternalServerError, + $"Expected error status code but got {response.StatusCode}" + ); + } + + [Fact] + public async Task RegisterComplete_WithInvalidChallengeId_ReturnsError() + { + // Attempting to complete registration with invalid challenge should fail + var request = new + { + ChallengeId = "non-existent-challenge-id", + OptionsJson = "{}", + AttestationResponse = new + { + Id = "ZmFrZS1jcmVkZW50aWFsLWlk", // base64url encoded + RawId = "ZmFrZS1jcmVkZW50aWFsLWlk", + Type = "public-key", + Response = new + { + AttestationObject = "o2NmbXRkbm9uZWdhdHRTdG10oGhhdXRoRGF0YVjE", + ClientDataJson = "eyJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIiwiY2hhbGxlbmdlIjoiYWFhYSIsIm9yaWdpbiI6Imh0dHA6Ly9sb2NhbGhvc3Q6NTE3MyJ9", + }, + }, + }; + + var response = await _client.PostAsJsonAsync("/auth/register/complete", request); + + // Should return an error (either BadRequest for validation or Problem for processing) + Assert.True( + response.StatusCode is HttpStatusCode.BadRequest or HttpStatusCode.InternalServerError, + $"Expected error status code but got {response.StatusCode}" + ); + } + + [Fact] + public async Task Session_WithoutToken_ReturnsUnauthorized() + { + var response = await _client.GetAsync("/auth/session"); + + Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); + } + + [Fact] + public async Task Session_WithInvalidToken_ReturnsUnauthorized() + { + _client.DefaultRequestHeaders.Authorization = + new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", "invalid-token"); + + var response = await _client.GetAsync("/auth/session"); + + Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); + } + + [Fact] + public async Task Logout_WithoutToken_ReturnsUnauthorized() + { + var response = await _client.PostAsync("/auth/logout", null); + + Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); + } +} + +/// +/// Tests for Base64Url encoding used in WebAuthn credential IDs. +/// +public sealed class Base64UrlTests +{ + [Fact] + public void Encode_ProducesUrlSafeOutput() + { + // Standard base64 uses + and /, base64url uses - and _ + var input = new byte[] { 0xfb, 0xff, 0xfe }; // Would produce +//+ in standard base64 + + var result = Base64Url.Encode(input); + + Assert.DoesNotContain("+", result); + Assert.DoesNotContain("/", result); + Assert.DoesNotContain("=", result); + Assert.Contains("-", result); // Should use - instead of + + Assert.Contains("_", result); // Should use _ instead of / + } + + [Fact] + public void Encode_Decode_RoundTrip() + { + var original = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; + + var encoded = Base64Url.Encode(original); + var decoded = Base64Url.Decode(encoded); + + Assert.Equal(original, decoded); + } + + [Fact] + public void Decode_HandlesNoPadding() + { + // base64url typically omits padding + var encoded = "AQIDBA"; // No = padding + + var decoded = Base64Url.Decode(encoded); + + Assert.Equal(new byte[] { 1, 2, 3, 4 }, decoded); + } + + [Fact] + public void Decode_HandlesUrlSafeCharacters() + { + // Test decoding with - and _ (url-safe chars) + var encoded = "-_8"; // base64url for 0xfb, 0xff + + var decoded = Base64Url.Decode(encoded); + + Assert.Equal(new byte[] { 0xfb, 0xff }, decoded); + } + + [Fact] + public void Encode_MatchesWebAuthnCredentialIdFormat() + { + // WebAuthn credential IDs use base64url encoding + // This test verifies our encoding matches the expected format + var credentialId = new byte[] + { + 0x01, + 0x02, + 0x03, + 0x04, + 0x05, + 0x06, + 0x07, + 0x08, + 0x09, + 0x0a, + 0x0b, + 0x0c, + 0x0d, + 0x0e, + 0x0f, + 0x10, + }; + + var encoded = Base64Url.Encode(credentialId); + + // Should be AQIDBAUGBwgJCgsMDQ4PEA (no padding) + Assert.Equal("AQIDBAUGBwgJCgsMDQ4PEA", encoded); + + // Verify round-trip + var decoded = Base64Url.Decode(encoded); + Assert.Equal(credentialId, decoded); + } +} diff --git a/Gatekeeper/Gatekeeper.Api.Tests/AuthorizationTests.cs b/Gatekeeper/Gatekeeper.Api.Tests/AuthorizationTests.cs new file mode 100644 index 0000000..aac8f2e --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api.Tests/AuthorizationTests.cs @@ -0,0 +1,646 @@ +using System.Globalization; +using Npgsql; +using Outcome; + +namespace Gatekeeper.Api.Tests; + +/// +/// Integration tests for Gatekeeper authorization endpoints. +/// Tests RBAC permission checks, resource grants, and bulk evaluation. +/// +public sealed class AuthorizationTests : IClassFixture +{ + private readonly GatekeeperTestFixture _fixture; + + public AuthorizationTests(GatekeeperTestFixture fixture) => _fixture = fixture; + + [Fact] + public async Task Check_WithoutToken_ReturnsUnauthorized() + { + var client = _fixture.CreateClient(); + + var response = await client.GetAsync("/authz/check?permission=test:read"); + + Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); + } + + [Fact] + public async Task Check_WithInvalidToken_ReturnsUnauthorized() + { + var client = _fixture.CreateClient(); + client.DefaultRequestHeaders.Authorization = + new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", "invalid-token"); + + var response = await client.GetAsync("/authz/check?permission=test:read"); + + Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); + } + + [Fact] + public async Task Check_WithValidToken_UserHasDefaultPermissions_ReturnsAllowed() + { + var client = _fixture.CreateClient(); + var token = await _fixture.CreateTestUserAndGetToken("authz-user-1@example.com"); + client.DefaultRequestHeaders.Authorization = + new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token); + + // Debug: Check what's in the database using DataProvider extensions + using var conn = _fixture.OpenConnection(); + var rolePermsResult = await conn.GetRolePermissionsAsync("role-user"); + var rolePerms = rolePermsResult switch + { + GetRolePermissionsOk ok => ok.Value.Select(p => $"role-user->{p.code}").ToList(), + GetRolePermissionsError err => [$"(error: {err.Value.Message})"], + }; + + // Default 'user' role has 'user:profile' permission + var response = await client.GetAsync("/authz/check?permission=user:profile"); + + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + var content = await response.Content.ReadAsStringAsync(); + var doc = JsonDocument.Parse(content); + Assert.True( + doc.RootElement.GetProperty("Allowed").GetBoolean(), + $"Response: {content}, RolePerms: [{string.Join(", ", rolePerms)}]" + ); + Assert.Contains("user:profile", doc.RootElement.GetProperty("Reason").GetString()); + } + + [Fact] + public async Task Check_WithValidToken_UserLacksPermission_ReturnsDenied() + { + var client = _fixture.CreateClient(); + var token = await _fixture.CreateTestUserAndGetToken("authz-user-2@example.com"); + client.DefaultRequestHeaders.Authorization = + new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token); + + // Default 'user' role does NOT have 'admin:users' permission + var response = await client.GetAsync("/authz/check?permission=admin:users"); + + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + var content = await response.Content.ReadAsStringAsync(); + var doc = JsonDocument.Parse(content); + Assert.False(doc.RootElement.GetProperty("Allowed").GetBoolean()); + Assert.Equal("no matching permission", doc.RootElement.GetProperty("Reason").GetString()); + } + + [Fact] + public async Task Check_AdminWildcardPermission_MatchesSubPermissions() + { + var client = _fixture.CreateClient(); + var token = await _fixture.CreateAdminUserAndGetToken("admin-wildcard@example.com"); + client.DefaultRequestHeaders.Authorization = + new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token); + + // Admin role has 'admin:*' which should match 'admin:users' + var response = await client.GetAsync("/authz/check?permission=admin:users"); + + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + var content = await response.Content.ReadAsStringAsync(); + var doc = JsonDocument.Parse(content); + Assert.True(doc.RootElement.GetProperty("Allowed").GetBoolean()); + Assert.Contains("admin", doc.RootElement.GetProperty("Reason").GetString()); + } + + [Fact] + public async Task Check_AdminWildcardPermission_MatchesNestedSubPermissions() + { + var client = _fixture.CreateClient(); + var token = await _fixture.CreateAdminUserAndGetToken("admin-nested@example.com"); + client.DefaultRequestHeaders.Authorization = + new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token); + + // Admin role has 'admin:*' which should match 'admin:users:create' + var response = await client.GetAsync("/authz/check?permission=admin:users:create"); + + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + var content = await response.Content.ReadAsStringAsync(); + var doc = JsonDocument.Parse(content); + Assert.True(doc.RootElement.GetProperty("Allowed").GetBoolean()); + } + + [Fact] + public async Task Permissions_WithoutToken_ReturnsUnauthorized() + { + var client = _fixture.CreateClient(); + + var response = await client.GetAsync("/authz/permissions"); + + Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); + } + + [Fact] + public async Task Permissions_WithValidToken_ReturnsUserPermissions() + { + var client = _fixture.CreateClient(); + var token = await _fixture.CreateTestUserAndGetToken("authz-perms@example.com"); + client.DefaultRequestHeaders.Authorization = + new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token); + + var response = await client.GetAsync("/authz/permissions"); + + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + var content = await response.Content.ReadAsStringAsync(); + var doc = JsonDocument.Parse(content); + + Assert.True(doc.RootElement.TryGetProperty("Permissions", out var perms)); + Assert.Equal(JsonValueKind.Array, perms.ValueKind); + + // Default user role has 'user:profile' and 'user:credentials' + var permCodes = perms + .EnumerateArray() + .Select(p => p.GetProperty("code").GetString()) + .ToList(); + Assert.Contains("user:profile", permCodes); + Assert.Contains("user:credentials", permCodes); + } + + [Fact] + public async Task Permissions_AdminUser_ReturnsAdminPermissions() + { + var client = _fixture.CreateClient(); + var token = await _fixture.CreateAdminUserAndGetToken("admin-perms@example.com"); + client.DefaultRequestHeaders.Authorization = + new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token); + + var response = await client.GetAsync("/authz/permissions"); + + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + var content = await response.Content.ReadAsStringAsync(); + var doc = JsonDocument.Parse(content); + + var perms = doc.RootElement.GetProperty("Permissions"); + var permCodes = perms + .EnumerateArray() + .Select(p => p.GetProperty("code").GetString()) + .ToList(); + Assert.Contains("admin:*", permCodes); + } + + [Fact] + public async Task Evaluate_WithoutToken_ReturnsUnauthorized() + { + var client = _fixture.CreateClient(); + + var request = new + { + Checks = new[] + { + new + { + Permission = "test:read", + ResourceType = (string?)null, + ResourceId = (string?)null, + }, + }, + }; + var response = await client.PostAsJsonAsync("/authz/evaluate", request); + + Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); + } + + [Fact] + public async Task Evaluate_WithValidToken_ReturnsBulkResults() + { + var client = _fixture.CreateClient(); + var token = await _fixture.CreateTestUserAndGetToken("authz-eval@example.com"); + client.DefaultRequestHeaders.Authorization = + new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token); + + var request = new + { + Checks = new[] + { + new + { + Permission = "user:profile", + ResourceType = (string?)null, + ResourceId = (string?)null, + }, + new + { + Permission = "admin:users", + ResourceType = (string?)null, + ResourceId = (string?)null, + }, + new + { + Permission = "user:credentials", + ResourceType = (string?)null, + ResourceId = (string?)null, + }, + }, + }; + + var response = await client.PostAsJsonAsync("/authz/evaluate", request); + + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + var content = await response.Content.ReadAsStringAsync(); + var doc = JsonDocument.Parse(content); + + Assert.True(doc.RootElement.TryGetProperty("Results", out var results)); + Assert.Equal(3, results.GetArrayLength()); + + var resultsList = results.EnumerateArray().ToList(); + + // user:profile - allowed + Assert.True(resultsList[0].GetProperty("Allowed").GetBoolean()); + + // admin:users - denied + Assert.False(resultsList[1].GetProperty("Allowed").GetBoolean()); + + // user:credentials - allowed + Assert.True(resultsList[2].GetProperty("Allowed").GetBoolean()); + } + + [Fact] + public async Task Evaluate_EmptyChecks_ReturnsEmptyResults() + { + var client = _fixture.CreateClient(); + var token = await _fixture.CreateTestUserAndGetToken("authz-empty@example.com"); + client.DefaultRequestHeaders.Authorization = + new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token); + + var request = new { Checks = Array.Empty() }; + + var response = await client.PostAsJsonAsync("/authz/evaluate", request); + + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + var content = await response.Content.ReadAsStringAsync(); + var doc = JsonDocument.Parse(content); + + Assert.True(doc.RootElement.TryGetProperty("Results", out var results)); + Assert.Equal(0, results.GetArrayLength()); + } + + [Fact] + public async Task Check_WithResourceGrant_AllowsAccessToSpecificResource() + { + var client = _fixture.CreateClient(); + var (token, userId) = await _fixture.CreateTestUserAndGetTokenWithId( + "resource-grant@example.com" + ); + client.DefaultRequestHeaders.Authorization = + new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token); + + // Grant access to a specific patient record + await _fixture.GrantResourceAccess(userId, "patient", "patient-123", "patient:read"); + + var response = await client.GetAsync( + "/authz/check?permission=patient:read&resourceType=patient&resourceId=patient-123" + ); + + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + var content = await response.Content.ReadAsStringAsync(); + var doc = JsonDocument.Parse(content); + Assert.True(doc.RootElement.GetProperty("Allowed").GetBoolean()); + Assert.Contains("resource-grant", doc.RootElement.GetProperty("Reason").GetString()); + } + + [Fact] + public async Task Check_WithResourceGrant_DeniesAccessToDifferentResource() + { + var client = _fixture.CreateClient(); + var (token, userId) = await _fixture.CreateTestUserAndGetTokenWithId( + "resource-deny@example.com" + ); + client.DefaultRequestHeaders.Authorization = + new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token); + + // Grant access only to patient-123 + await _fixture.GrantResourceAccess(userId, "patient", "patient-123", "patient:read"); + + // Check access to patient-456 (should be denied) + var response = await client.GetAsync( + "/authz/check?permission=patient:read&resourceType=patient&resourceId=patient-456" + ); + + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + var content = await response.Content.ReadAsStringAsync(); + var doc = JsonDocument.Parse(content); + Assert.False(doc.RootElement.GetProperty("Allowed").GetBoolean()); + } + + [Fact] + public async Task Check_WithExpiredResourceGrant_DeniesAccess() + { + var client = _fixture.CreateClient(); + var (token, userId) = await _fixture.CreateTestUserAndGetTokenWithId( + "expired-grant@example.com" + ); + client.DefaultRequestHeaders.Authorization = + new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token); + + // Grant access that's already expired + await _fixture.GrantResourceAccessExpired(userId, "order", "order-999", "order:read"); + + var response = await client.GetAsync( + "/authz/check?permission=order:read&resourceType=order&resourceId=order-999" + ); + + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + var content = await response.Content.ReadAsStringAsync(); + var doc = JsonDocument.Parse(content); + Assert.False(doc.RootElement.GetProperty("Allowed").GetBoolean()); + } +} + +/// +/// Test fixture providing shared setup for Gatekeeper tests. +/// Creates test users and tokens without WebAuthn ceremony. +/// Uses PostgreSQL test database. +/// +public sealed class GatekeeperTestFixture : IDisposable +{ + private readonly WebApplicationFactory _factory; + private readonly byte[] _signingKey; + private readonly string _dbName; + private readonly string _connectionString; + + public GatekeeperTestFixture() + { + var baseConnectionString = + Environment.GetEnvironmentVariable("TEST_POSTGRES_CONNECTION") + ?? "Host=localhost;Database=postgres;Username=postgres;Password=changeme"; + + _dbName = $"test_gatekeeper_{Guid.NewGuid():N}"; + _signingKey = new byte[32]; + + // Create test database + using (var adminConn = new NpgsqlConnection(baseConnectionString)) + { + adminConn.Open(); + using var createCmd = adminConn.CreateCommand(); + createCmd.CommandText = $"CREATE DATABASE {_dbName}"; + createCmd.ExecuteNonQuery(); + } + + // Build connection string for test database + _connectionString = baseConnectionString.Replace( + "Database=postgres", + $"Database={_dbName}" + ); + + _factory = new WebApplicationFactory().WithWebHostBuilder(builder => + { + builder.UseSetting("ConnectionStrings:Postgres", _connectionString); + builder.UseSetting("Jwt:SigningKey", Convert.ToBase64String(_signingKey)); + }); + + // Initialize database by making HTTP requests through the factory + // This ensures the app creates and seeds the database before we access it directly + using var client = _factory.CreateClient(); + // Make a request that forces full app initialization + _ = client.PostAsJsonAsync("/auth/login/begin", new { }).GetAwaiter().GetResult(); + } + + /// Creates a fresh HTTP client for testing. + public HttpClient CreateClient() => _factory.CreateClient(); + + /// Opens a database connection for direct data access. + public NpgsqlConnection OpenConnection() + { + var conn = new NpgsqlConnection(_connectionString); + conn.Open(); + return conn; + } + + /// + /// Creates a test user and returns a valid JWT token. + /// Bypasses WebAuthn by directly inserting user and generating token. + /// Uses DataProvider generated methods for data access. + /// + public async Task CreateTestUserAndGetToken(string email) + { + var (token, _) = await CreateTestUserAndGetTokenWithId(email).ConfigureAwait(false); + return token; + } + + /// + /// Creates a test user and returns both the token and user ID. + /// Uses DataProvider generated methods for data access. + /// + public async Task<(string Token, string UserId)> CreateTestUserAndGetTokenWithId(string email) + { + using var conn = OpenConnection(); + await using var tx = await conn.BeginTransactionAsync().ConfigureAwait(false); + + var userId = Guid.NewGuid().ToString(); + var now = DateTime.UtcNow.ToString("o", CultureInfo.InvariantCulture); + + // Insert user using DataProvider generated method + await tx.Insertgk_userAsync( + userId, + "Test User", + email, + now, + null, // last_login_at + true, // is_active + null // metadata + ) + .ConfigureAwait(false); + + // Link user to role using DataProvider generated method + await tx.Insertgk_user_roleAsync( + userId, + "role-user", + now, + null, // granted_by + null // expires_at + ) + .ConfigureAwait(false); + + await tx.CommitAsync().ConfigureAwait(false); + + var token = TokenService.CreateToken( + userId, + "Test User", + email, + ["user"], + _signingKey, + TimeSpan.FromHours(1) + ); + + return (token, userId); + } + + /// + /// Creates an admin user and returns a valid JWT token. + /// Uses DataProvider generated methods for data access. + /// + public async Task CreateAdminUserAndGetToken(string email) + { + using var conn = OpenConnection(); + await using var tx = await conn.BeginTransactionAsync().ConfigureAwait(false); + + var userId = Guid.NewGuid().ToString(); + var now = DateTime.UtcNow.ToString("o", CultureInfo.InvariantCulture); + + // Insert user using DataProvider generated method + await tx.Insertgk_userAsync( + userId, + "Admin User", + email, + now, + null, // last_login_at + true, // is_active + null // metadata + ) + .ConfigureAwait(false); + + // Link user to admin role using DataProvider generated method + await tx.Insertgk_user_roleAsync( + userId, + "role-admin", + now, + null, // granted_by + null // expires_at + ) + .ConfigureAwait(false); + + await tx.CommitAsync().ConfigureAwait(false); + + var token = TokenService.CreateToken( + userId, + "Admin User", + email, + ["admin"], + _signingKey, + TimeSpan.FromHours(1) + ); + + return token; + } + + /// + /// Grants resource-level access to a user. + /// Uses DataProvider generated methods for data access. + /// + public async Task GrantResourceAccess( + string userId, + string resourceType, + string resourceId, + string permissionCode + ) + { + using var conn = OpenConnection(); + + // Look up existing permission by code BEFORE starting transaction + var permLookupResult = await conn.GetPermissionByCodeAsync(permissionCode) + .ConfigureAwait(false); + var existingPerm = permLookupResult switch + { + GetPermissionByCodeOk ok => ok.Value.FirstOrDefault(), + GetPermissionByCodeError err => throw new InvalidOperationException( + $"Permission lookup failed: {err.Value.Message}, Exception: {err.Value.InnerException?.Message}" + ), + }; + + var permId = + existingPerm?.id + ?? throw new InvalidOperationException( + $"Permission '{permissionCode}' not found in seeded database" + ); + + await using var tx = await conn.BeginTransactionAsync().ConfigureAwait(false); + var now = DateTime.UtcNow.ToString("o", CultureInfo.InvariantCulture); + var grantId = Guid.NewGuid().ToString(); + + // Grant access using DataProvider generated method + var grantResult = await tx.Insertgk_resource_grantAsync( + grantId, + userId, + resourceType, + resourceId, + permId, + now, + null, // granted_by + null // expires_at + ) + .ConfigureAwait(false); + + if (grantResult is Result.Error grantErr) + { + throw new InvalidOperationException( + $"Failed to insert grant: {grantErr.Value.Message}" + ); + } + + await tx.CommitAsync().ConfigureAwait(false); + } + + /// + /// Grants resource-level access that has already expired. + /// Uses DataProvider generated methods for data access. + /// + public async Task GrantResourceAccessExpired( + string userId, + string resourceType, + string resourceId, + string permissionCode + ) + { + using var conn = OpenConnection(); + + // Look up existing permission by code BEFORE starting transaction + var permLookupResult = await conn.GetPermissionByCodeAsync(permissionCode) + .ConfigureAwait(false); + var existingPerm = permLookupResult switch + { + GetPermissionByCodeOk ok => ok.Value.FirstOrDefault(), + GetPermissionByCodeError err => throw new InvalidOperationException( + $"Permission lookup failed: {err.Value.Message}" + ), + }; + + var permId = + existingPerm?.id + ?? throw new InvalidOperationException( + $"Permission '{permissionCode}' not found in seeded database" + ); + + await using var tx = await conn.BeginTransactionAsync().ConfigureAwait(false); + var now = DateTime.UtcNow.ToString("o", CultureInfo.InvariantCulture); + var expired = DateTime.UtcNow.AddHours(-1).ToString("o", CultureInfo.InvariantCulture); + var grantId = Guid.NewGuid().ToString(); + + // Grant access with expired timestamp using DataProvider generated method + await tx.Insertgk_resource_grantAsync( + grantId, + userId, + resourceType, + resourceId, + permId, + now, + null, // granted_by + expired // expires_at + ) + .ConfigureAwait(false); + + await tx.CommitAsync().ConfigureAwait(false); + } + + /// Disposes the test fixture and cleans up test database. + public void Dispose() + { + _factory.Dispose(); + + var baseConnectionString = + Environment.GetEnvironmentVariable("TEST_POSTGRES_CONNECTION") + ?? "Host=localhost;Database=postgres;Username=postgres;Password=changeme"; + + // Drop the test database + using var adminConn = new NpgsqlConnection(baseConnectionString); + adminConn.Open(); + + // Terminate any existing connections to the database + using var terminateCmd = adminConn.CreateCommand(); + terminateCmd.CommandText = + $"SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = '{_dbName}'"; + terminateCmd.ExecuteNonQuery(); + + using var dropCmd = adminConn.CreateCommand(); + dropCmd.CommandText = $"DROP DATABASE IF EXISTS {_dbName}"; + dropCmd.ExecuteNonQuery(); + } +} diff --git a/Gatekeeper/Gatekeeper.Api.Tests/Gatekeeper.Api.Tests.csproj b/Gatekeeper/Gatekeeper.Api.Tests/Gatekeeper.Api.Tests.csproj new file mode 100644 index 0000000..45a54eb --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api.Tests/Gatekeeper.Api.Tests.csproj @@ -0,0 +1,35 @@ + + + Library + true + Gatekeeper.Api.Tests + CS1591;CA1707;CA1307;CA1062;CA1515;CA2100;CA1822;CA1859;CA1849;CA2234;CA1812;CA2007;CA2000;xUnit1030 + + + + + + + all + runtime; build; native; contentfiles; analyzers + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + + PreserveNewest + + + diff --git a/Gatekeeper/Gatekeeper.Api.Tests/GlobalUsings.cs b/Gatekeeper/Gatekeeper.Api.Tests/GlobalUsings.cs new file mode 100644 index 0000000..90439cd --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api.Tests/GlobalUsings.cs @@ -0,0 +1,36 @@ +#pragma warning disable IDE0005 // Using directive is unnecessary + +global using System.Net; +global using System.Net.Http.Json; +global using System.Text.Json; +global using Generated; +global using Microsoft.AspNetCore.Mvc.Testing; +global using Selecta; +global using Xunit; +global using GetPermissionByCodeError = Outcome.Result< + System.Collections.Immutable.ImmutableList, + Selecta.SqlError +>.Error< + System.Collections.Immutable.ImmutableList, + Selecta.SqlError +>; +global using GetPermissionByCodeOk = Outcome.Result< + System.Collections.Immutable.ImmutableList, + Selecta.SqlError +>.Ok, Selecta.SqlError>; +global using GetRolePermissionsError = Outcome.Result< + System.Collections.Immutable.ImmutableList, + Selecta.SqlError +>.Error, Selecta.SqlError>; +global using GetRolePermissionsOk = Outcome.Result< + System.Collections.Immutable.ImmutableList, + Selecta.SqlError +>.Ok, Selecta.SqlError>; +global using GetSessionRevokedError = Outcome.Result< + System.Collections.Immutable.ImmutableList, + Selecta.SqlError +>.Error, Selecta.SqlError>; +global using GetSessionRevokedOk = Outcome.Result< + System.Collections.Immutable.ImmutableList, + Selecta.SqlError +>.Ok, Selecta.SqlError>; diff --git a/Gatekeeper/Gatekeeper.Api.Tests/TokenServiceTests.cs b/Gatekeeper/Gatekeeper.Api.Tests/TokenServiceTests.cs new file mode 100644 index 0000000..29c7ea1 --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api.Tests/TokenServiceTests.cs @@ -0,0 +1,597 @@ +using System.Globalization; +using Nimblesite.DataProvider.Migration.Core; +using Nimblesite.DataProvider.Migration.Postgres; +using Npgsql; + +namespace Gatekeeper.Api.Tests; + +/// +/// Unit tests for TokenService JWT creation, validation, and revocation. +/// +public sealed class TokenServiceTests +{ + private static readonly byte[] TestSigningKey = new byte[32]; + + [Fact] + public void CreateToken_ReturnsValidJwtFormat() + { + var token = TokenService.CreateToken( + "user-123", + "Test User", + "test@example.com", + ["user", "admin"], + TestSigningKey, + TimeSpan.FromHours(1) + ); + + // JWT has 3 parts separated by dots + var parts = token.Split('.'); + Assert.Equal(3, parts.Length); + + // All parts should be base64url encoded (no padding) + Assert.DoesNotContain("=", parts[0]); + Assert.DoesNotContain("=", parts[1]); + Assert.DoesNotContain("=", parts[2]); + } + + [Fact] + public void CreateToken_HeaderContainsCorrectAlgorithm() + { + var token = TokenService.CreateToken( + "user-123", + "Test User", + "test@example.com", + ["user"], + TestSigningKey, + TimeSpan.FromHours(1) + ); + + var parts = token.Split('.'); + var headerJson = Base64UrlDecode(parts[0]); + var header = JsonDocument.Parse(headerJson); + + Assert.Equal("HS256", header.RootElement.GetProperty("alg").GetString()); + Assert.Equal("JWT", header.RootElement.GetProperty("typ").GetString()); + } + + [Fact] + public void CreateToken_PayloadContainsAllClaims() + { + var token = TokenService.CreateToken( + "user-456", + "Jane Doe", + "jane@example.com", + ["admin", "manager"], + TestSigningKey, + TimeSpan.FromHours(2) + ); + + var parts = token.Split('.'); + var payloadJson = Base64UrlDecode(parts[1]); + var payload = JsonDocument.Parse(payloadJson); + + Assert.Equal("user-456", payload.RootElement.GetProperty("sub").GetString()); + Assert.Equal("Jane Doe", payload.RootElement.GetProperty("name").GetString()); + Assert.Equal("jane@example.com", payload.RootElement.GetProperty("email").GetString()); + + var roles = payload + .RootElement.GetProperty("roles") + .EnumerateArray() + .Select(e => e.GetString()) + .ToList(); + Assert.Contains("admin", roles); + Assert.Contains("manager", roles); + + Assert.True(payload.RootElement.TryGetProperty("jti", out var jti)); + Assert.False(string.IsNullOrEmpty(jti.GetString())); + + Assert.True(payload.RootElement.TryGetProperty("iat", out _)); + Assert.True(payload.RootElement.TryGetProperty("exp", out _)); + } + + [Fact] + public void CreateToken_ExpirationIsCorrect() + { + var beforeCreate = DateTimeOffset.UtcNow; + + var token = TokenService.CreateToken( + "user-789", + "Test", + "test@example.com", + [], + TestSigningKey, + TimeSpan.FromMinutes(30) + ); + + var parts = token.Split('.'); + var payloadJson = Base64UrlDecode(parts[1]); + var payload = JsonDocument.Parse(payloadJson); + + var exp = payload.RootElement.GetProperty("exp").GetInt64(); + var iat = payload.RootElement.GetProperty("iat").GetInt64(); + var expTime = DateTimeOffset.FromUnixTimeSeconds(exp); + var iatTime = DateTimeOffset.FromUnixTimeSeconds(iat); + + // exp should be ~30 minutes after iat + var diff = expTime - iatTime; + Assert.True(diff.TotalMinutes >= 29 && diff.TotalMinutes <= 31); + + // exp should be ~30 minutes from now + var expFromNow = expTime - beforeCreate; + Assert.True(expFromNow.TotalMinutes >= 29 && expFromNow.TotalMinutes <= 31); + } + + [Fact] + public async Task ValidateTokenAsync_ValidToken_ReturnsOk() + { + var (conn, dbPath) = CreateTestDb(); + try + { + var token = TokenService.CreateToken( + "user-valid", + "Valid User", + "valid@example.com", + ["user"], + TestSigningKey, + TimeSpan.FromHours(1) + ); + + var result = await TokenService.ValidateTokenAsync( + conn, + token, + TestSigningKey, + checkRevocation: false + ); + + Assert.IsType(result); + var ok = (TokenService.TokenValidationOk)result; + Assert.Equal("user-valid", ok.Claims.UserId); + Assert.Equal("Valid User", ok.Claims.DisplayName); + Assert.Equal("valid@example.com", ok.Claims.Email); + Assert.Contains("user", ok.Claims.Roles); + } + finally + { + CleanupTestDb(conn, dbPath); + } + } + + [Fact] + public async Task ValidateTokenAsync_InvalidFormat_ReturnsError() + { + var (conn, dbPath) = CreateTestDb(); + try + { + var result = await TokenService.ValidateTokenAsync( + conn, + "not-a-jwt", + TestSigningKey, + checkRevocation: false + ); + + Assert.IsType(result); + var error = (TokenService.TokenValidationError)result; + Assert.Equal("Invalid token format", error.Reason); + } + finally + { + CleanupTestDb(conn, dbPath); + } + } + + [Fact] + public async Task ValidateTokenAsync_TwoPartToken_ReturnsError() + { + var (conn, dbPath) = CreateTestDb(); + try + { + var result = await TokenService.ValidateTokenAsync( + conn, + "header.payload", + TestSigningKey, + checkRevocation: false + ); + + Assert.IsType(result); + var error = (TokenService.TokenValidationError)result; + Assert.Equal("Invalid token format", error.Reason); + } + finally + { + CleanupTestDb(conn, dbPath); + } + } + + [Fact] + public async Task ValidateTokenAsync_InvalidSignature_ReturnsError() + { + var (conn, dbPath) = CreateTestDb(); + try + { + var token = TokenService.CreateToken( + "user-sig", + "Sig User", + "sig@example.com", + [], + TestSigningKey, + TimeSpan.FromHours(1) + ); + + // Use different key for validation + var differentKey = new byte[32]; + differentKey[0] = 0xFF; + + var result = await TokenService.ValidateTokenAsync( + conn, + token, + differentKey, + checkRevocation: false + ); + + Assert.IsType(result); + var error = (TokenService.TokenValidationError)result; + Assert.Equal("Invalid signature", error.Reason); + } + finally + { + CleanupTestDb(conn, dbPath); + } + } + + [Fact] + public async Task ValidateTokenAsync_ExpiredToken_ReturnsError() + { + var (conn, dbPath) = CreateTestDb(); + try + { + // Create token that expired 1 hour ago + var token = TokenService.CreateToken( + "user-expired", + "Expired User", + "expired@example.com", + [], + TestSigningKey, + TimeSpan.FromHours(-2) // Negative = already expired + ); + + var result = await TokenService.ValidateTokenAsync( + conn, + token, + TestSigningKey, + checkRevocation: false + ); + + Assert.IsType(result); + var error = (TokenService.TokenValidationError)result; + Assert.Equal("Token expired", error.Reason); + } + finally + { + CleanupTestDb(conn, dbPath); + } + } + + [Fact] + public async Task ValidateTokenAsync_RevokedToken_ReturnsError() + { + var (conn, dbPath) = CreateTestDb(); + try + { + var token = TokenService.CreateToken( + "user-revoked", + "Revoked User", + "revoked@example.com", + [], + TestSigningKey, + TimeSpan.FromHours(1) + ); + + // Extract JTI and revoke + var parts = token.Split('.'); + var payloadJson = Base64UrlDecode(parts[1]); + var payload = JsonDocument.Parse(payloadJson); + var jti = payload.RootElement.GetProperty("jti").GetString()!; + + var now = DateTime.UtcNow.ToString("o", CultureInfo.InvariantCulture); + var exp = DateTime.UtcNow.AddHours(1).ToString("o", CultureInfo.InvariantCulture); + + // Insert user and revoked session using raw SQL (consistent with other tests) + using var tx = conn.BeginTransaction(); + + using var userCmd = conn.CreateCommand(); + userCmd.Transaction = tx; + userCmd.CommandText = + @"INSERT INTO gk_user (id, display_name, email, created_at, last_login_at, is_active, metadata) + VALUES (@id, @name, @email, @now, NULL, true, NULL)"; + userCmd.Parameters.AddWithValue("@id", "user-revoked"); + userCmd.Parameters.AddWithValue("@name", "Revoked User"); + userCmd.Parameters.AddWithValue("@email", DBNull.Value); + userCmd.Parameters.AddWithValue("@now", now); + await userCmd.ExecuteNonQueryAsync().ConfigureAwait(false); + + using var sessionCmd = conn.CreateCommand(); + sessionCmd.Transaction = tx; + sessionCmd.CommandText = + @"INSERT INTO gk_session (id, user_id, credential_id, created_at, expires_at, last_activity_at, ip_address, user_agent, is_revoked) + VALUES (@id, @user_id, NULL, @created, @expires, @activity, NULL, NULL, true)"; + sessionCmd.Parameters.AddWithValue("@id", jti); + sessionCmd.Parameters.AddWithValue("@user_id", "user-revoked"); + sessionCmd.Parameters.AddWithValue("@created", now); + sessionCmd.Parameters.AddWithValue("@expires", exp); + sessionCmd.Parameters.AddWithValue("@activity", now); + await sessionCmd.ExecuteNonQueryAsync().ConfigureAwait(false); + + tx.Commit(); + + var result = await TokenService.ValidateTokenAsync( + conn, + token, + TestSigningKey, + checkRevocation: true + ); + + Assert.IsType(result); + var error = (TokenService.TokenValidationError)result; + Assert.Equal("Token revoked", error.Reason); + } + finally + { + CleanupTestDb(conn, dbPath); + } + } + + [Fact] + public async Task ValidateTokenAsync_RevokedToken_IgnoredWhenCheckRevocationFalse() + { + var (conn, dbPath) = CreateTestDb(); + try + { + var token = TokenService.CreateToken( + "user-revoked2", + "Revoked User 2", + "revoked2@example.com", + [], + TestSigningKey, + TimeSpan.FromHours(1) + ); + + // Extract JTI and revoke + var parts = token.Split('.'); + var payloadJson = Base64UrlDecode(parts[1]); + var payload = JsonDocument.Parse(payloadJson); + var jti = payload.RootElement.GetProperty("jti").GetString()!; + + var now = DateTime.UtcNow.ToString("o", CultureInfo.InvariantCulture); + var exp = DateTime.UtcNow.AddHours(1).ToString("o", CultureInfo.InvariantCulture); + + // Insert user and revoked session using raw SQL (consistent with other tests) + using var tx = conn.BeginTransaction(); + + using var userCmd = conn.CreateCommand(); + userCmd.Transaction = tx; + userCmd.CommandText = + @"INSERT INTO gk_user (id, display_name, email, created_at, last_login_at, is_active, metadata) + VALUES (@id, @name, @email, @now, NULL, true, NULL)"; + userCmd.Parameters.AddWithValue("@id", "user-revoked2"); + userCmd.Parameters.AddWithValue("@name", "Revoked User 2"); + userCmd.Parameters.AddWithValue("@email", DBNull.Value); + userCmd.Parameters.AddWithValue("@now", now); + await userCmd.ExecuteNonQueryAsync().ConfigureAwait(false); + + using var sessionCmd = conn.CreateCommand(); + sessionCmd.Transaction = tx; + sessionCmd.CommandText = + @"INSERT INTO gk_session (id, user_id, credential_id, created_at, expires_at, last_activity_at, ip_address, user_agent, is_revoked) + VALUES (@id, @user_id, NULL, @created, @expires, @activity, NULL, NULL, true)"; + sessionCmd.Parameters.AddWithValue("@id", jti); + sessionCmd.Parameters.AddWithValue("@user_id", "user-revoked2"); + sessionCmd.Parameters.AddWithValue("@created", now); + sessionCmd.Parameters.AddWithValue("@expires", exp); + sessionCmd.Parameters.AddWithValue("@activity", now); + await sessionCmd.ExecuteNonQueryAsync().ConfigureAwait(false); + + tx.Commit(); + + // With checkRevocation: false, should still validate + var result = await TokenService.ValidateTokenAsync( + conn, + token, + TestSigningKey, + checkRevocation: false + ); + + Assert.IsType(result); + } + finally + { + CleanupTestDb(conn, dbPath); + } + } + + [Fact] + public async Task RevokeTokenAsync_SetsIsRevokedFlag() + { + var (conn, dbPath) = CreateTestDb(); + try + { + var jti = Guid.NewGuid().ToString(); + var userId = "user-test"; + var now = DateTime.UtcNow.ToString("o", CultureInfo.InvariantCulture); + var exp = DateTime.UtcNow.AddHours(1).ToString("o", CultureInfo.InvariantCulture); + + // Insert user and session using raw SQL (TEXT PK doesn't return rowid) + using var tx = conn.BeginTransaction(); + + using var userCmd = conn.CreateCommand(); + userCmd.Transaction = tx; + userCmd.CommandText = + @"INSERT INTO gk_user (id, display_name, email, created_at, last_login_at, is_active, metadata) + VALUES (@id, @name, @email, @now, NULL, true, NULL)"; + userCmd.Parameters.AddWithValue("@id", userId); + userCmd.Parameters.AddWithValue("@name", "Test User"); + userCmd.Parameters.AddWithValue("@email", DBNull.Value); + userCmd.Parameters.AddWithValue("@now", now); + await userCmd.ExecuteNonQueryAsync().ConfigureAwait(false); + + using var sessionCmd = conn.CreateCommand(); + sessionCmd.Transaction = tx; + sessionCmd.CommandText = + @"INSERT INTO gk_session (id, user_id, credential_id, created_at, expires_at, last_activity_at, ip_address, user_agent, is_revoked) + VALUES (@id, @user_id, NULL, @created, @expires, @activity, NULL, NULL, false)"; + sessionCmd.Parameters.AddWithValue("@id", jti); + sessionCmd.Parameters.AddWithValue("@user_id", userId); + sessionCmd.Parameters.AddWithValue("@created", now); + sessionCmd.Parameters.AddWithValue("@expires", exp); + sessionCmd.Parameters.AddWithValue("@activity", now); + await sessionCmd.ExecuteNonQueryAsync().ConfigureAwait(false); + + tx.Commit(); + + // Revoke + await TokenService.RevokeTokenAsync(conn, jti); + + // Verify using DataProvider generated method + var revokedResult = await conn.GetSessionRevokedAsync(jti); + var isRevoked = revokedResult switch + { + GetSessionRevokedOk ok => ok.Value.FirstOrDefault()?.is_revoked ?? false, + GetSessionRevokedError err => throw new InvalidOperationException( + $"GetSessionRevoked failed: {err.Value.Message}, {err.Value.InnerException?.Message}" + ), + }; + + Assert.True(isRevoked); + } + finally + { + CleanupTestDb(conn, dbPath); + } + } + + [Fact] + public void ExtractBearerToken_ValidHeader_ReturnsToken() + { + var token = TokenService.ExtractBearerToken("Bearer abc123xyz"); + + Assert.Equal("abc123xyz", token); + } + + [Fact] + public void ExtractBearerToken_NullHeader_ReturnsNull() + { + var token = TokenService.ExtractBearerToken(null); + + Assert.Null(token); + } + + [Fact] + public void ExtractBearerToken_EmptyHeader_ReturnsNull() + { + var token = TokenService.ExtractBearerToken(""); + + Assert.Null(token); + } + + [Fact] + public void ExtractBearerToken_NonBearerScheme_ReturnsNull() + { + var token = TokenService.ExtractBearerToken("Basic abc123xyz"); + + Assert.Null(token); + } + + [Fact] + public void ExtractBearerToken_BearerWithoutSpace_ReturnsNull() + { + var token = TokenService.ExtractBearerToken("Bearerabc123xyz"); + + Assert.Null(token); + } + + private static (NpgsqlConnection Connection, string DbName) CreateTestDb() + { + // Connect to PostgreSQL server - use environment variable or default to localhost + var baseConnectionString = + Environment.GetEnvironmentVariable("TEST_POSTGRES_CONNECTION") + ?? "Host=localhost;Database=postgres;Username=postgres;Password=changeme"; + + var dbName = $"test_tokenservice_{Guid.NewGuid():N}"; + + // Create test database + using (var adminConn = new NpgsqlConnection(baseConnectionString)) + { + adminConn.Open(); + using var createCmd = adminConn.CreateCommand(); + createCmd.CommandText = $"CREATE DATABASE {dbName}"; + createCmd.ExecuteNonQuery(); + } + + // Connect to the new test database + var testConnectionString = baseConnectionString.Replace( + "Database=postgres", + $"Database={dbName}" + ); + var conn = new NpgsqlConnection(testConnectionString); + conn.Open(); + + // Use the YAML schema to create only the needed tables + // gk_credential is needed because gk_session has a FK to it + var yamlPath = Path.Combine(AppContext.BaseDirectory, "gatekeeper-schema.yaml"); + var schema = SchemaYamlSerializer.FromYamlFile(yamlPath); + var neededTables = new[] { "gk_user", "gk_credential", "gk_session" }; + + foreach (var table in schema.Tables.Where(t => neededTables.Contains(t.Name))) + { + var ddl = PostgresDdlGenerator.Generate(new CreateTableOperation(table)); + foreach ( + var statement in ddl.Split( + ';', + StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries + ) + ) + { + if (string.IsNullOrWhiteSpace(statement)) + { + continue; + } + using var cmd = conn.CreateCommand(); + cmd.CommandText = statement; + cmd.ExecuteNonQuery(); + } + } + + return (conn, dbName); + } + + private static void CleanupTestDb(NpgsqlConnection connection, string dbName) + { + var baseConnectionString = + Environment.GetEnvironmentVariable("TEST_POSTGRES_CONNECTION") + ?? "Host=localhost;Database=postgres;Username=postgres;Password=changeme"; + + connection.Close(); + connection.Dispose(); + + // Drop the test database + using var adminConn = new NpgsqlConnection(baseConnectionString); + adminConn.Open(); + + // Terminate any existing connections to the database + using var terminateCmd = adminConn.CreateCommand(); + terminateCmd.CommandText = + $"SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = '{dbName}'"; + terminateCmd.ExecuteNonQuery(); + + using var dropCmd = adminConn.CreateCommand(); + dropCmd.CommandText = $"DROP DATABASE IF EXISTS {dbName}"; + dropCmd.ExecuteNonQuery(); + } + + private static string Base64UrlDecode(string input) + { + var padded = input.Replace("-", "+").Replace("_", "/"); + var padding = (4 - (padded.Length % 4)) % 4; + padded += new string('=', padding); + return System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(padded)); + } +} diff --git a/Gatekeeper/Gatekeeper.Api/AuthorizationService.cs b/Gatekeeper/Gatekeeper.Api/AuthorizationService.cs new file mode 100644 index 0000000..3b3f4f3 --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api/AuthorizationService.cs @@ -0,0 +1,113 @@ +using System.Text; + +namespace Gatekeeper.Api; + +/// +/// Service for evaluating authorization decisions. +/// +public static class AuthorizationService +{ + /// + /// Checks if a user has a specific permission, optionally scoped to a resource. + /// + public static async Task<(bool Allowed, string Reason)> CheckPermissionAsync( + NpgsqlConnection conn, + string userId, + string permissionCode, + string? resourceType, + string? resourceId, + string now + ) + { + // Step 1: Check resource-level grants first (most specific) + if (!string.IsNullOrEmpty(resourceType) && !string.IsNullOrEmpty(resourceId)) + { + var grantResult = await conn.CheckResourceGrantAsync( + now: now, + resource_id: resourceId, + user_id: userId, + resource_type: resourceType, + permission_code: permissionCode + ) + .ConfigureAwait(false); + + if (grantResult is CheckResourceGrantOk grantOk && grantOk.Value.Count > 0) + { + return (true, $"resource-grant:{resourceType}/{resourceId}"); + } + } + + // Step 2: Check user permissions (direct grants and role-based) + var permResult = await conn.GetUserPermissionsAsync(userId, now).ConfigureAwait(false); + var permissions = permResult is GetUserPermissionsOk ok ? ok.Value : []; + + foreach (var perm in permissions) + { + var matches = PermissionMatches(perm.code, permissionCode); + if (!matches) + { + continue; + } + + // Check scope - handle both string and byte[] types from generated code + var scopeType = ToStringValue(perm.scope_type); + var scopeValue = ToStringValue(perm.scope_value); + + var scopeMatches = scopeType switch + { + null or "" or "all" => true, + "record" => scopeValue == resourceId, + _ => false, + }; + + if (scopeMatches) + { + // source_type is role_id for role-based permissions, permission_id for direct grants + // source_name is role name for role-based, permission code for direct + var source = + perm.source_name != perm.code ? $"role:{perm.source_name}" : "direct-grant"; + return (true, $"{source} grants {perm.code}"); + } + } + + return (false, "no matching permission"); + } + + /// + /// Converts a value to string, handling byte[] from SQLite. + /// + private static string? ToStringValue(object? value) => + value switch + { + null => null, + string s => s, + byte[] bytes => Encoding.UTF8.GetString(bytes), + _ => value.ToString(), + }; + + /// + /// Checks if a permission code matches a target, supporting wildcards. + /// + private static bool PermissionMatches(string grantedCode, string targetCode) + { + if (grantedCode == targetCode) + { + return true; + } + + // Handle wildcards like "admin:*" matching "admin:users" + if (grantedCode.EndsWith(":*", StringComparison.Ordinal)) + { + var prefix = grantedCode[..^1]; // Remove "*" + return targetCode.StartsWith(prefix, StringComparison.Ordinal); + } + + // Handle global wildcard + if (grantedCode == "*:*" || grantedCode == "*") + { + return true; + } + + return false; + } +} diff --git a/Gatekeeper/Gatekeeper.Api/DataProvider.json b/Gatekeeper/Gatekeeper.Api/DataProvider.json new file mode 100644 index 0000000..5aa5ad0 --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api/DataProvider.json @@ -0,0 +1,34 @@ +{ + "queries": [ + { "name": "GetUserByEmail", "sqlFile": "Sql/GetUserByEmail.sql" }, + { "name": "GetUserById", "sqlFile": "Sql/GetUserById.sql" }, + { "name": "GetUserCredentials", "sqlFile": "Sql/GetUserCredentials.sql" }, + { "name": "GetCredentialById", "sqlFile": "Sql/GetCredentialById.sql" }, + { "name": "GetSessionById", "sqlFile": "Sql/GetSessionById.sql" }, + { "name": "GetChallengeById", "sqlFile": "Sql/GetChallengeById.sql" }, + { "name": "GetUserRoles", "sqlFile": "Sql/GetUserRoles.sql" }, + { "name": "GetUserPermissions", "sqlFile": "Sql/GetUserPermissions.sql" }, + { "name": "CheckResourceGrant", "sqlFile": "Sql/CheckResourceGrant.sql" }, + { "name": "GetActivePolicies", "sqlFile": "Sql/GetActivePolicies.sql" }, + { "name": "GetAllRoles", "sqlFile": "Sql/GetAllRoles.sql" }, + { "name": "GetAllPermissions", "sqlFile": "Sql/GetAllPermissions.sql" }, + { "name": "GetCredentialsByUserId", "sqlFile": "Sql/GetCredentialsByUserId.sql" }, + { "name": "GetRolePermissions", "sqlFile": "Sql/GetRolePermissions.sql" }, + { "name": "GetAllUsers", "sqlFile": "Sql/GetAllUsers.sql" }, + { "name": "CheckPermission", "sqlFile": "Sql/CheckPermission.sql" }, + { "name": "GetSessionRevoked", "sqlFile": "Sql/GetSessionRevoked.sql" }, + { "name": "GetSessionForRevoke", "sqlFile": "Sql/GetSessionForRevoke.sql" } + ], + "tables": [ + { "schema": "main", "name": "gk_user", "generateInsert": true, "excludeColumns": ["id"], "primaryKeyColumns": ["id"] }, + { "schema": "main", "name": "gk_credential", "generateInsert": true, "excludeColumns": ["id"], "primaryKeyColumns": ["id"] }, + { "schema": "main", "name": "gk_session", "generateInsert": true, "generateUpdate": true, "excludeColumns": ["id"], "primaryKeyColumns": ["id"] }, + { "schema": "main", "name": "gk_challenge", "generateInsert": true, "excludeColumns": ["id"], "primaryKeyColumns": ["id"] }, + { "schema": "main", "name": "gk_user_role", "generateInsert": true, "excludeColumns": [], "primaryKeyColumns": ["user_id", "role_id"] }, + { "schema": "main", "name": "gk_permission", "generateInsert": true, "excludeColumns": ["id"], "primaryKeyColumns": ["id"] }, + { "schema": "main", "name": "gk_resource_grant", "generateInsert": true, "excludeColumns": ["id"], "primaryKeyColumns": ["id"] }, + { "schema": "main", "name": "gk_role", "generateInsert": true, "excludeColumns": ["id"], "primaryKeyColumns": ["id"] }, + { "schema": "main", "name": "gk_role_permission", "generateInsert": true, "excludeColumns": [], "primaryKeyColumns": ["role_id", "permission_id"] } + ], + "connectionString": "Data Source=gatekeeper.db" +} diff --git a/Gatekeeper/Gatekeeper.Api/DatabaseSetup.cs b/Gatekeeper/Gatekeeper.Api/DatabaseSetup.cs new file mode 100644 index 0000000..dde1471 --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api/DatabaseSetup.cs @@ -0,0 +1,148 @@ +using Nimblesite.DataProvider.Migration.Core; +using Nimblesite.DataProvider.Migration.Postgres; +using InitError = Outcome.Result.Error; +using InitOk = Outcome.Result.Ok; +using InitResult = Outcome.Result; + +namespace Gatekeeper.Api; + +/// +/// Database initialization and seeding using Migration library. +/// +internal static class DatabaseSetup +{ + /// + /// Initializes the database schema and seeds default data. + /// + public static InitResult Initialize(NpgsqlConnection conn, ILogger logger) + { + var schemaResult = CreateSchemaFromMigration(conn, logger); + if (schemaResult is InitError) + return schemaResult; + + return SeedDefaultData(conn, logger); + } + + private static InitResult CreateSchemaFromMigration(NpgsqlConnection conn, ILogger logger) + { + logger.LogInformation("Creating database schema from gatekeeper-schema.yaml"); + + try + { + // Load schema from YAML (source of truth) + var yamlPath = Path.Combine(AppContext.BaseDirectory, "gatekeeper-schema.yaml"); + var schema = SchemaYamlSerializer.FromYamlFile(yamlPath); + + foreach (var table in schema.Tables) + { + var ddl = PostgresDdlGenerator.Generate(new CreateTableOperation(table)); + // DDL may contain multiple statements (CREATE TABLE + CREATE INDEX) + foreach ( + var statement in ddl.Split( + ';', + StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries + ) + ) + { + if (string.IsNullOrWhiteSpace(statement)) + { + continue; + } + using var cmd = conn.CreateCommand(); + cmd.CommandText = statement; + cmd.ExecuteNonQuery(); + } + logger.LogDebug("Created table {TableName}", table.Name); + } + + logger.LogInformation("Created Gatekeeper database schema from YAML"); + return new InitOk(true); + } + catch (Exception ex) + { + logger.LogError(ex, "Failed to create Gatekeeper database schema"); + return new InitError($"Failed to create Gatekeeper database schema: {ex.Message}"); + } + } + + private static InitResult SeedDefaultData(NpgsqlConnection conn, ILogger logger) + { + try + { + var now = DateTime.UtcNow.ToString("o", CultureInfo.InvariantCulture); + + using var checkCmd = conn.CreateCommand(); + checkCmd.CommandText = "SELECT COUNT(*) FROM gk_role WHERE is_system = true"; + var count = Convert.ToInt64(checkCmd.ExecuteScalar(), CultureInfo.InvariantCulture); + + if (count > 0) + { + logger.LogInformation("Database already seeded, skipping"); + return new InitOk(true); + } + + logger.LogInformation("Seeding default roles and permissions"); + + ExecuteNonQuery( + conn, + """ + INSERT INTO gk_role (id, name, description, is_system, created_at) + VALUES ('role-admin', 'admin', 'Full system access', true, @now), + ('role-user', 'user', 'Basic authenticated user', true, @now) + """, + ("@now", now) + ); + + ExecuteNonQuery( + conn, + """ + INSERT INTO gk_permission (id, code, resource_type, action, description, created_at) + VALUES ('perm-admin-all', 'admin:*', 'admin', '*', 'Full admin access', @now), + ('perm-user-profile', 'user:profile', 'user', 'read', 'View own profile', @now), + ('perm-user-credentials', 'user:credentials', 'user', 'manage', 'Manage own passkeys', @now), + ('perm-patient-read', 'patient:read', 'patient', 'read', 'Read patient records', @now), + ('perm-order-read', 'order:read', 'order', 'read', 'Read order records', @now), + ('perm-sync-read', 'sync:read', 'sync', 'read', 'Read sync data', @now), + ('perm-sync-write', 'sync:write', 'sync', 'write', 'Write sync data', @now) + """, + ("@now", now) + ); + + ExecuteNonQuery( + conn, + """ + INSERT INTO gk_role_permission (role_id, permission_id, granted_at) + VALUES ('role-admin', 'perm-admin-all', @now), + ('role-admin', 'perm-sync-read', @now), + ('role-admin', 'perm-sync-write', @now), + ('role-user', 'perm-user-profile', @now), + ('role-user', 'perm-user-credentials', @now) + """, + ("@now", now) + ); + + logger.LogInformation("Default data seeded successfully"); + return new InitOk(true); + } + catch (Exception ex) + { + logger.LogError(ex, "Failed to seed Gatekeeper default data"); + return new InitError($"Failed to seed Gatekeeper default data: {ex.Message}"); + } + } + + private static void ExecuteNonQuery( + NpgsqlConnection conn, + string sql, + params (string name, object value)[] parameters + ) + { + using var cmd = conn.CreateCommand(); + cmd.CommandText = sql; + foreach (var (name, value) in parameters) + { + cmd.Parameters.AddWithValue(name, value); + } + cmd.ExecuteNonQuery(); + } +} diff --git a/Gatekeeper/Gatekeeper.Api/FileLoggerProvider.cs b/Gatekeeper/Gatekeeper.Api/FileLoggerProvider.cs new file mode 100644 index 0000000..8514a99 --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api/FileLoggerProvider.cs @@ -0,0 +1,109 @@ +namespace Gatekeeper.Api; + +/// +/// Extension methods for adding file logging. +/// +public static class FileLoggingExtensions +{ + /// + /// Adds file logging to the logging builder. + /// + public static ILoggingBuilder AddFileLogging(this ILoggingBuilder builder, string path) + { + // CA2000: DI container takes ownership and disposes when application shuts down +#pragma warning disable CA2000 + builder.Services.AddSingleton(new FileLoggerProvider(path)); +#pragma warning restore CA2000 + return builder; + } +} + +/// +/// Simple file logger provider for writing logs to disk. +/// +public sealed class FileLoggerProvider : ILoggerProvider +{ + private readonly string _path; + private readonly object _lock = new(); + + /// + /// Initializes a new instance of FileLoggerProvider. + /// + public FileLoggerProvider(string path) + { + _path = path; + } + + /// + /// Creates a logger for the specified category. + /// + public ILogger CreateLogger(string categoryName) => new FileLogger(_path, categoryName, _lock); + + /// + /// Disposes the provider. + /// + public void Dispose() + { + // Nothing to dispose - singleton managed by DI container + } +} + +/// +/// Simple file logger that appends log entries to a file. +/// +public sealed class FileLogger : ILogger +{ + private readonly string _path; + private readonly string _category; + private readonly object _lock; + + /// + /// Initializes a new instance of FileLogger. + /// + public FileLogger(string path, string category, object lockObj) + { + _path = path; + _category = category; + _lock = lockObj; + } + + /// + /// Begins a logical operation scope. + /// + public IDisposable? BeginScope(TState state) + where TState : notnull => null; + + /// + /// Checks if the given log level is enabled. + /// + public bool IsEnabled(LogLevel logLevel) => logLevel != LogLevel.None; + + /// + /// Writes a log entry to the file. + /// + public void Log( + LogLevel logLevel, + EventId eventId, + TState state, + Exception? exception, + Func formatter + ) + { + if (!IsEnabled(logLevel)) + { + return; + } + + var message = formatter(state, exception); + var line = $"{DateTime.UtcNow:yyyy-MM-dd HH:mm:ss.fff} [{logLevel}] {_category}: {message}"; + if (exception != null) + { + line += Environment.NewLine + exception; + } + + lock (_lock) + { + File.AppendAllText(_path, line + Environment.NewLine); + } + } +} diff --git a/Gatekeeper/Gatekeeper.Api/Gatekeeper.Api.csproj b/Gatekeeper/Gatekeeper.Api/Gatekeeper.Api.csproj new file mode 100644 index 0000000..4b85e6f --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api/Gatekeeper.Api.csproj @@ -0,0 +1,67 @@ + + + Exe + MelbourneDev.Gatekeeper + CA1515;CA2100;RS1035;CA1508;CA2234;CA1819;CA2007;EPC12 + + + + + + + + + + + + + + + + + + + + + + + + + + + PreserveNewest + + + + + + + + + + + + + + + + + + + diff --git a/Gatekeeper/Gatekeeper.Api/Generated/.timestamp b/Gatekeeper/Gatekeeper.Api/Generated/.timestamp new file mode 100644 index 0000000..e69de29 diff --git a/Gatekeeper/Gatekeeper.Api/Generated/CheckPermission.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/CheckPermission.g.cs new file mode 100644 index 0000000..437858e --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api/Generated/CheckPermission.g.cs @@ -0,0 +1,107 @@ +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Threading.Tasks; +using Npgsql; +using Outcome; +using Selecta; + +namespace Generated; + +/// +/// Extension methods for 'CheckPermission'. +/// +public static partial class CheckPermissionExtensions +{ + /// + /// Executes 'CheckPermission.sql' and maps results. + /// + /// Open NpgsqlConnection connection. + /// Query parameter. + /// Query parameter. + /// Query parameter. + /// Result of records or SQL error. + public static async Task, SqlError>> CheckPermissionAsync(this NpgsqlConnection connection, object permissionCode, object userId, object now) + { + const string sql = @"-- name: CheckPermission +-- Checks if user has a specific permission code (via roles or direct grant) +SELECT 1 AS has_permission +FROM gk_permission p +WHERE p.code = @permissionCode + AND ( + -- Check role permissions + EXISTS ( + SELECT 1 FROM gk_role_permission rp + JOIN gk_user_role ur ON rp.role_id = ur.role_id + WHERE rp.permission_id = p.id + AND ur.user_id = @userId + AND (ur.expires_at IS NULL OR ur.expires_at > @now) + ) + OR + -- Check direct permissions + EXISTS ( + SELECT 1 FROM gk_user_permission up + WHERE up.permission_id = p.id + AND up.user_id = @userId + AND (up.expires_at IS NULL OR up.expires_at > @now) + ) + ) +LIMIT 1; +"; + + try + { + var results = ImmutableList.CreateBuilder(); + + using (var command = new NpgsqlCommand(sql, connection)) + { + if (permissionCode is not null and not DBNull) + command.Parameters.AddWithValue("@permissionCode", permissionCode); + else + command.Parameters.Add(new NpgsqlParameter("@permissionCode", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); + if (userId is not null and not DBNull) + command.Parameters.AddWithValue("@userId", userId); + else + command.Parameters.Add(new NpgsqlParameter("@userId", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); + if (now is not null and not DBNull) + command.Parameters.AddWithValue("@now", now); + else + command.Parameters.Add(new NpgsqlParameter("@now", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); + + using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false)) + { + while (await reader.ReadAsync().ConfigureAwait(false)) + { + var item = new CheckPermission( + reader.IsDBNull(0) ? null : reader.GetFieldValue(0) + ); + results.Add(item); + } + } + } + + return new Result, SqlError>.Ok, SqlError>(results.ToImmutable()); + } + catch (Exception ex) + { + return new Result, SqlError>.Error, SqlError>(new SqlError("Database error", ex)); + } + } +} + +/// +/// Result row for 'CheckPermission' query. +/// +public record CheckPermission +{ + /// Column 'has_permission'. + public byte[] has_permission { get; init; } + + /// Initializes a new instance of CheckPermission. + public CheckPermission( + byte[] has_permission + ) + { + this.has_permission = has_permission; + } +} diff --git a/Gatekeeper/Gatekeeper.Api/Generated/CheckResourceGrant.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/CheckResourceGrant.g.cs new file mode 100644 index 0000000..57d9ee3 --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api/Generated/CheckResourceGrant.g.cs @@ -0,0 +1,151 @@ +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Threading.Tasks; +using Npgsql; +using Outcome; +using Selecta; + +namespace Generated; + +/// +/// Extension methods for 'CheckResourceGrant'. +/// +public static partial class CheckResourceGrantExtensions +{ + /// + /// Executes 'CheckResourceGrant.sql' and maps results. + /// + /// Open NpgsqlConnection connection. + /// Query parameter. + /// Query parameter. + /// Query parameter. + /// Query parameter. + /// Query parameter. + /// Result of records or SQL error. + public static async Task, SqlError>> CheckResourceGrantAsync(this NpgsqlConnection connection, object resource_type, object now, object resource_id, object user_id, object permission_code) + { + const string sql = @"-- name: CheckResourceGrant +SELECT rg.id, rg.user_id, rg.resource_type, rg.resource_id, rg.permission_id, + rg.granted_at, rg.granted_by, rg.expires_at, p.code as permission_code +FROM gk_resource_grant rg +JOIN gk_permission p ON rg.permission_id = p.id +WHERE rg.user_id = @user_id + AND rg.resource_type = @resource_type + AND rg.resource_id = @resource_id + AND p.code = @permission_code + AND (rg.expires_at IS NULL OR rg.expires_at > @now); +"; + + try + { + var results = ImmutableList.CreateBuilder(); + + using (var command = new NpgsqlCommand(sql, connection)) + { + if (resource_type is not null and not DBNull) + command.Parameters.AddWithValue("@resource_type", resource_type); + else + command.Parameters.Add(new NpgsqlParameter("@resource_type", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); + if (now is not null and not DBNull) + command.Parameters.AddWithValue("@now", now); + else + command.Parameters.Add(new NpgsqlParameter("@now", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); + if (resource_id is not null and not DBNull) + command.Parameters.AddWithValue("@resource_id", resource_id); + else + command.Parameters.Add(new NpgsqlParameter("@resource_id", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); + if (user_id is not null and not DBNull) + command.Parameters.AddWithValue("@user_id", user_id); + else + command.Parameters.Add(new NpgsqlParameter("@user_id", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); + if (permission_code is not null and not DBNull) + command.Parameters.AddWithValue("@permission_code", permission_code); + else + command.Parameters.Add(new NpgsqlParameter("@permission_code", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); + + using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false)) + { + while (await reader.ReadAsync().ConfigureAwait(false)) + { + var item = new CheckResourceGrant( + reader.IsDBNull(0) ? null : reader.GetFieldValue(0), + reader.IsDBNull(1) ? null : reader.GetFieldValue(1), + reader.IsDBNull(2) ? null : reader.GetFieldValue(2), + reader.IsDBNull(3) ? null : reader.GetFieldValue(3), + reader.IsDBNull(4) ? null : reader.GetFieldValue(4), + reader.IsDBNull(5) ? null : reader.GetFieldValue(5), + reader.IsDBNull(6) ? null : reader.GetFieldValue(6), + reader.IsDBNull(7) ? null : reader.GetFieldValue(7), + reader.IsDBNull(8) ? null : reader.GetFieldValue(8) + ); + results.Add(item); + } + } + } + + return new Result, SqlError>.Ok, SqlError>(results.ToImmutable()); + } + catch (Exception ex) + { + return new Result, SqlError>.Error, SqlError>(new SqlError("Database error", ex)); + } + } +} + +/// +/// Result row for 'CheckResourceGrant' query. +/// +public record CheckResourceGrant +{ + /// Column 'id'. + public string id { get; init; } + + /// Column 'user_id'. + public string user_id { get; init; } + + /// Column 'resource_type'. + public string resource_type { get; init; } + + /// Column 'resource_id'. + public string resource_id { get; init; } + + /// Column 'permission_id'. + public string permission_id { get; init; } + + /// Column 'granted_at'. + public string granted_at { get; init; } + + /// Column 'granted_by'. + public string granted_by { get; init; } + + /// Column 'expires_at'. + public string expires_at { get; init; } + + /// Column 'permission_code'. + public string permission_code { get; init; } + + /// Initializes a new instance of CheckResourceGrant. + public CheckResourceGrant( + string id, + string user_id, + string resource_type, + string resource_id, + string permission_id, + string granted_at, + string granted_by, + string expires_at, + string permission_code + ) + { + this.id = id; + this.user_id = user_id; + this.resource_type = resource_type; + this.resource_id = resource_id; + this.permission_id = permission_id; + this.granted_at = granted_at; + this.granted_by = granted_by; + this.expires_at = expires_at; + this.permission_code = permission_code; + } +} diff --git a/Gatekeeper/Gatekeeper.Api/Generated/CountSystemRoles.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/CountSystemRoles.g.cs new file mode 100644 index 0000000..95e0a54 --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api/Generated/CountSystemRoles.g.cs @@ -0,0 +1,70 @@ +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Threading.Tasks; +using Npgsql; +using Outcome; +using Selecta; + +namespace Generated; + +/// +/// Extension methods for 'CountSystemRoles'. +/// +public static partial class CountSystemRolesExtensions +{ + /// + /// Executes 'CountSystemRoles.sql' and maps results. + /// + /// Open NpgsqlConnection connection. + /// Result of records or SQL error. + public static async Task, SqlError>> CountSystemRolesAsync(this NpgsqlConnection connection) + { + const string sql = @"-- name: CountSystemRoles +SELECT COUNT(*) as cnt FROM gk_role WHERE is_system = true; +"; + + try + { + var results = ImmutableList.CreateBuilder(); + + using (var command = new NpgsqlCommand(sql, connection)) + { + + using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false)) + { + while (await reader.ReadAsync().ConfigureAwait(false)) + { + var item = new CountSystemRoles( + reader.IsDBNull(0) ? default(long) : reader.GetFieldValue(0) + ); + results.Add(item); + } + } + } + + return new Result, SqlError>.Ok, SqlError>(results.ToImmutable()); + } + catch (Exception ex) + { + return new Result, SqlError>.Error, SqlError>(new SqlError("Database error", ex)); + } + } +} + +/// +/// Result row for 'CountSystemRoles' query. +/// +public record CountSystemRoles +{ + /// Column 'cnt'. + public long cnt { get; init; } + + /// Initializes a new instance of CountSystemRoles. + public CountSystemRoles( + long cnt + ) + { + this.cnt = cnt; + } +} diff --git a/Gatekeeper/Gatekeeper.Api/Generated/GetActivePolicies.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/GetActivePolicies.g.cs new file mode 100644 index 0000000..70c34e1 --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api/Generated/GetActivePolicies.g.cs @@ -0,0 +1,127 @@ +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Threading.Tasks; +using Npgsql; +using Outcome; +using Selecta; + +namespace Generated; + +/// +/// Extension methods for 'GetActivePolicies'. +/// +public static partial class GetActivePoliciesExtensions +{ + /// + /// Executes 'GetActivePolicies.sql' and maps results. + /// + /// Open NpgsqlConnection connection. + /// Query parameter. + /// Query parameter. + /// Result of records or SQL error. + public static async Task, SqlError>> GetActivePoliciesAsync(this NpgsqlConnection connection, object resource_type, object action) + { + const string sql = @"-- name: GetActivePolicies +SELECT id, name, description, resource_type, action, condition, effect, priority +FROM gk_policy +WHERE is_active = true + AND (resource_type = @resource_type OR resource_type = '*') + AND (action = @action OR action = '*') +ORDER BY priority DESC; +"; + + try + { + var results = ImmutableList.CreateBuilder(); + + using (var command = new NpgsqlCommand(sql, connection)) + { + if (resource_type is not null and not DBNull) + command.Parameters.AddWithValue("@resource_type", resource_type); + else + command.Parameters.Add(new NpgsqlParameter("@resource_type", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); + if (action is not null and not DBNull) + command.Parameters.AddWithValue("@action", action); + else + command.Parameters.Add(new NpgsqlParameter("@action", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); + + using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false)) + { + while (await reader.ReadAsync().ConfigureAwait(false)) + { + var item = new GetActivePolicies( + reader.IsDBNull(0) ? null : reader.GetFieldValue(0), + reader.IsDBNull(1) ? null : reader.GetFieldValue(1), + reader.IsDBNull(2) ? null : reader.GetFieldValue(2), + reader.IsDBNull(3) ? null : reader.GetFieldValue(3), + reader.IsDBNull(4) ? null : reader.GetFieldValue(4), + reader.IsDBNull(5) ? null : reader.GetFieldValue(5), + reader.IsDBNull(6) ? null : reader.GetFieldValue(6), + reader.IsDBNull(7) ? default(long) : reader.GetFieldValue(7) + ); + results.Add(item); + } + } + } + + return new Result, SqlError>.Ok, SqlError>(results.ToImmutable()); + } + catch (Exception ex) + { + return new Result, SqlError>.Error, SqlError>(new SqlError("Database error", ex)); + } + } +} + +/// +/// Result row for 'GetActivePolicies' query. +/// +public record GetActivePolicies +{ + /// Column 'id'. + public string id { get; init; } + + /// Column 'name'. + public string name { get; init; } + + /// Column 'description'. + public string description { get; init; } + + /// Column 'resource_type'. + public string resource_type { get; init; } + + /// Column 'action'. + public string action { get; init; } + + /// Column 'condition'. + public string condition { get; init; } + + /// Column 'effect'. + public string effect { get; init; } + + /// Column 'priority'. + public long priority { get; init; } + + /// Initializes a new instance of GetActivePolicies. + public GetActivePolicies( + string id, + string name, + string description, + string resource_type, + string action, + string condition, + string effect, + long priority + ) + { + this.id = id; + this.name = name; + this.description = description; + this.resource_type = resource_type; + this.action = action; + this.condition = condition; + this.effect = effect; + this.priority = priority; + } +} diff --git a/Gatekeeper/Gatekeeper.Api/Generated/GetAllPermissions.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/GetAllPermissions.g.cs new file mode 100644 index 0000000..13611cf --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api/Generated/GetAllPermissions.g.cs @@ -0,0 +1,102 @@ +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Threading.Tasks; +using Npgsql; +using Outcome; +using Selecta; + +namespace Generated; + +/// +/// Extension methods for 'GetAllPermissions'. +/// +public static partial class GetAllPermissionsExtensions +{ + /// + /// Executes 'GetAllPermissions.sql' and maps results. + /// + /// Open NpgsqlConnection connection. + /// Result of records or SQL error. + public static async Task, SqlError>> GetAllPermissionsAsync(this NpgsqlConnection connection) + { + const string sql = @"-- name: GetAllPermissions +SELECT id, code, resource_type, action, description, created_at +FROM gk_permission +ORDER BY resource_type, action; +"; + + try + { + var results = ImmutableList.CreateBuilder(); + + using (var command = new NpgsqlCommand(sql, connection)) + { + + using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false)) + { + while (await reader.ReadAsync().ConfigureAwait(false)) + { + var item = new GetAllPermissions( + reader.IsDBNull(0) ? null : reader.GetFieldValue(0), + reader.IsDBNull(1) ? null : reader.GetFieldValue(1), + reader.IsDBNull(2) ? null : reader.GetFieldValue(2), + reader.IsDBNull(3) ? null : reader.GetFieldValue(3), + reader.IsDBNull(4) ? null : reader.GetFieldValue(4), + reader.IsDBNull(5) ? null : reader.GetFieldValue(5) + ); + results.Add(item); + } + } + } + + return new Result, SqlError>.Ok, SqlError>(results.ToImmutable()); + } + catch (Exception ex) + { + return new Result, SqlError>.Error, SqlError>(new SqlError("Database error", ex)); + } + } +} + +/// +/// Result row for 'GetAllPermissions' query. +/// +public record GetAllPermissions +{ + /// Column 'id'. + public string id { get; init; } + + /// Column 'code'. + public string code { get; init; } + + /// Column 'resource_type'. + public string resource_type { get; init; } + + /// Column 'action'. + public string action { get; init; } + + /// Column 'description'. + public string description { get; init; } + + /// Column 'created_at'. + public string created_at { get; init; } + + /// Initializes a new instance of GetAllPermissions. + public GetAllPermissions( + string id, + string code, + string resource_type, + string action, + string description, + string created_at + ) + { + this.id = id; + this.code = code; + this.resource_type = resource_type; + this.action = action; + this.description = description; + this.created_at = created_at; + } +} diff --git a/Gatekeeper/Gatekeeper.Api/Generated/GetAllRoles.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/GetAllRoles.g.cs new file mode 100644 index 0000000..1298969 --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api/Generated/GetAllRoles.g.cs @@ -0,0 +1,102 @@ +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Threading.Tasks; +using Npgsql; +using Outcome; +using Selecta; + +namespace Generated; + +/// +/// Extension methods for 'GetAllRoles'. +/// +public static partial class GetAllRolesExtensions +{ + /// + /// Executes 'GetAllRoles.sql' and maps results. + /// + /// Open NpgsqlConnection connection. + /// Result of records or SQL error. + public static async Task, SqlError>> GetAllRolesAsync(this NpgsqlConnection connection) + { + const string sql = @"-- name: GetAllRoles +SELECT id, name, description, is_system, created_at, parent_role_id +FROM gk_role +ORDER BY name; +"; + + try + { + var results = ImmutableList.CreateBuilder(); + + using (var command = new NpgsqlCommand(sql, connection)) + { + + using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false)) + { + while (await reader.ReadAsync().ConfigureAwait(false)) + { + var item = new GetAllRoles( + reader.IsDBNull(0) ? null : reader.GetFieldValue(0), + reader.IsDBNull(1) ? null : reader.GetFieldValue(1), + reader.IsDBNull(2) ? null : reader.GetFieldValue(2), + reader.IsDBNull(3) ? null : reader.GetFieldValue(3), + reader.IsDBNull(4) ? null : reader.GetFieldValue(4), + reader.IsDBNull(5) ? null : reader.GetFieldValue(5) + ); + results.Add(item); + } + } + } + + return new Result, SqlError>.Ok, SqlError>(results.ToImmutable()); + } + catch (Exception ex) + { + return new Result, SqlError>.Error, SqlError>(new SqlError("Database error", ex)); + } + } +} + +/// +/// Result row for 'GetAllRoles' query. +/// +public record GetAllRoles +{ + /// Column 'id'. + public string id { get; init; } + + /// Column 'name'. + public string name { get; init; } + + /// Column 'description'. + public string description { get; init; } + + /// Column 'is_system'. + public bool? is_system { get; init; } + + /// Column 'created_at'. + public string created_at { get; init; } + + /// Column 'parent_role_id'. + public string parent_role_id { get; init; } + + /// Initializes a new instance of GetAllRoles. + public GetAllRoles( + string id, + string name, + string description, + bool? is_system, + string created_at, + string parent_role_id + ) + { + this.id = id; + this.name = name; + this.description = description; + this.is_system = is_system; + this.created_at = created_at; + this.parent_role_id = parent_role_id; + } +} diff --git a/Gatekeeper/Gatekeeper.Api/Generated/GetAllUsers.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/GetAllUsers.g.cs new file mode 100644 index 0000000..6ed530d --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api/Generated/GetAllUsers.g.cs @@ -0,0 +1,102 @@ +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Threading.Tasks; +using Npgsql; +using Outcome; +using Selecta; + +namespace Generated; + +/// +/// Extension methods for 'GetAllUsers'. +/// +public static partial class GetAllUsersExtensions +{ + /// + /// Executes 'GetAllUsers.sql' and maps results. + /// + /// Open NpgsqlConnection connection. + /// Result of records or SQL error. + public static async Task, SqlError>> GetAllUsersAsync(this NpgsqlConnection connection) + { + const string sql = @"-- name: GetAllUsers +SELECT id, display_name, email, created_at, last_login_at, is_active +FROM gk_user +ORDER BY display_name; +"; + + try + { + var results = ImmutableList.CreateBuilder(); + + using (var command = new NpgsqlCommand(sql, connection)) + { + + using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false)) + { + while (await reader.ReadAsync().ConfigureAwait(false)) + { + var item = new GetAllUsers( + reader.IsDBNull(0) ? null : reader.GetFieldValue(0), + reader.IsDBNull(1) ? null : reader.GetFieldValue(1), + reader.IsDBNull(2) ? null : reader.GetFieldValue(2), + reader.IsDBNull(3) ? null : reader.GetFieldValue(3), + reader.IsDBNull(4) ? null : reader.GetFieldValue(4), + reader.IsDBNull(5) ? null : reader.GetFieldValue(5) + ); + results.Add(item); + } + } + } + + return new Result, SqlError>.Ok, SqlError>(results.ToImmutable()); + } + catch (Exception ex) + { + return new Result, SqlError>.Error, SqlError>(new SqlError("Database error", ex)); + } + } +} + +/// +/// Result row for 'GetAllUsers' query. +/// +public record GetAllUsers +{ + /// Column 'id'. + public string id { get; init; } + + /// Column 'display_name'. + public string display_name { get; init; } + + /// Column 'email'. + public string email { get; init; } + + /// Column 'created_at'. + public string created_at { get; init; } + + /// Column 'last_login_at'. + public string last_login_at { get; init; } + + /// Column 'is_active'. + public bool? is_active { get; init; } + + /// Initializes a new instance of GetAllUsers. + public GetAllUsers( + string id, + string display_name, + string email, + string created_at, + string last_login_at, + bool? is_active + ) + { + this.id = id; + this.display_name = display_name; + this.email = email; + this.created_at = created_at; + this.last_login_at = last_login_at; + this.is_active = is_active; + } +} diff --git a/Gatekeeper/Gatekeeper.Api/Generated/GetChallengeById.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/GetChallengeById.g.cs new file mode 100644 index 0000000..6884d4a --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api/Generated/GetChallengeById.g.cs @@ -0,0 +1,112 @@ +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Threading.Tasks; +using Npgsql; +using Outcome; +using Selecta; + +namespace Generated; + +/// +/// Extension methods for 'GetChallengeById'. +/// +public static partial class GetChallengeByIdExtensions +{ + /// + /// Executes 'GetChallengeById.sql' and maps results. + /// + /// Open NpgsqlConnection connection. + /// Query parameter. + /// Query parameter. + /// Result of records or SQL error. + public static async Task, SqlError>> GetChallengeByIdAsync(this NpgsqlConnection connection, object id, object now) + { + const string sql = @"-- name: GetChallengeById +SELECT id, user_id, challenge, type, created_at, expires_at +FROM gk_challenge +WHERE id = @id AND expires_at > @now; +"; + + try + { + var results = ImmutableList.CreateBuilder(); + + using (var command = new NpgsqlCommand(sql, connection)) + { + if (id is not null and not DBNull) + command.Parameters.AddWithValue("@id", id); + else + command.Parameters.Add(new NpgsqlParameter("@id", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); + if (now is not null and not DBNull) + command.Parameters.AddWithValue("@now", now); + else + command.Parameters.Add(new NpgsqlParameter("@now", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); + + using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false)) + { + while (await reader.ReadAsync().ConfigureAwait(false)) + { + var item = new GetChallengeById( + reader.IsDBNull(0) ? null : reader.GetFieldValue(0), + reader.IsDBNull(1) ? null : reader.GetFieldValue(1), + reader.IsDBNull(2) ? null : reader.GetFieldValue(2), + reader.IsDBNull(3) ? null : reader.GetFieldValue(3), + reader.IsDBNull(4) ? null : reader.GetFieldValue(4), + reader.IsDBNull(5) ? null : reader.GetFieldValue(5) + ); + results.Add(item); + } + } + } + + return new Result, SqlError>.Ok, SqlError>(results.ToImmutable()); + } + catch (Exception ex) + { + return new Result, SqlError>.Error, SqlError>(new SqlError("Database error", ex)); + } + } +} + +/// +/// Result row for 'GetChallengeById' query. +/// +public record GetChallengeById +{ + /// Column 'id'. + public string id { get; init; } + + /// Column 'user_id'. + public string user_id { get; init; } + + /// Column 'challenge'. + public byte[] challenge { get; init; } + + /// Column 'type'. + public string type { get; init; } + + /// Column 'created_at'. + public string created_at { get; init; } + + /// Column 'expires_at'. + public string expires_at { get; init; } + + /// Initializes a new instance of GetChallengeById. + public GetChallengeById( + string id, + string user_id, + byte[] challenge, + string type, + string created_at, + string expires_at + ) + { + this.id = id; + this.user_id = user_id; + this.challenge = challenge; + this.type = type; + this.created_at = created_at; + this.expires_at = expires_at; + } +} diff --git a/Gatekeeper/Gatekeeper.Api/Generated/GetCredentialById.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/GetCredentialById.g.cs new file mode 100644 index 0000000..8e034b6 --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api/Generated/GetCredentialById.g.cs @@ -0,0 +1,164 @@ +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Threading.Tasks; +using Npgsql; +using Outcome; +using Selecta; + +namespace Generated; + +/// +/// Extension methods for 'GetCredentialById'. +/// +public static partial class GetCredentialByIdExtensions +{ + /// + /// Executes 'GetCredentialById.sql' and maps results. + /// + /// Open NpgsqlConnection connection. + /// Query parameter. + /// Result of records or SQL error. + public static async Task, SqlError>> GetCredentialByIdAsync(this NpgsqlConnection connection, object id) + { + const string sql = @"-- name: GetCredentialById +SELECT c.id, c.user_id, c.public_key, c.sign_count, c.aaguid, c.credential_type, c.transports, + c.attestation_format, c.created_at, c.last_used_at, c.device_name, c.is_backup_eligible, c.is_backed_up, + u.display_name, u.email +FROM gk_credential c +JOIN gk_user u ON c.user_id = u.id +WHERE c.id = @id AND u.is_active = true; +"; + + try + { + var results = ImmutableList.CreateBuilder(); + + using (var command = new NpgsqlCommand(sql, connection)) + { + if (id is not null and not DBNull) + command.Parameters.AddWithValue("@id", id); + else + command.Parameters.Add(new NpgsqlParameter("@id", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); + + using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false)) + { + while (await reader.ReadAsync().ConfigureAwait(false)) + { + var item = new GetCredentialById( + reader.IsDBNull(0) ? null : reader.GetFieldValue(0), + reader.IsDBNull(1) ? null : reader.GetFieldValue(1), + reader.IsDBNull(2) ? null : reader.GetFieldValue(2), + reader.IsDBNull(3) ? default(long) : reader.GetFieldValue(3), + reader.IsDBNull(4) ? null : reader.GetFieldValue(4), + reader.IsDBNull(5) ? null : reader.GetFieldValue(5), + reader.IsDBNull(6) ? null : reader.GetFieldValue(6), + reader.IsDBNull(7) ? null : reader.GetFieldValue(7), + reader.IsDBNull(8) ? null : reader.GetFieldValue(8), + reader.IsDBNull(9) ? null : reader.GetFieldValue(9), + reader.IsDBNull(10) ? null : reader.GetFieldValue(10), + reader.IsDBNull(11) ? null : reader.GetFieldValue(11), + reader.IsDBNull(12) ? null : reader.GetFieldValue(12), + reader.IsDBNull(13) ? null : reader.GetFieldValue(13), + reader.IsDBNull(14) ? null : reader.GetFieldValue(14) + ); + results.Add(item); + } + } + } + + return new Result, SqlError>.Ok, SqlError>(results.ToImmutable()); + } + catch (Exception ex) + { + return new Result, SqlError>.Error, SqlError>(new SqlError("Database error", ex)); + } + } +} + +/// +/// Result row for 'GetCredentialById' query. +/// +public record GetCredentialById +{ + /// Column 'id'. + public string id { get; init; } + + /// Column 'user_id'. + public string user_id { get; init; } + + /// Column 'public_key'. + public byte[] public_key { get; init; } + + /// Column 'sign_count'. + public long sign_count { get; init; } + + /// Column 'aaguid'. + public string aaguid { get; init; } + + /// Column 'credential_type'. + public string credential_type { get; init; } + + /// Column 'transports'. + public string transports { get; init; } + + /// Column 'attestation_format'. + public string attestation_format { get; init; } + + /// Column 'created_at'. + public string created_at { get; init; } + + /// Column 'last_used_at'. + public string last_used_at { get; init; } + + /// Column 'device_name'. + public string device_name { get; init; } + + /// Column 'is_backup_eligible'. + public bool? is_backup_eligible { get; init; } + + /// Column 'is_backed_up'. + public bool? is_backed_up { get; init; } + + /// Column 'display_name'. + public string display_name { get; init; } + + /// Column 'email'. + public string email { get; init; } + + /// Initializes a new instance of GetCredentialById. + public GetCredentialById( + string id, + string user_id, + byte[] public_key, + long sign_count, + string aaguid, + string credential_type, + string transports, + string attestation_format, + string created_at, + string last_used_at, + string device_name, + bool? is_backup_eligible, + bool? is_backed_up, + string display_name, + string email + ) + { + this.id = id; + this.user_id = user_id; + this.public_key = public_key; + this.sign_count = sign_count; + this.aaguid = aaguid; + this.credential_type = credential_type; + this.transports = transports; + this.attestation_format = attestation_format; + this.created_at = created_at; + this.last_used_at = last_used_at; + this.device_name = device_name; + this.is_backup_eligible = is_backup_eligible; + this.is_backed_up = is_backed_up; + this.display_name = display_name; + this.email = email; + } +} diff --git a/Gatekeeper/Gatekeeper.Api/Generated/GetCredentialsByUserId.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/GetCredentialsByUserId.g.cs new file mode 100644 index 0000000..67d6c98 --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api/Generated/GetCredentialsByUserId.g.cs @@ -0,0 +1,151 @@ +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Threading.Tasks; +using Npgsql; +using Outcome; +using Selecta; + +namespace Generated; + +/// +/// Extension methods for 'GetCredentialsByUserId'. +/// +public static partial class GetCredentialsByUserIdExtensions +{ + /// + /// Executes 'GetCredentialsByUserId.sql' and maps results. + /// + /// Open NpgsqlConnection connection. + /// Query parameter. + /// Result of records or SQL error. + public static async Task, SqlError>> GetCredentialsByUserIdAsync(this NpgsqlConnection connection, object userId) + { + const string sql = @"-- name: GetCredentialsByUserId +SELECT id, user_id, public_key, sign_count, aaguid, credential_type, transports, + attestation_format, created_at, last_used_at, device_name, + is_backup_eligible, is_backed_up +FROM gk_credential +WHERE user_id = @userId; +"; + + try + { + var results = ImmutableList.CreateBuilder(); + + using (var command = new NpgsqlCommand(sql, connection)) + { + if (userId is not null and not DBNull) + command.Parameters.AddWithValue("@userId", userId); + else + command.Parameters.Add(new NpgsqlParameter("@userId", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); + + using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false)) + { + while (await reader.ReadAsync().ConfigureAwait(false)) + { + var item = new GetCredentialsByUserId( + reader.IsDBNull(0) ? null : reader.GetFieldValue(0), + reader.IsDBNull(1) ? null : reader.GetFieldValue(1), + reader.IsDBNull(2) ? null : reader.GetFieldValue(2), + reader.IsDBNull(3) ? default(long) : reader.GetFieldValue(3), + reader.IsDBNull(4) ? null : reader.GetFieldValue(4), + reader.IsDBNull(5) ? null : reader.GetFieldValue(5), + reader.IsDBNull(6) ? null : reader.GetFieldValue(6), + reader.IsDBNull(7) ? null : reader.GetFieldValue(7), + reader.IsDBNull(8) ? null : reader.GetFieldValue(8), + reader.IsDBNull(9) ? null : reader.GetFieldValue(9), + reader.IsDBNull(10) ? null : reader.GetFieldValue(10), + reader.IsDBNull(11) ? null : reader.GetFieldValue(11), + reader.IsDBNull(12) ? null : reader.GetFieldValue(12) + ); + results.Add(item); + } + } + } + + return new Result, SqlError>.Ok, SqlError>(results.ToImmutable()); + } + catch (Exception ex) + { + return new Result, SqlError>.Error, SqlError>(new SqlError("Database error", ex)); + } + } +} + +/// +/// Result row for 'GetCredentialsByUserId' query. +/// +public record GetCredentialsByUserId +{ + /// Column 'id'. + public string id { get; init; } + + /// Column 'user_id'. + public string user_id { get; init; } + + /// Column 'public_key'. + public byte[] public_key { get; init; } + + /// Column 'sign_count'. + public long sign_count { get; init; } + + /// Column 'aaguid'. + public string aaguid { get; init; } + + /// Column 'credential_type'. + public string credential_type { get; init; } + + /// Column 'transports'. + public string transports { get; init; } + + /// Column 'attestation_format'. + public string attestation_format { get; init; } + + /// Column 'created_at'. + public string created_at { get; init; } + + /// Column 'last_used_at'. + public string last_used_at { get; init; } + + /// Column 'device_name'. + public string device_name { get; init; } + + /// Column 'is_backup_eligible'. + public bool? is_backup_eligible { get; init; } + + /// Column 'is_backed_up'. + public bool? is_backed_up { get; init; } + + /// Initializes a new instance of GetCredentialsByUserId. + public GetCredentialsByUserId( + string id, + string user_id, + byte[] public_key, + long sign_count, + string aaguid, + string credential_type, + string transports, + string attestation_format, + string created_at, + string last_used_at, + string device_name, + bool? is_backup_eligible, + bool? is_backed_up + ) + { + this.id = id; + this.user_id = user_id; + this.public_key = public_key; + this.sign_count = sign_count; + this.aaguid = aaguid; + this.credential_type = credential_type; + this.transports = transports; + this.attestation_format = attestation_format; + this.created_at = created_at; + this.last_used_at = last_used_at; + this.device_name = device_name; + this.is_backup_eligible = is_backup_eligible; + this.is_backed_up = is_backed_up; + } +} diff --git a/Gatekeeper/Gatekeeper.Api/Generated/GetPermissionByCode.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/GetPermissionByCode.g.cs new file mode 100644 index 0000000..07f17f7 --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api/Generated/GetPermissionByCode.g.cs @@ -0,0 +1,107 @@ +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Threading.Tasks; +using Npgsql; +using Outcome; +using Selecta; + +namespace Generated; + +/// +/// Extension methods for 'GetPermissionByCode'. +/// +public static partial class GetPermissionByCodeExtensions +{ + /// + /// Executes 'GetPermissionByCode.sql' and maps results. + /// + /// Open NpgsqlConnection connection. + /// Query parameter. + /// Result of records or SQL error. + public static async Task, SqlError>> GetPermissionByCodeAsync(this NpgsqlConnection connection, object code) + { + const string sql = @"-- name: GetPermissionByCode +SELECT id, code, resource_type, action, description, created_at +FROM gk_permission +WHERE code = @code; +"; + + try + { + var results = ImmutableList.CreateBuilder(); + + using (var command = new NpgsqlCommand(sql, connection)) + { + if (code is not null and not DBNull) + command.Parameters.AddWithValue("@code", code); + else + command.Parameters.Add(new NpgsqlParameter("@code", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); + + using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false)) + { + while (await reader.ReadAsync().ConfigureAwait(false)) + { + var item = new GetPermissionByCode( + reader.IsDBNull(0) ? null : reader.GetFieldValue(0), + reader.IsDBNull(1) ? null : reader.GetFieldValue(1), + reader.IsDBNull(2) ? null : reader.GetFieldValue(2), + reader.IsDBNull(3) ? null : reader.GetFieldValue(3), + reader.IsDBNull(4) ? null : reader.GetFieldValue(4), + reader.IsDBNull(5) ? null : reader.GetFieldValue(5) + ); + results.Add(item); + } + } + } + + return new Result, SqlError>.Ok, SqlError>(results.ToImmutable()); + } + catch (Exception ex) + { + return new Result, SqlError>.Error, SqlError>(new SqlError("Database error", ex)); + } + } +} + +/// +/// Result row for 'GetPermissionByCode' query. +/// +public record GetPermissionByCode +{ + /// Column 'id'. + public string id { get; init; } + + /// Column 'code'. + public string code { get; init; } + + /// Column 'resource_type'. + public string resource_type { get; init; } + + /// Column 'action'. + public string action { get; init; } + + /// Column 'description'. + public string description { get; init; } + + /// Column 'created_at'. + public string created_at { get; init; } + + /// Initializes a new instance of GetPermissionByCode. + public GetPermissionByCode( + string id, + string code, + string resource_type, + string action, + string description, + string created_at + ) + { + this.id = id; + this.code = code; + this.resource_type = resource_type; + this.action = action; + this.description = description; + this.created_at = created_at; + } +} diff --git a/Gatekeeper/Gatekeeper.Api/Generated/GetRolePermissions.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/GetRolePermissions.g.cs new file mode 100644 index 0000000..284dbae --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api/Generated/GetRolePermissions.g.cs @@ -0,0 +1,115 @@ +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Threading.Tasks; +using Npgsql; +using Outcome; +using Selecta; + +namespace Generated; + +/// +/// Extension methods for 'GetRolePermissions'. +/// +public static partial class GetRolePermissionsExtensions +{ + /// + /// Executes 'GetRolePermissions.sql' and maps results. + /// + /// Open NpgsqlConnection connection. + /// Query parameter. + /// Result of records or SQL error. + public static async Task, SqlError>> GetRolePermissionsAsync(this NpgsqlConnection connection, object roleId) + { + const string sql = @"-- name: GetRolePermissions +SELECT p.id, p.code, p.resource_type, p.action, p.description, p.created_at, + rp.granted_at +FROM gk_permission p +JOIN gk_role_permission rp ON p.id = rp.permission_id +WHERE rp.role_id = @roleId; +"; + + try + { + var results = ImmutableList.CreateBuilder(); + + using (var command = new NpgsqlCommand(sql, connection)) + { + if (roleId is not null and not DBNull) + command.Parameters.AddWithValue("@roleId", roleId); + else + command.Parameters.Add(new NpgsqlParameter("@roleId", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); + + using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false)) + { + while (await reader.ReadAsync().ConfigureAwait(false)) + { + var item = new GetRolePermissions( + reader.IsDBNull(0) ? null : reader.GetFieldValue(0), + reader.IsDBNull(1) ? null : reader.GetFieldValue(1), + reader.IsDBNull(2) ? null : reader.GetFieldValue(2), + reader.IsDBNull(3) ? null : reader.GetFieldValue(3), + reader.IsDBNull(4) ? null : reader.GetFieldValue(4), + reader.IsDBNull(5) ? null : reader.GetFieldValue(5), + reader.IsDBNull(6) ? null : reader.GetFieldValue(6) + ); + results.Add(item); + } + } + } + + return new Result, SqlError>.Ok, SqlError>(results.ToImmutable()); + } + catch (Exception ex) + { + return new Result, SqlError>.Error, SqlError>(new SqlError("Database error", ex)); + } + } +} + +/// +/// Result row for 'GetRolePermissions' query. +/// +public record GetRolePermissions +{ + /// Column 'id'. + public string id { get; init; } + + /// Column 'code'. + public string code { get; init; } + + /// Column 'resource_type'. + public string resource_type { get; init; } + + /// Column 'action'. + public string action { get; init; } + + /// Column 'description'. + public string description { get; init; } + + /// Column 'created_at'. + public string created_at { get; init; } + + /// Column 'granted_at'. + public string granted_at { get; init; } + + /// Initializes a new instance of GetRolePermissions. + public GetRolePermissions( + string id, + string code, + string resource_type, + string action, + string description, + string created_at, + string granted_at + ) + { + this.id = id; + this.code = code; + this.resource_type = resource_type; + this.action = action; + this.description = description; + this.created_at = created_at; + this.granted_at = granted_at; + } +} diff --git a/Gatekeeper/Gatekeeper.Api/Generated/GetSessionById.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/GetSessionById.g.cs new file mode 100644 index 0000000..15e6c14 --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api/Generated/GetSessionById.g.cs @@ -0,0 +1,145 @@ +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Threading.Tasks; +using Npgsql; +using Outcome; +using Selecta; + +namespace Generated; + +/// +/// Extension methods for 'GetSessionById'. +/// +public static partial class GetSessionByIdExtensions +{ + /// + /// Executes 'GetSessionById.sql' and maps results. + /// + /// Open NpgsqlConnection connection. + /// Query parameter. + /// Query parameter. + /// Result of records or SQL error. + public static async Task, SqlError>> GetSessionByIdAsync(this NpgsqlConnection connection, object id, object now) + { + const string sql = @"-- name: GetSessionById +SELECT s.id, s.user_id, s.credential_id, s.created_at, s.expires_at, s.last_activity_at, + s.ip_address, s.user_agent, s.is_revoked, + u.display_name, u.email +FROM gk_session s +JOIN gk_user u ON s.user_id = u.id +WHERE s.id = @id AND s.is_revoked = false AND s.expires_at > @now AND u.is_active = true; +"; + + try + { + var results = ImmutableList.CreateBuilder(); + + using (var command = new NpgsqlCommand(sql, connection)) + { + if (id is not null and not DBNull) + command.Parameters.AddWithValue("@id", id); + else + command.Parameters.Add(new NpgsqlParameter("@id", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); + if (now is not null and not DBNull) + command.Parameters.AddWithValue("@now", now); + else + command.Parameters.Add(new NpgsqlParameter("@now", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); + + using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false)) + { + while (await reader.ReadAsync().ConfigureAwait(false)) + { + var item = new GetSessionById( + reader.IsDBNull(0) ? null : reader.GetFieldValue(0), + reader.IsDBNull(1) ? null : reader.GetFieldValue(1), + reader.IsDBNull(2) ? null : reader.GetFieldValue(2), + reader.IsDBNull(3) ? null : reader.GetFieldValue(3), + reader.IsDBNull(4) ? null : reader.GetFieldValue(4), + reader.IsDBNull(5) ? null : reader.GetFieldValue(5), + reader.IsDBNull(6) ? null : reader.GetFieldValue(6), + reader.IsDBNull(7) ? null : reader.GetFieldValue(7), + reader.IsDBNull(8) ? null : reader.GetFieldValue(8), + reader.IsDBNull(9) ? null : reader.GetFieldValue(9), + reader.IsDBNull(10) ? null : reader.GetFieldValue(10) + ); + results.Add(item); + } + } + } + + return new Result, SqlError>.Ok, SqlError>(results.ToImmutable()); + } + catch (Exception ex) + { + return new Result, SqlError>.Error, SqlError>(new SqlError("Database error", ex)); + } + } +} + +/// +/// Result row for 'GetSessionById' query. +/// +public record GetSessionById +{ + /// Column 'id'. + public string id { get; init; } + + /// Column 'user_id'. + public string user_id { get; init; } + + /// Column 'credential_id'. + public string credential_id { get; init; } + + /// Column 'created_at'. + public string created_at { get; init; } + + /// Column 'expires_at'. + public string expires_at { get; init; } + + /// Column 'last_activity_at'. + public string last_activity_at { get; init; } + + /// Column 'ip_address'. + public string ip_address { get; init; } + + /// Column 'user_agent'. + public string user_agent { get; init; } + + /// Column 'is_revoked'. + public bool? is_revoked { get; init; } + + /// Column 'display_name'. + public string display_name { get; init; } + + /// Column 'email'. + public string email { get; init; } + + /// Initializes a new instance of GetSessionById. + public GetSessionById( + string id, + string user_id, + string credential_id, + string created_at, + string expires_at, + string last_activity_at, + string ip_address, + string user_agent, + bool? is_revoked, + string display_name, + string email + ) + { + this.id = id; + this.user_id = user_id; + this.credential_id = credential_id; + this.created_at = created_at; + this.expires_at = expires_at; + this.last_activity_at = last_activity_at; + this.ip_address = ip_address; + this.user_agent = user_agent; + this.is_revoked = is_revoked; + this.display_name = display_name; + this.email = email; + } +} diff --git a/Gatekeeper/Gatekeeper.Api/Generated/GetSessionForRevoke.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/GetSessionForRevoke.g.cs new file mode 100644 index 0000000..5840dfa --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api/Generated/GetSessionForRevoke.g.cs @@ -0,0 +1,127 @@ +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Threading.Tasks; +using Npgsql; +using Outcome; +using Selecta; + +namespace Generated; + +/// +/// Extension methods for 'GetSessionForRevoke'. +/// +public static partial class GetSessionForRevokeExtensions +{ + /// + /// Executes 'GetSessionForRevoke.sql' and maps results. + /// + /// Open NpgsqlConnection connection. + /// Query parameter. + /// Result of records or SQL error. + public static async Task, SqlError>> GetSessionForRevokeAsync(this NpgsqlConnection connection, object jti) + { + const string sql = @"-- Gets a session for revocation (no filters) +-- @jti: The session ID (JWT ID) to get +SELECT id, user_id, credential_id, created_at, expires_at, last_activity_at, + ip_address, user_agent, is_revoked +FROM gk_session +WHERE id = @jti; +"; + + try + { + var results = ImmutableList.CreateBuilder(); + + using (var command = new NpgsqlCommand(sql, connection)) + { + if (jti is not null and not DBNull) + command.Parameters.AddWithValue("@jti", jti); + else + command.Parameters.Add(new NpgsqlParameter("@jti", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); + + using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false)) + { + while (await reader.ReadAsync().ConfigureAwait(false)) + { + var item = new GetSessionForRevoke( + reader.IsDBNull(0) ? null : reader.GetFieldValue(0), + reader.IsDBNull(1) ? null : reader.GetFieldValue(1), + reader.IsDBNull(2) ? null : reader.GetFieldValue(2), + reader.IsDBNull(3) ? null : reader.GetFieldValue(3), + reader.IsDBNull(4) ? null : reader.GetFieldValue(4), + reader.IsDBNull(5) ? null : reader.GetFieldValue(5), + reader.IsDBNull(6) ? null : reader.GetFieldValue(6), + reader.IsDBNull(7) ? null : reader.GetFieldValue(7), + reader.IsDBNull(8) ? null : reader.GetFieldValue(8) + ); + results.Add(item); + } + } + } + + return new Result, SqlError>.Ok, SqlError>(results.ToImmutable()); + } + catch (Exception ex) + { + return new Result, SqlError>.Error, SqlError>(new SqlError("Database error", ex)); + } + } +} + +/// +/// Result row for 'GetSessionForRevoke' query. +/// +public record GetSessionForRevoke +{ + /// Column 'id'. + public string id { get; init; } + + /// Column 'user_id'. + public string user_id { get; init; } + + /// Column 'credential_id'. + public string credential_id { get; init; } + + /// Column 'created_at'. + public string created_at { get; init; } + + /// Column 'expires_at'. + public string expires_at { get; init; } + + /// Column 'last_activity_at'. + public string last_activity_at { get; init; } + + /// Column 'ip_address'. + public string ip_address { get; init; } + + /// Column 'user_agent'. + public string user_agent { get; init; } + + /// Column 'is_revoked'. + public bool? is_revoked { get; init; } + + /// Initializes a new instance of GetSessionForRevoke. + public GetSessionForRevoke( + string id, + string user_id, + string credential_id, + string created_at, + string expires_at, + string last_activity_at, + string ip_address, + string user_agent, + bool? is_revoked + ) + { + this.id = id; + this.user_id = user_id; + this.credential_id = credential_id; + this.created_at = created_at; + this.expires_at = expires_at; + this.last_activity_at = last_activity_at; + this.ip_address = ip_address; + this.user_agent = user_agent; + this.is_revoked = is_revoked; + } +} diff --git a/Gatekeeper/Gatekeeper.Api/Generated/GetSessionRevoked.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/GetSessionRevoked.g.cs new file mode 100644 index 0000000..b57735c --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api/Generated/GetSessionRevoked.g.cs @@ -0,0 +1,76 @@ +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Threading.Tasks; +using Npgsql; +using Outcome; +using Selecta; + +namespace Generated; + +/// +/// Extension methods for 'GetSessionRevoked'. +/// +public static partial class GetSessionRevokedExtensions +{ + /// + /// Executes 'GetSessionRevoked.sql' and maps results. + /// + /// Open NpgsqlConnection connection. + /// Query parameter. + /// Result of records or SQL error. + public static async Task, SqlError>> GetSessionRevokedAsync(this NpgsqlConnection connection, object jti) + { + const string sql = @"-- Gets the revocation status of a session +-- @jti: The session ID (JWT ID) to check +SELECT is_revoked FROM gk_session WHERE id = @jti; +"; + + try + { + var results = ImmutableList.CreateBuilder(); + + using (var command = new NpgsqlCommand(sql, connection)) + { + if (jti is not null and not DBNull) + command.Parameters.AddWithValue("@jti", jti); + else + command.Parameters.Add(new NpgsqlParameter("@jti", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); + + using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false)) + { + while (await reader.ReadAsync().ConfigureAwait(false)) + { + var item = new GetSessionRevoked( + reader.IsDBNull(0) ? null : reader.GetFieldValue(0) + ); + results.Add(item); + } + } + } + + return new Result, SqlError>.Ok, SqlError>(results.ToImmutable()); + } + catch (Exception ex) + { + return new Result, SqlError>.Error, SqlError>(new SqlError("Database error", ex)); + } + } +} + +/// +/// Result row for 'GetSessionRevoked' query. +/// +public record GetSessionRevoked +{ + /// Column 'is_revoked'. + public bool? is_revoked { get; init; } + + /// Initializes a new instance of GetSessionRevoked. + public GetSessionRevoked( + bool? is_revoked + ) + { + this.is_revoked = is_revoked; + } +} diff --git a/Gatekeeper/Gatekeeper.Api/Generated/GetUserByEmail.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/GetUserByEmail.g.cs new file mode 100644 index 0000000..1b26a87 --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api/Generated/GetUserByEmail.g.cs @@ -0,0 +1,113 @@ +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Threading.Tasks; +using Npgsql; +using Outcome; +using Selecta; + +namespace Generated; + +/// +/// Extension methods for 'GetUserByEmail'. +/// +public static partial class GetUserByEmailExtensions +{ + /// + /// Executes 'GetUserByEmail.sql' and maps results. + /// + /// Open NpgsqlConnection connection. + /// Query parameter. + /// Result of records or SQL error. + public static async Task, SqlError>> GetUserByEmailAsync(this NpgsqlConnection connection, object email) + { + const string sql = @"-- name: GetUserByEmail +SELECT id, display_name, email, created_at, last_login_at, is_active, metadata +FROM gk_user +WHERE email = @email AND is_active = true; +"; + + try + { + var results = ImmutableList.CreateBuilder(); + + using (var command = new NpgsqlCommand(sql, connection)) + { + if (email is not null and not DBNull) + command.Parameters.AddWithValue("@email", email); + else + command.Parameters.Add(new NpgsqlParameter("@email", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); + + using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false)) + { + while (await reader.ReadAsync().ConfigureAwait(false)) + { + var item = new GetUserByEmail( + reader.IsDBNull(0) ? null : reader.GetFieldValue(0), + reader.IsDBNull(1) ? null : reader.GetFieldValue(1), + reader.IsDBNull(2) ? null : reader.GetFieldValue(2), + reader.IsDBNull(3) ? null : reader.GetFieldValue(3), + reader.IsDBNull(4) ? null : reader.GetFieldValue(4), + reader.IsDBNull(5) ? null : reader.GetFieldValue(5), + reader.IsDBNull(6) ? null : reader.GetFieldValue(6) + ); + results.Add(item); + } + } + } + + return new Result, SqlError>.Ok, SqlError>(results.ToImmutable()); + } + catch (Exception ex) + { + return new Result, SqlError>.Error, SqlError>(new SqlError("Database error", ex)); + } + } +} + +/// +/// Result row for 'GetUserByEmail' query. +/// +public record GetUserByEmail +{ + /// Column 'id'. + public string id { get; init; } + + /// Column 'display_name'. + public string display_name { get; init; } + + /// Column 'email'. + public string email { get; init; } + + /// Column 'created_at'. + public string created_at { get; init; } + + /// Column 'last_login_at'. + public string last_login_at { get; init; } + + /// Column 'is_active'. + public bool? is_active { get; init; } + + /// Column 'metadata'. + public string metadata { get; init; } + + /// Initializes a new instance of GetUserByEmail. + public GetUserByEmail( + string id, + string display_name, + string email, + string created_at, + string last_login_at, + bool? is_active, + string metadata + ) + { + this.id = id; + this.display_name = display_name; + this.email = email; + this.created_at = created_at; + this.last_login_at = last_login_at; + this.is_active = is_active; + this.metadata = metadata; + } +} diff --git a/Gatekeeper/Gatekeeper.Api/Generated/GetUserById.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/GetUserById.g.cs new file mode 100644 index 0000000..872f743 --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api/Generated/GetUserById.g.cs @@ -0,0 +1,113 @@ +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Threading.Tasks; +using Npgsql; +using Outcome; +using Selecta; + +namespace Generated; + +/// +/// Extension methods for 'GetUserById'. +/// +public static partial class GetUserByIdExtensions +{ + /// + /// Executes 'GetUserById.sql' and maps results. + /// + /// Open NpgsqlConnection connection. + /// Query parameter. + /// Result of records or SQL error. + public static async Task, SqlError>> GetUserByIdAsync(this NpgsqlConnection connection, object id) + { + const string sql = @"-- name: GetUserById +SELECT id, display_name, email, created_at, last_login_at, is_active, metadata +FROM gk_user +WHERE id = @id; +"; + + try + { + var results = ImmutableList.CreateBuilder(); + + using (var command = new NpgsqlCommand(sql, connection)) + { + if (id is not null and not DBNull) + command.Parameters.AddWithValue("@id", id); + else + command.Parameters.Add(new NpgsqlParameter("@id", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); + + using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false)) + { + while (await reader.ReadAsync().ConfigureAwait(false)) + { + var item = new GetUserById( + reader.IsDBNull(0) ? null : reader.GetFieldValue(0), + reader.IsDBNull(1) ? null : reader.GetFieldValue(1), + reader.IsDBNull(2) ? null : reader.GetFieldValue(2), + reader.IsDBNull(3) ? null : reader.GetFieldValue(3), + reader.IsDBNull(4) ? null : reader.GetFieldValue(4), + reader.IsDBNull(5) ? null : reader.GetFieldValue(5), + reader.IsDBNull(6) ? null : reader.GetFieldValue(6) + ); + results.Add(item); + } + } + } + + return new Result, SqlError>.Ok, SqlError>(results.ToImmutable()); + } + catch (Exception ex) + { + return new Result, SqlError>.Error, SqlError>(new SqlError("Database error", ex)); + } + } +} + +/// +/// Result row for 'GetUserById' query. +/// +public record GetUserById +{ + /// Column 'id'. + public string id { get; init; } + + /// Column 'display_name'. + public string display_name { get; init; } + + /// Column 'email'. + public string email { get; init; } + + /// Column 'created_at'. + public string created_at { get; init; } + + /// Column 'last_login_at'. + public string last_login_at { get; init; } + + /// Column 'is_active'. + public bool? is_active { get; init; } + + /// Column 'metadata'. + public string metadata { get; init; } + + /// Initializes a new instance of GetUserById. + public GetUserById( + string id, + string display_name, + string email, + string created_at, + string last_login_at, + bool? is_active, + string metadata + ) + { + this.id = id; + this.display_name = display_name; + this.email = email; + this.created_at = created_at; + this.last_login_at = last_login_at; + this.is_active = is_active; + this.metadata = metadata; + } +} diff --git a/Gatekeeper/Gatekeeper.Api/Generated/GetUserCredentials.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/GetUserCredentials.g.cs new file mode 100644 index 0000000..089d0d8 --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api/Generated/GetUserCredentials.g.cs @@ -0,0 +1,150 @@ +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Threading.Tasks; +using Npgsql; +using Outcome; +using Selecta; + +namespace Generated; + +/// +/// Extension methods for 'GetUserCredentials'. +/// +public static partial class GetUserCredentialsExtensions +{ + /// + /// Executes 'GetUserCredentials.sql' and maps results. + /// + /// Open NpgsqlConnection connection. + /// Query parameter. + /// Result of records or SQL error. + public static async Task, SqlError>> GetUserCredentialsAsync(this NpgsqlConnection connection, object user_id) + { + const string sql = @"-- name: GetUserCredentials +SELECT id, user_id, public_key, sign_count, aaguid, credential_type, transports, + attestation_format, created_at, last_used_at, device_name, is_backup_eligible, is_backed_up +FROM gk_credential +WHERE user_id = @user_id; +"; + + try + { + var results = ImmutableList.CreateBuilder(); + + using (var command = new NpgsqlCommand(sql, connection)) + { + if (user_id is not null and not DBNull) + command.Parameters.AddWithValue("@user_id", user_id); + else + command.Parameters.Add(new NpgsqlParameter("@user_id", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); + + using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false)) + { + while (await reader.ReadAsync().ConfigureAwait(false)) + { + var item = new GetUserCredentials( + reader.IsDBNull(0) ? null : reader.GetFieldValue(0), + reader.IsDBNull(1) ? null : reader.GetFieldValue(1), + reader.IsDBNull(2) ? null : reader.GetFieldValue(2), + reader.IsDBNull(3) ? default(long) : reader.GetFieldValue(3), + reader.IsDBNull(4) ? null : reader.GetFieldValue(4), + reader.IsDBNull(5) ? null : reader.GetFieldValue(5), + reader.IsDBNull(6) ? null : reader.GetFieldValue(6), + reader.IsDBNull(7) ? null : reader.GetFieldValue(7), + reader.IsDBNull(8) ? null : reader.GetFieldValue(8), + reader.IsDBNull(9) ? null : reader.GetFieldValue(9), + reader.IsDBNull(10) ? null : reader.GetFieldValue(10), + reader.IsDBNull(11) ? null : reader.GetFieldValue(11), + reader.IsDBNull(12) ? null : reader.GetFieldValue(12) + ); + results.Add(item); + } + } + } + + return new Result, SqlError>.Ok, SqlError>(results.ToImmutable()); + } + catch (Exception ex) + { + return new Result, SqlError>.Error, SqlError>(new SqlError("Database error", ex)); + } + } +} + +/// +/// Result row for 'GetUserCredentials' query. +/// +public record GetUserCredentials +{ + /// Column 'id'. + public string id { get; init; } + + /// Column 'user_id'. + public string user_id { get; init; } + + /// Column 'public_key'. + public byte[] public_key { get; init; } + + /// Column 'sign_count'. + public long sign_count { get; init; } + + /// Column 'aaguid'. + public string aaguid { get; init; } + + /// Column 'credential_type'. + public string credential_type { get; init; } + + /// Column 'transports'. + public string transports { get; init; } + + /// Column 'attestation_format'. + public string attestation_format { get; init; } + + /// Column 'created_at'. + public string created_at { get; init; } + + /// Column 'last_used_at'. + public string last_used_at { get; init; } + + /// Column 'device_name'. + public string device_name { get; init; } + + /// Column 'is_backup_eligible'. + public bool? is_backup_eligible { get; init; } + + /// Column 'is_backed_up'. + public bool? is_backed_up { get; init; } + + /// Initializes a new instance of GetUserCredentials. + public GetUserCredentials( + string id, + string user_id, + byte[] public_key, + long sign_count, + string aaguid, + string credential_type, + string transports, + string attestation_format, + string created_at, + string last_used_at, + string device_name, + bool? is_backup_eligible, + bool? is_backed_up + ) + { + this.id = id; + this.user_id = user_id; + this.public_key = public_key; + this.sign_count = sign_count; + this.aaguid = aaguid; + this.credential_type = credential_type; + this.transports = transports; + this.attestation_format = attestation_format; + this.created_at = created_at; + this.last_used_at = last_used_at; + this.device_name = device_name; + this.is_backup_eligible = is_backup_eligible; + this.is_backed_up = is_backed_up; + } +} diff --git a/Gatekeeper/Gatekeeper.Api/Generated/GetUserPermissions.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/GetUserPermissions.g.cs new file mode 100644 index 0000000..c695a43 --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api/Generated/GetUserPermissions.g.cs @@ -0,0 +1,152 @@ +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Threading.Tasks; +using Npgsql; +using Outcome; +using Selecta; + +namespace Generated; + +/// +/// Extension methods for 'GetUserPermissions'. +/// +public static partial class GetUserPermissionsExtensions +{ + /// + /// Executes 'GetUserPermissions.sql' and maps results. + /// + /// Open NpgsqlConnection connection. + /// Query parameter. + /// Query parameter. + /// Result of records or SQL error. + public static async Task, SqlError>> GetUserPermissionsAsync(this NpgsqlConnection connection, object user_id, object now) + { + const string sql = @"-- name: GetUserPermissions +-- Returns all permissions for a user: from roles + direct grants +-- Note: source_type column uses role name prefix to indicate source (role-based vs direct) +SELECT DISTINCT p.id, p.code, p.resource_type, p.action, p.description, + r.name as source_name, + ur.role_id as source_type, + NULL as scope_type, + NULL as scope_value +FROM gk_user_role ur +JOIN gk_role r ON ur.role_id = r.id +JOIN gk_role_permission rp ON r.id = rp.role_id +JOIN gk_permission p ON rp.permission_id = p.id +WHERE ur.user_id = @user_id + AND (ur.expires_at IS NULL OR ur.expires_at > @now) + +UNION ALL + +SELECT p.id, p.code, p.resource_type, p.action, p.description, + p.code as source_name, + up.permission_id as source_type, + COALESCE(up.scope_type, p.resource_type) as scope_type, + COALESCE(up.scope_value, p.action) as scope_value +FROM gk_user_permission up +JOIN gk_permission p ON up.permission_id = p.id +WHERE up.user_id = @user_id + AND (up.expires_at IS NULL OR up.expires_at > @now); +"; + + try + { + var results = ImmutableList.CreateBuilder(); + + using (var command = new NpgsqlCommand(sql, connection)) + { + if (user_id is not null and not DBNull) + command.Parameters.AddWithValue("@user_id", user_id); + else + command.Parameters.Add(new NpgsqlParameter("@user_id", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); + if (now is not null and not DBNull) + command.Parameters.AddWithValue("@now", now); + else + command.Parameters.Add(new NpgsqlParameter("@now", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); + + using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false)) + { + while (await reader.ReadAsync().ConfigureAwait(false)) + { + var item = new GetUserPermissions( + reader.IsDBNull(0) ? null : reader.GetFieldValue(0), + reader.IsDBNull(1) ? null : reader.GetFieldValue(1), + reader.IsDBNull(2) ? null : reader.GetFieldValue(2), + reader.IsDBNull(3) ? null : reader.GetFieldValue(3), + reader.IsDBNull(4) ? null : reader.GetFieldValue(4), + reader.IsDBNull(5) ? null : reader.GetFieldValue(5), + reader.IsDBNull(6) ? null : reader.GetFieldValue(6), + reader.IsDBNull(7) ? null : reader.GetFieldValue(7), + reader.IsDBNull(8) ? null : reader.GetFieldValue(8) + ); + results.Add(item); + } + } + } + + return new Result, SqlError>.Ok, SqlError>(results.ToImmutable()); + } + catch (Exception ex) + { + return new Result, SqlError>.Error, SqlError>(new SqlError("Database error", ex)); + } + } +} + +/// +/// Result row for 'GetUserPermissions' query. +/// +public record GetUserPermissions +{ + /// Column 'id'. + public string id { get; init; } + + /// Column 'code'. + public string code { get; init; } + + /// Column 'resource_type'. + public string resource_type { get; init; } + + /// Column 'action'. + public string action { get; init; } + + /// Column 'description'. + public string description { get; init; } + + /// Column 'source_name'. + public string source_name { get; init; } + + /// Column 'source_type'. + public string source_type { get; init; } + + /// Column 'scope_type'. + public byte[] scope_type { get; init; } + + /// Column 'scope_value'. + public byte[] scope_value { get; init; } + + /// Initializes a new instance of GetUserPermissions. + public GetUserPermissions( + string id, + string code, + string resource_type, + string action, + string description, + string source_name, + string source_type, + byte[] scope_type, + byte[] scope_value + ) + { + this.id = id; + this.code = code; + this.resource_type = resource_type; + this.action = action; + this.description = description; + this.source_name = source_name; + this.source_type = source_type; + this.scope_type = scope_type; + this.scope_value = scope_value; + } +} diff --git a/Gatekeeper/Gatekeeper.Api/Generated/GetUserRoles.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/GetUserRoles.g.cs new file mode 100644 index 0000000..ed3f6ea --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api/Generated/GetUserRoles.g.cs @@ -0,0 +1,114 @@ +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Threading.Tasks; +using Npgsql; +using Outcome; +using Selecta; + +namespace Generated; + +/// +/// Extension methods for 'GetUserRoles'. +/// +public static partial class GetUserRolesExtensions +{ + /// + /// Executes 'GetUserRoles.sql' and maps results. + /// + /// Open NpgsqlConnection connection. + /// Query parameter. + /// Query parameter. + /// Result of records or SQL error. + public static async Task, SqlError>> GetUserRolesAsync(this NpgsqlConnection connection, object user_id, object now) + { + const string sql = @"-- name: GetUserRoles +SELECT r.id, r.name, r.description, r.is_system, ur.granted_at, ur.expires_at +FROM gk_user_role ur +JOIN gk_role r ON ur.role_id = r.id +WHERE ur.user_id = @user_id + AND (ur.expires_at IS NULL OR ur.expires_at > @now); +"; + + try + { + var results = ImmutableList.CreateBuilder(); + + using (var command = new NpgsqlCommand(sql, connection)) + { + if (user_id is not null and not DBNull) + command.Parameters.AddWithValue("@user_id", user_id); + else + command.Parameters.Add(new NpgsqlParameter("@user_id", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); + if (now is not null and not DBNull) + command.Parameters.AddWithValue("@now", now); + else + command.Parameters.Add(new NpgsqlParameter("@now", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); + + using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false)) + { + while (await reader.ReadAsync().ConfigureAwait(false)) + { + var item = new GetUserRoles( + reader.IsDBNull(0) ? null : reader.GetFieldValue(0), + reader.IsDBNull(1) ? null : reader.GetFieldValue(1), + reader.IsDBNull(2) ? null : reader.GetFieldValue(2), + reader.IsDBNull(3) ? null : reader.GetFieldValue(3), + reader.IsDBNull(4) ? null : reader.GetFieldValue(4), + reader.IsDBNull(5) ? null : reader.GetFieldValue(5) + ); + results.Add(item); + } + } + } + + return new Result, SqlError>.Ok, SqlError>(results.ToImmutable()); + } + catch (Exception ex) + { + return new Result, SqlError>.Error, SqlError>(new SqlError("Database error", ex)); + } + } +} + +/// +/// Result row for 'GetUserRoles' query. +/// +public record GetUserRoles +{ + /// Column 'id'. + public string id { get; init; } + + /// Column 'name'. + public string name { get; init; } + + /// Column 'description'. + public string description { get; init; } + + /// Column 'is_system'. + public bool? is_system { get; init; } + + /// Column 'granted_at'. + public string granted_at { get; init; } + + /// Column 'expires_at'. + public string expires_at { get; init; } + + /// Initializes a new instance of GetUserRoles. + public GetUserRoles( + string id, + string name, + string description, + bool? is_system, + string granted_at, + string expires_at + ) + { + this.id = id; + this.name = name; + this.description = description; + this.is_system = is_system; + this.granted_at = granted_at; + this.expires_at = expires_at; + } +} diff --git a/Gatekeeper/Gatekeeper.Api/Generated/RevokeSession.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/RevokeSession.g.cs new file mode 100644 index 0000000..7bd6353 --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api/Generated/RevokeSession.g.cs @@ -0,0 +1,82 @@ +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Threading.Tasks; +using Npgsql; +using Outcome; +using Selecta; + +namespace Generated; + +/// +/// Extension methods for 'RevokeSession'. +/// +public static partial class RevokeSessionExtensions +{ + /// + /// Executes 'RevokeSession.sql' and maps results. + /// + /// Open NpgsqlConnection connection. + /// Query parameter. + /// Result of records or SQL error. + public static async Task, SqlError>> RevokeSessionAsync(this NpgsqlConnection connection, object jti) + { + const string sql = @"-- Revokes a session by setting is_revoked = true +-- @jti: The session ID (JWT ID) to revoke +UPDATE gk_session SET is_revoked = true WHERE id = @jti RETURNING id, is_revoked; +"; + + try + { + var results = ImmutableList.CreateBuilder(); + + using (var command = new NpgsqlCommand(sql, connection)) + { + if (jti is not null and not DBNull) + command.Parameters.AddWithValue("@jti", jti); + else + command.Parameters.Add(new NpgsqlParameter("@jti", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); + + using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false)) + { + while (await reader.ReadAsync().ConfigureAwait(false)) + { + var item = new RevokeSession( + reader.IsDBNull(0) ? null : reader.GetFieldValue(0), + reader.IsDBNull(1) ? null : reader.GetFieldValue(1) + ); + results.Add(item); + } + } + } + + return new Result, SqlError>.Ok, SqlError>(results.ToImmutable()); + } + catch (Exception ex) + { + return new Result, SqlError>.Error, SqlError>(new SqlError("Database error", ex)); + } + } +} + +/// +/// Result row for 'RevokeSession' query. +/// +public record RevokeSession +{ + /// Column 'id'. + public string id { get; init; } + + /// Column 'is_revoked'. + public bool? is_revoked { get; init; } + + /// Initializes a new instance of RevokeSession. + public RevokeSession( + string id, + bool? is_revoked + ) + { + this.id = id; + this.is_revoked = is_revoked; + } +} diff --git a/Gatekeeper/Gatekeeper.Api/Generated/gk_challengeOperations.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/gk_challengeOperations.g.cs new file mode 100644 index 0000000..575f8f2 --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api/Generated/gk_challengeOperations.g.cs @@ -0,0 +1,52 @@ +#nullable enable +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Data; +using System.Globalization; +using System.Threading.Tasks; +using Npgsql; +using Outcome; +using Selecta; + +namespace Generated +{ + /// + /// Extension methods for table operations on gk_challenge + /// + public static partial class gk_challengeExtensions + { + + /// + /// Inserts a new row into the gk_challenge table. + /// + public static async Task> Insertgk_challengeAsync(this IDbTransaction transaction, string? id, string? user_id, byte[] challenge, string? type, string? created_at, string? expires_at) + { + const string sql = "INSERT INTO gk_challenge (id, user_id, challenge, type, created_at, expires_at) VALUES (@id, @user_id, @challenge, @type, @created_at, @expires_at)"; + + if (transaction.Connection is null) + return new Result.Error(new SqlError("Transaction has no connection")); + + try + { + using (var command = new NpgsqlCommand(sql, (NpgsqlConnection)transaction.Connection!, (NpgsqlTransaction)transaction)) + { + command.Parameters.AddWithValue("@id", id ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@user_id", user_id ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@challenge", challenge ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@type", type ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@created_at", created_at ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@expires_at", expires_at ?? (object)DBNull.Value); + + var rowsAffected = await command.ExecuteNonQueryAsync().ConfigureAwait(false); + return new Result.Ok(rowsAffected); + } + } + catch (Exception ex) + { + return new Result.Error(new SqlError("Insert failed", ex)); + } + } + + } +} diff --git a/Gatekeeper/Gatekeeper.Api/Generated/gk_credentialOperations.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/gk_credentialOperations.g.cs new file mode 100644 index 0000000..7fe648c --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api/Generated/gk_credentialOperations.g.cs @@ -0,0 +1,59 @@ +#nullable enable +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Data; +using System.Globalization; +using System.Threading.Tasks; +using Npgsql; +using Outcome; +using Selecta; + +namespace Generated +{ + /// + /// Extension methods for table operations on gk_credential + /// + public static partial class gk_credentialExtensions + { + + /// + /// Inserts a new row into the gk_credential table. + /// + public static async Task> Insertgk_credentialAsync(this IDbTransaction transaction, string? id, string? user_id, byte[] public_key, long? sign_count, string? aaguid, string? credential_type, string? transports, string? attestation_format, string? created_at, string? last_used_at, string? device_name, bool? is_backup_eligible, bool? is_backed_up) + { + const string sql = "INSERT INTO gk_credential (id, user_id, public_key, sign_count, aaguid, credential_type, transports, attestation_format, created_at, last_used_at, device_name, is_backup_eligible, is_backed_up) VALUES (@id, @user_id, @public_key, @sign_count, @aaguid, @credential_type, @transports, @attestation_format, @created_at, @last_used_at, @device_name, @is_backup_eligible, @is_backed_up)"; + + if (transaction.Connection is null) + return new Result.Error(new SqlError("Transaction has no connection")); + + try + { + using (var command = new NpgsqlCommand(sql, (NpgsqlConnection)transaction.Connection!, (NpgsqlTransaction)transaction)) + { + command.Parameters.AddWithValue("@id", id ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@user_id", user_id ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@public_key", public_key ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@sign_count", sign_count ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@aaguid", aaguid ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@credential_type", credential_type ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@transports", transports ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@attestation_format", attestation_format ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@created_at", created_at ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@last_used_at", last_used_at ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@device_name", device_name ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@is_backup_eligible", is_backup_eligible ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@is_backed_up", is_backed_up ?? (object)DBNull.Value); + + var rowsAffected = await command.ExecuteNonQueryAsync().ConfigureAwait(false); + return new Result.Ok(rowsAffected); + } + } + catch (Exception ex) + { + return new Result.Error(new SqlError("Insert failed", ex)); + } + } + + } +} diff --git a/Gatekeeper/Gatekeeper.Api/Generated/gk_permissionOperations.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/gk_permissionOperations.g.cs new file mode 100644 index 0000000..c635e21 --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api/Generated/gk_permissionOperations.g.cs @@ -0,0 +1,52 @@ +#nullable enable +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Data; +using System.Globalization; +using System.Threading.Tasks; +using Npgsql; +using Outcome; +using Selecta; + +namespace Generated +{ + /// + /// Extension methods for table operations on gk_permission + /// + public static partial class gk_permissionExtensions + { + + /// + /// Inserts a new row into the gk_permission table. + /// + public static async Task> Insertgk_permissionAsync(this IDbTransaction transaction, string? id, string? code, string? resource_type, string? action, string? description, string? created_at) + { + const string sql = "INSERT INTO gk_permission (id, code, resource_type, action, description, created_at) VALUES (@id, @code, @resource_type, @action, @description, @created_at)"; + + if (transaction.Connection is null) + return new Result.Error(new SqlError("Transaction has no connection")); + + try + { + using (var command = new NpgsqlCommand(sql, (NpgsqlConnection)transaction.Connection!, (NpgsqlTransaction)transaction)) + { + command.Parameters.AddWithValue("@id", id ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@code", code ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@resource_type", resource_type ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@action", action ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@description", description ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@created_at", created_at ?? (object)DBNull.Value); + + var rowsAffected = await command.ExecuteNonQueryAsync().ConfigureAwait(false); + return new Result.Ok(rowsAffected); + } + } + catch (Exception ex) + { + return new Result.Error(new SqlError("Insert failed", ex)); + } + } + + } +} diff --git a/Gatekeeper/Gatekeeper.Api/Generated/gk_resource_grantOperations.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/gk_resource_grantOperations.g.cs new file mode 100644 index 0000000..4b3aada --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api/Generated/gk_resource_grantOperations.g.cs @@ -0,0 +1,54 @@ +#nullable enable +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Data; +using System.Globalization; +using System.Threading.Tasks; +using Npgsql; +using Outcome; +using Selecta; + +namespace Generated +{ + /// + /// Extension methods for table operations on gk_resource_grant + /// + public static partial class gk_resource_grantExtensions + { + + /// + /// Inserts a new row into the gk_resource_grant table. + /// + public static async Task> Insertgk_resource_grantAsync(this IDbTransaction transaction, string? id, string? user_id, string? resource_type, string? resource_id, string? permission_id, string? granted_at, string? granted_by, string? expires_at) + { + const string sql = "INSERT INTO gk_resource_grant (id, user_id, resource_type, resource_id, permission_id, granted_at, granted_by, expires_at) VALUES (@id, @user_id, @resource_type, @resource_id, @permission_id, @granted_at, @granted_by, @expires_at)"; + + if (transaction.Connection is null) + return new Result.Error(new SqlError("Transaction has no connection")); + + try + { + using (var command = new NpgsqlCommand(sql, (NpgsqlConnection)transaction.Connection!, (NpgsqlTransaction)transaction)) + { + command.Parameters.AddWithValue("@id", id ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@user_id", user_id ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@resource_type", resource_type ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@resource_id", resource_id ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@permission_id", permission_id ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@granted_at", granted_at ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@granted_by", granted_by ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@expires_at", expires_at ?? (object)DBNull.Value); + + var rowsAffected = await command.ExecuteNonQueryAsync().ConfigureAwait(false); + return new Result.Ok(rowsAffected); + } + } + catch (Exception ex) + { + return new Result.Error(new SqlError("Insert failed", ex)); + } + } + + } +} diff --git a/Gatekeeper/Gatekeeper.Api/Generated/gk_roleOperations.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/gk_roleOperations.g.cs new file mode 100644 index 0000000..8223b8a --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api/Generated/gk_roleOperations.g.cs @@ -0,0 +1,52 @@ +#nullable enable +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Data; +using System.Globalization; +using System.Threading.Tasks; +using Npgsql; +using Outcome; +using Selecta; + +namespace Generated +{ + /// + /// Extension methods for table operations on gk_role + /// + public static partial class gk_roleExtensions + { + + /// + /// Inserts a new row into the gk_role table. + /// + public static async Task> Insertgk_roleAsync(this IDbTransaction transaction, string? id, string? name, string? description, bool? is_system, string? created_at, string? parent_role_id) + { + const string sql = "INSERT INTO gk_role (id, name, description, is_system, created_at, parent_role_id) VALUES (@id, @name, @description, @is_system, @created_at, @parent_role_id)"; + + if (transaction.Connection is null) + return new Result.Error(new SqlError("Transaction has no connection")); + + try + { + using (var command = new NpgsqlCommand(sql, (NpgsqlConnection)transaction.Connection!, (NpgsqlTransaction)transaction)) + { + command.Parameters.AddWithValue("@id", id ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@name", name ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@description", description ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@is_system", is_system ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@created_at", created_at ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@parent_role_id", parent_role_id ?? (object)DBNull.Value); + + var rowsAffected = await command.ExecuteNonQueryAsync().ConfigureAwait(false); + return new Result.Ok(rowsAffected); + } + } + catch (Exception ex) + { + return new Result.Error(new SqlError("Insert failed", ex)); + } + } + + } +} diff --git a/Gatekeeper/Gatekeeper.Api/Generated/gk_role_permissionOperations.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/gk_role_permissionOperations.g.cs new file mode 100644 index 0000000..7b7c600 --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api/Generated/gk_role_permissionOperations.g.cs @@ -0,0 +1,49 @@ +#nullable enable +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Data; +using System.Globalization; +using System.Threading.Tasks; +using Npgsql; +using Outcome; +using Selecta; + +namespace Generated +{ + /// + /// Extension methods for table operations on gk_role_permission + /// + public static partial class gk_role_permissionExtensions + { + + /// + /// Inserts a new row into the gk_role_permission table. + /// + public static async Task> Insertgk_role_permissionAsync(this IDbTransaction transaction, string? role_id, string? permission_id, string? granted_at) + { + const string sql = "INSERT INTO gk_role_permission (role_id, permission_id, granted_at) VALUES (@role_id, @permission_id, @granted_at)"; + + if (transaction.Connection is null) + return new Result.Error(new SqlError("Transaction has no connection")); + + try + { + using (var command = new NpgsqlCommand(sql, (NpgsqlConnection)transaction.Connection!, (NpgsqlTransaction)transaction)) + { + command.Parameters.AddWithValue("@role_id", role_id ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@permission_id", permission_id ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@granted_at", granted_at ?? (object)DBNull.Value); + + var rowsAffected = await command.ExecuteNonQueryAsync().ConfigureAwait(false); + return new Result.Ok(rowsAffected); + } + } + catch (Exception ex) + { + return new Result.Error(new SqlError("Insert failed", ex)); + } + } + + } +} diff --git a/Gatekeeper/Gatekeeper.Api/Generated/gk_sessionOperations.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/gk_sessionOperations.g.cs new file mode 100644 index 0000000..11ab2c7 --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api/Generated/gk_sessionOperations.g.cs @@ -0,0 +1,90 @@ +#nullable enable +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Data; +using System.Globalization; +using System.Threading.Tasks; +using Npgsql; +using Outcome; +using Selecta; + +namespace Generated +{ + /// + /// Extension methods for table operations on gk_session + /// + public static partial class gk_sessionExtensions + { + + /// + /// Inserts a new row into the gk_session table. + /// + public static async Task> Insertgk_sessionAsync(this IDbTransaction transaction, string? id, string? user_id, string? credential_id, string? created_at, string? expires_at, string? last_activity_at, string? ip_address, string? user_agent, bool? is_revoked) + { + const string sql = "INSERT INTO gk_session (id, user_id, credential_id, created_at, expires_at, last_activity_at, ip_address, user_agent, is_revoked) VALUES (@id, @user_id, @credential_id, @created_at, @expires_at, @last_activity_at, @ip_address, @user_agent, @is_revoked)"; + + if (transaction.Connection is null) + return new Result.Error(new SqlError("Transaction has no connection")); + + try + { + using (var command = new NpgsqlCommand(sql, (NpgsqlConnection)transaction.Connection!, (NpgsqlTransaction)transaction)) + { + command.Parameters.AddWithValue("@id", id ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@user_id", user_id ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@credential_id", credential_id ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@created_at", created_at ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@expires_at", expires_at ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@last_activity_at", last_activity_at ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@ip_address", ip_address ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@user_agent", user_agent ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@is_revoked", is_revoked ?? (object)DBNull.Value); + + var rowsAffected = await command.ExecuteNonQueryAsync().ConfigureAwait(false); + return new Result.Ok(rowsAffected); + } + } + catch (Exception ex) + { + return new Result.Error(new SqlError("Insert failed", ex)); + } + } + + + /// + /// Updates a row in the gk_session table. + /// + public static async Task> Updategk_sessionAsync(this IDbTransaction transaction, string id, string user_id, string credential_id, string created_at, string expires_at, string last_activity_at, string ip_address, string user_agent, bool? is_revoked) + { + const string sql = "UPDATE gk_session SET user_id = @user_id, credential_id = @credential_id, created_at = @created_at, expires_at = @expires_at, last_activity_at = @last_activity_at, ip_address = @ip_address, user_agent = @user_agent, is_revoked = @is_revoked WHERE id = @id"; + + if (transaction.Connection is null) + return new Result.Error(new SqlError("Transaction has no connection")); + + try + { + using (var command = new NpgsqlCommand(sql, (NpgsqlConnection)transaction.Connection!, (NpgsqlTransaction)transaction)) + { + command.Parameters.AddWithValue("@id", id ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@user_id", user_id ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@credential_id", credential_id ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@created_at", created_at ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@expires_at", expires_at ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@last_activity_at", last_activity_at ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@ip_address", ip_address ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@user_agent", user_agent ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@is_revoked", is_revoked ?? (object)DBNull.Value); + + var rowsAffected = await command.ExecuteNonQueryAsync().ConfigureAwait(false); + return new Result.Ok(rowsAffected); + } + } + catch (Exception ex) + { + return new Result.Error(new SqlError("Update failed", ex)); + } + } + + } +} diff --git a/Gatekeeper/Gatekeeper.Api/Generated/gk_userOperations.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/gk_userOperations.g.cs new file mode 100644 index 0000000..31b93cb --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api/Generated/gk_userOperations.g.cs @@ -0,0 +1,53 @@ +#nullable enable +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Data; +using System.Globalization; +using System.Threading.Tasks; +using Npgsql; +using Outcome; +using Selecta; + +namespace Generated +{ + /// + /// Extension methods for table operations on gk_user + /// + public static partial class gk_userExtensions + { + + /// + /// Inserts a new row into the gk_user table. + /// + public static async Task> Insertgk_userAsync(this IDbTransaction transaction, string? id, string? display_name, string? email, string? created_at, string? last_login_at, bool? is_active, string? metadata) + { + const string sql = "INSERT INTO gk_user (id, display_name, email, created_at, last_login_at, is_active, metadata) VALUES (@id, @display_name, @email, @created_at, @last_login_at, @is_active, @metadata)"; + + if (transaction.Connection is null) + return new Result.Error(new SqlError("Transaction has no connection")); + + try + { + using (var command = new NpgsqlCommand(sql, (NpgsqlConnection)transaction.Connection!, (NpgsqlTransaction)transaction)) + { + command.Parameters.AddWithValue("@id", id ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@display_name", display_name ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@email", email ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@created_at", created_at ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@last_login_at", last_login_at ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@is_active", is_active ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@metadata", metadata ?? (object)DBNull.Value); + + var rowsAffected = await command.ExecuteNonQueryAsync().ConfigureAwait(false); + return new Result.Ok(rowsAffected); + } + } + catch (Exception ex) + { + return new Result.Error(new SqlError("Insert failed", ex)); + } + } + + } +} diff --git a/Gatekeeper/Gatekeeper.Api/Generated/gk_user_roleOperations.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/gk_user_roleOperations.g.cs new file mode 100644 index 0000000..f283f89 --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api/Generated/gk_user_roleOperations.g.cs @@ -0,0 +1,51 @@ +#nullable enable +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Data; +using System.Globalization; +using System.Threading.Tasks; +using Npgsql; +using Outcome; +using Selecta; + +namespace Generated +{ + /// + /// Extension methods for table operations on gk_user_role + /// + public static partial class gk_user_roleExtensions + { + + /// + /// Inserts a new row into the gk_user_role table. + /// + public static async Task> Insertgk_user_roleAsync(this IDbTransaction transaction, string? user_id, string? role_id, string? granted_at, string? granted_by, string? expires_at) + { + const string sql = "INSERT INTO gk_user_role (user_id, role_id, granted_at, granted_by, expires_at) VALUES (@user_id, @role_id, @granted_at, @granted_by, @expires_at)"; + + if (transaction.Connection is null) + return new Result.Error(new SqlError("Transaction has no connection")); + + try + { + using (var command = new NpgsqlCommand(sql, (NpgsqlConnection)transaction.Connection!, (NpgsqlTransaction)transaction)) + { + command.Parameters.AddWithValue("@user_id", user_id ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@role_id", role_id ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@granted_at", granted_at ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@granted_by", granted_by ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@expires_at", expires_at ?? (object)DBNull.Value); + + var rowsAffected = await command.ExecuteNonQueryAsync().ConfigureAwait(false); + return new Result.Ok(rowsAffected); + } + } + catch (Exception ex) + { + return new Result.Error(new SqlError("Insert failed", ex)); + } + } + + } +} diff --git a/Gatekeeper/Gatekeeper.Api/GlobalUsings.cs b/Gatekeeper/Gatekeeper.Api/GlobalUsings.cs new file mode 100644 index 0000000..60d2c0d --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api/GlobalUsings.cs @@ -0,0 +1,59 @@ +#pragma warning disable IDE0005 // Using directive is unnecessary (some are unused but needed for tests) + +global using System; +global using System.Globalization; +global using System.Text.Json; +global using Fido2NetLib; +global using Fido2NetLib.Objects; +global using Generated; +global using Microsoft.Extensions.Logging; +global using Npgsql; +global using Outcome; +global using Selecta; +global using CheckResourceGrantOk = Outcome.Result< + System.Collections.Immutable.ImmutableList, + Selecta.SqlError +>.Ok, Selecta.SqlError>; +// Insert result type alias +global using GetChallengeByIdOk = Outcome.Result< + System.Collections.Immutable.ImmutableList, + Selecta.SqlError +>.Ok, Selecta.SqlError>; +// Additional query result type aliases +global using GetCredentialByIdOk = Outcome.Result< + System.Collections.Immutable.ImmutableList, + Selecta.SqlError +>.Ok, Selecta.SqlError>; +global using GetSessionRevokedError = Outcome.Result< + System.Collections.Immutable.ImmutableList, + Selecta.SqlError +>.Error, Selecta.SqlError>; +global using GetSessionRevokedOk = Outcome.Result< + System.Collections.Immutable.ImmutableList, + Selecta.SqlError +>.Ok, Selecta.SqlError>; +// Query result type aliases +global using GetUserByEmailOk = Outcome.Result< + System.Collections.Immutable.ImmutableList, + Selecta.SqlError +>.Ok, Selecta.SqlError>; +global using GetUserByIdOk = Outcome.Result< + System.Collections.Immutable.ImmutableList, + Selecta.SqlError +>.Ok, Selecta.SqlError>; +global using GetUserCredentialsError = Outcome.Result< + System.Collections.Immutable.ImmutableList, + Selecta.SqlError +>.Error, Selecta.SqlError>; +global using GetUserCredentialsOk = Outcome.Result< + System.Collections.Immutable.ImmutableList, + Selecta.SqlError +>.Ok, Selecta.SqlError>; +global using GetUserPermissionsOk = Outcome.Result< + System.Collections.Immutable.ImmutableList, + Selecta.SqlError +>.Ok, Selecta.SqlError>; +global using GetUserRolesOk = Outcome.Result< + System.Collections.Immutable.ImmutableList, + Selecta.SqlError +>.Ok, Selecta.SqlError>; diff --git a/Gatekeeper/Gatekeeper.Api/Program.cs b/Gatekeeper/Gatekeeper.Api/Program.cs new file mode 100644 index 0000000..27ab8cc --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api/Program.cs @@ -0,0 +1,716 @@ +#pragma warning disable IDE0037 // Use inferred member name + +using System.Text; +using Gatekeeper.Api; +using Microsoft.AspNetCore.Http.Json; +using InitError = Outcome.Result.Error; + +var builder = WebApplication.CreateBuilder(args); + +// File logging - use LOG_PATH env var or default to /tmp in containers +var logPath = + Environment.GetEnvironmentVariable("LOG_PATH") + ?? ( + Environment.GetEnvironmentVariable("DOTNET_RUNNING_IN_CONTAINER") == "true" + ? "/tmp/gatekeeper.log" + : Path.Combine(AppContext.BaseDirectory, "gatekeeper.log") + ); +builder.Logging.AddFileLogging(logPath); + +builder.Services.Configure(options => + options.SerializerOptions.PropertyNamingPolicy = null +); + +builder.Services.AddCors(options => + options.AddPolicy( + "Dashboard", + policy => policy.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod() + ) +); + +var serverDomain = builder.Configuration["Fido2:ServerDomain"] ?? "localhost"; +var serverName = builder.Configuration["Fido2:ServerName"] ?? "Gatekeeper"; +var origin = builder.Configuration["Fido2:Origin"] ?? "http://localhost:5173"; + +builder.Services.AddFido2(options => +{ + options.ServerDomain = serverDomain; + options.ServerName = serverName; + options.Origins = new HashSet { origin }; + options.TimestampDriftTolerance = 300000; +}); + +var connectionString = + builder.Configuration.GetConnectionString("Postgres") + ?? throw new InvalidOperationException("PostgreSQL connection string 'Postgres' is required"); + +builder.Services.AddSingleton(new DbConfig(connectionString)); + +var signingKeyBase64 = builder.Configuration["Jwt:SigningKey"]; +var signingKey = string.IsNullOrEmpty(signingKeyBase64) + ? new byte[32] // Default dev key (32 zeros) - MUST match Clinical/Scheduling APIs + : Convert.FromBase64String(signingKeyBase64); +builder.Services.AddSingleton(new JwtConfig(signingKey, TimeSpan.FromHours(24))); + +var app = builder.Build(); + +using (var conn = new NpgsqlConnection(connectionString)) +{ + conn.Open(); + if (DatabaseSetup.Initialize(conn, app.Logger) is InitError initErr) + Environment.FailFast(initErr.Value); +} + +app.UseCors("Dashboard"); + +static string Now() => DateTime.UtcNow.ToString("o", CultureInfo.InvariantCulture); + +static NpgsqlConnection OpenConnection(DbConfig db) +{ + var conn = new NpgsqlConnection(db.ConnectionString); + conn.Open(); + return conn; +} + +var authGroup = app.MapGroup("/auth").WithTags("Authentication"); + +authGroup.MapPost( + "/register/begin", + async (RegisterBeginRequest request, IFido2 fido2, DbConfig db, ILogger logger) => + { + try + { + using var conn = OpenConnection(db); + var now = Now(); + + var existingUser = await conn.GetUserByEmailAsync(request.Email).ConfigureAwait(false); + var isNewUser = existingUser is not GetUserByEmailOk { Value.Count: > 0 }; + var userId = isNewUser + ? Guid.NewGuid().ToString() + : ((GetUserByEmailOk)existingUser).Value[0].id; + + if (isNewUser) + { + await using var tx = await conn.BeginTransactionAsync().ConfigureAwait(false); + _ = await tx.Insertgk_userAsync( + userId, + request.DisplayName, + request.Email, + now, + null, + true, + null + ) + .ConfigureAwait(false); + await tx.CommitAsync().ConfigureAwait(false); + } + + var existingCredentials = await conn.GetUserCredentialsAsync(userId) + .ConfigureAwait(false); + var excludeCredentials = existingCredentials switch + { + GetUserCredentialsOk ok => ok + .Value.Select(c => new PublicKeyCredentialDescriptor(Base64Url.Decode(c.id))) + .ToList(), + GetUserCredentialsError _ => [], + }; + + var user = new Fido2User + { + Id = Encoding.UTF8.GetBytes(userId), + Name = request.Email, + DisplayName = request.DisplayName, + }; + // Don't restrict to platform authenticators only - allows security keys too + // Chrome on macOS can timeout with Platform-only restriction + var authSelector = new AuthenticatorSelection + { + ResidentKey = ResidentKeyRequirement.Required, + UserVerification = UserVerificationRequirement.Required, + }; + + var options = fido2.RequestNewCredential( + new RequestNewCredentialParams + { + User = user, + ExcludeCredentials = excludeCredentials, + AuthenticatorSelection = authSelector, + AttestationPreference = AttestationConveyancePreference.None, + } + ); + var challengeId = Guid.NewGuid().ToString(); + var challengeExpiry = DateTime + .UtcNow.AddMinutes(5) + .ToString("o", CultureInfo.InvariantCulture); + + await using var tx2 = await conn.BeginTransactionAsync().ConfigureAwait(false); + _ = await tx2.Insertgk_challengeAsync( + challengeId, + userId, + options.Challenge, + "registration", + now, + challengeExpiry + ) + .ConfigureAwait(false); + await tx2.CommitAsync().ConfigureAwait(false); + + return Results.Ok(new { ChallengeId = challengeId, OptionsJson = options.ToJson() }); + } + catch (Exception ex) + { + logger.LogError(ex, "Registration begin failed"); + return Results.Problem("Registration failed"); + } + } +); + +authGroup.MapPost( + "/login/begin", + async (IFido2 fido2, DbConfig db, ILogger logger) => + { + try + { + using var conn = OpenConnection(db); + var now = Now(); + + // Discoverable credentials: empty allowCredentials lets browser show all stored passkeys + // The credential contains userHandle which we use in /login/complete to identify the user + // See: https://webauthn.guide/ and fido2-net-lib docs + var options = fido2.GetAssertionOptions( + new GetAssertionOptionsParams + { + AllowedCredentials = [], // Empty = discoverable credentials + UserVerification = UserVerificationRequirement.Required, + } + ); + var challengeId = Guid.NewGuid().ToString(); + var challengeExpiry = DateTime + .UtcNow.AddMinutes(5) + .ToString("o", CultureInfo.InvariantCulture); + + await using var tx = await conn.BeginTransactionAsync().ConfigureAwait(false); + _ = await tx.Insertgk_challengeAsync( + challengeId, + null, // No user ID - discovered from credential in /login/complete + options.Challenge, + "authentication", + now, + challengeExpiry + ) + .ConfigureAwait(false); + await tx.CommitAsync().ConfigureAwait(false); + + return Results.Ok(new { ChallengeId = challengeId, OptionsJson = options.ToJson() }); + } + catch (Exception ex) + { + logger.LogError(ex, "Login begin failed"); + return Results.Problem("Login failed"); + } + } +); + +authGroup.MapPost( + "/register/complete", + async ( + RegisterCompleteRequest request, + IFido2 fido2, + DbConfig db, + JwtConfig jwtConfig, + ILogger logger + ) => + { + try + { + using var conn = OpenConnection(db); + var now = Now(); + + // Get the stored challenge + var challengeResult = await conn.GetChallengeByIdAsync(request.ChallengeId, now) + .ConfigureAwait(false); + if (challengeResult is not GetChallengeByIdOk { Value.Count: > 0 } challengeOk) + { + return Results.BadRequest(new { Error = "Challenge not found or expired" }); + } + + var storedChallenge = challengeOk.Value[0]; + if (string.IsNullOrEmpty(storedChallenge.user_id)) + { + return Results.BadRequest(new { Error = "Invalid challenge" }); + } + + // Parse the authenticator response + var options = CredentialCreateOptions.FromJson(request.OptionsJson); + + // Verify the attestation + var credentialResult = await fido2 + .MakeNewCredentialAsync( + new MakeNewCredentialParams + { + AttestationResponse = request.AttestationResponse, + OriginalOptions = options, + IsCredentialIdUniqueToUserCallback = async (args, ct) => + { + var existing = await conn.GetCredentialByIdAsync( + Base64Url.Encode(args.CredentialId) + ) + .ConfigureAwait(false); + return existing is not GetCredentialByIdOk { Value.Count: > 0 }; + }, + } + ) + .ConfigureAwait(false); + + var cred = credentialResult; + + // Store the credential - use base64url encoding to match WebAuthn spec + await using var tx = await conn.BeginTransactionAsync().ConfigureAwait(false); + _ = await tx.Insertgk_credentialAsync( + Base64Url.Encode(cred.Id), + storedChallenge.user_id, + cred.PublicKey, + cred.SignCount, + cred.AaGuid.ToString(), + cred.Type.ToString(), + cred.Transports != null ? string.Join(",", cred.Transports) : null, + cred.AttestationFormat, + now, + null, + request.DeviceName, + cred.IsBackupEligible, + cred.IsBackedUp + ) + .ConfigureAwait(false); + + // Assign default user role + _ = await tx.Insertgk_user_roleAsync( + storedChallenge.user_id, + "role-user", + now, + null, + null + ) + .ConfigureAwait(false); + + await tx.CommitAsync().ConfigureAwait(false); + + // Get user info for token + var userResult = await conn.GetUserByIdAsync(storedChallenge.user_id) + .ConfigureAwait(false); + var user = userResult is GetUserByIdOk { Value.Count: > 0 } userOk + ? userOk.Value[0] + : null; + + // Get user roles + var rolesResult = await conn.GetUserRolesAsync(storedChallenge.user_id, now) + .ConfigureAwait(false); + var roles = rolesResult is GetUserRolesOk rolesOk + ? rolesOk.Value.Select(r => r.name).ToList() + : []; + + // Generate JWT + var token = TokenService.CreateToken( + storedChallenge.user_id, + user?.display_name, + user?.email, + roles, + jwtConfig.SigningKey, + jwtConfig.TokenLifetime + ); + + return Results.Ok( + new + { + Token = token, + UserId = storedChallenge.user_id, + DisplayName = user?.display_name, + Email = user?.email, + Roles = roles, + } + ); + } + catch (Exception ex) + { + logger.LogError(ex, "Registration complete failed"); + return Results.Problem("Registration failed"); + } + } +); + +authGroup.MapPost( + "/login/complete", + async ( + LoginCompleteRequest request, + IFido2 fido2, + DbConfig db, + JwtConfig jwtConfig, + ILogger logger + ) => + { + try + { + using var conn = OpenConnection(db); + var now = Now(); + + // Get the stored challenge + var challengeResult = await conn.GetChallengeByIdAsync(request.ChallengeId, now) + .ConfigureAwait(false); + if (challengeResult is not GetChallengeByIdOk { Value.Count: > 0 } challengeOk) + { + return Results.BadRequest(new { Error = "Challenge not found or expired" }); + } + + var storedChallenge = challengeOk.Value[0]; + + var credentialId = request.AssertionResponse.Id; + logger.LogInformation("Login attempt - credential ID: {CredentialId}", credentialId); + var credResult = await conn.GetCredentialByIdAsync(credentialId).ConfigureAwait(false); + if (credResult is not GetCredentialByIdOk { Value.Count: > 0 } credOk) + { + logger.LogWarning("Credential not found for ID: {CredentialId}", credentialId); + return Results.BadRequest(new { Error = "Credential not found" }); + } + + var storedCred = credOk.Value[0]; + + // Parse the assertion options + var options = AssertionOptions.FromJson(request.OptionsJson); + + // Verify the assertion + var assertionResult = await fido2 + .MakeAssertionAsync( + new MakeAssertionParams + { + AssertionResponse = request.AssertionResponse, + OriginalOptions = options, + StoredPublicKey = storedCred.public_key, + StoredSignatureCounter = (uint)storedCred.sign_count, + IsUserHandleOwnerOfCredentialIdCallback = (args, _) => + { + var userIdFromHandle = Encoding.UTF8.GetString(args.UserHandle); + return Task.FromResult(storedCred.user_id == userIdFromHandle); + }, + } + ) + .ConfigureAwait(false); + + // Update sign count and last used + using var updateCmd = conn.CreateCommand(); + updateCmd.CommandText = + @" + UPDATE gk_credential + SET sign_count = @signCount, last_used_at = @now + WHERE id = @id"; + updateCmd.Parameters.AddWithValue("@signCount", (long)assertionResult.SignCount); + updateCmd.Parameters.AddWithValue("@now", now); + updateCmd.Parameters.AddWithValue("@id", credentialId); + await updateCmd.ExecuteNonQueryAsync().ConfigureAwait(false); + + // Update user last login + using var userUpdateCmd = conn.CreateCommand(); + userUpdateCmd.CommandText = "UPDATE gk_user SET last_login_at = @now WHERE id = @id"; + userUpdateCmd.Parameters.AddWithValue("@now", now); + userUpdateCmd.Parameters.AddWithValue("@id", storedCred.user_id); + await userUpdateCmd.ExecuteNonQueryAsync().ConfigureAwait(false); + + // Get user info for token + var userResult = await conn.GetUserByIdAsync(storedCred.user_id).ConfigureAwait(false); + var user = userResult is GetUserByIdOk { Value.Count: > 0 } userOk + ? userOk.Value[0] + : null; + + // Get user roles + var rolesResult = await conn.GetUserRolesAsync(storedCred.user_id, now) + .ConfigureAwait(false); + var roles = rolesResult is GetUserRolesOk rolesOk + ? rolesOk.Value.Select(r => r.name).ToList() + : []; + + // Generate JWT + var token = TokenService.CreateToken( + storedCred.user_id, + user?.display_name, + user?.email, + roles, + jwtConfig.SigningKey, + jwtConfig.TokenLifetime + ); + + return Results.Ok( + new + { + Token = token, + UserId = storedCred.user_id, + DisplayName = user?.display_name, + Email = user?.email, + Roles = roles, + } + ); + } + catch (Exception ex) + { + logger.LogError(ex, "Login complete failed"); + return Results.Problem("Login failed"); + } + } +); + +authGroup.MapGet( + "/session", + async (HttpContext ctx, DbConfig db, JwtConfig jwtConfig) => + { + var token = TokenService.ExtractBearerToken(ctx.Request.Headers.Authorization); + if (string.IsNullOrEmpty(token)) + { + return Results.Unauthorized(); + } + + using var conn = OpenConnection(db); + + var result = await TokenService + .ValidateTokenAsync(conn, token, jwtConfig.SigningKey, checkRevocation: true) + .ConfigureAwait(false); + if (result is not TokenService.TokenValidationOk ok) + { + return Results.Unauthorized(); + } + + return Results.Ok( + new + { + ok.Claims.UserId, + ok.Claims.DisplayName, + ok.Claims.Email, + ok.Claims.Roles, + ExpiresAt = DateTimeOffset + .FromUnixTimeSeconds(ok.Claims.Exp) + .ToString("o", CultureInfo.InvariantCulture), + } + ); + } +); + +authGroup.MapPost( + "/logout", + async (HttpContext ctx, DbConfig db, JwtConfig jwtConfig) => + { + var token = TokenService.ExtractBearerToken(ctx.Request.Headers.Authorization); + if (string.IsNullOrEmpty(token)) + { + return Results.Unauthorized(); + } + + using var conn = OpenConnection(db); + + var result = await TokenService + .ValidateTokenAsync(conn, token, jwtConfig.SigningKey, checkRevocation: false) + .ConfigureAwait(false); + if (result is TokenService.TokenValidationOk ok) + { + await TokenService.RevokeTokenAsync(conn, ok.Claims.Jti).ConfigureAwait(false); + } + + return Results.NoContent(); + } +); + +var authzGroup = app.MapGroup("/authz").WithTags("Authorization"); + +authzGroup.MapGet( + "/check", + async ( + string permission, + string? resourceType, + string? resourceId, + HttpContext ctx, + DbConfig db, + JwtConfig jwtConfig + ) => + { + var token = TokenService.ExtractBearerToken(ctx.Request.Headers.Authorization); + if (string.IsNullOrEmpty(token)) + { + return Results.Unauthorized(); + } + + using var conn = OpenConnection(db); + + var validateResult = await TokenService + .ValidateTokenAsync(conn, token, jwtConfig.SigningKey, checkRevocation: true) + .ConfigureAwait(false); + if (validateResult is not TokenService.TokenValidationOk ok) + { + return Results.Unauthorized(); + } + + var (allowed, reason) = await AuthorizationService + .CheckPermissionAsync( + conn, + ok.Claims.UserId, + permission, + resourceType, + resourceId, + Now() + ) + .ConfigureAwait(false); + return Results.Ok(new { Allowed = allowed, Reason = reason }); + } +); + +authzGroup.MapGet( + "/permissions", + async (HttpContext ctx, DbConfig db, JwtConfig jwtConfig) => + { + var token = TokenService.ExtractBearerToken(ctx.Request.Headers.Authorization); + if (string.IsNullOrEmpty(token)) + { + return Results.Unauthorized(); + } + + using var conn = OpenConnection(db); + + var validateResult = await TokenService + .ValidateTokenAsync(conn, token, jwtConfig.SigningKey, checkRevocation: true) + .ConfigureAwait(false); + if (validateResult is not TokenService.TokenValidationOk ok) + { + return Results.Unauthorized(); + } + + var permissionsResult = await conn.GetUserPermissionsAsync(ok.Claims.UserId, Now()) + .ConfigureAwait(false); + var permissions = permissionsResult is GetUserPermissionsOk permOk + ? permOk + .Value.Select(p => new + { + p.code, + p.source_name, + p.source_type, + p.scope_type, + p.scope_value, + }) + .ToList() + : []; + + return Results.Ok(new { Permissions = permissions }); + } +); + +authzGroup.MapPost( + "/evaluate", + async (EvaluateRequest request, HttpContext ctx, DbConfig db, JwtConfig jwtConfig) => + { + var token = TokenService.ExtractBearerToken(ctx.Request.Headers.Authorization); + if (string.IsNullOrEmpty(token)) + { + return Results.Unauthorized(); + } + + using var conn = OpenConnection(db); + + var validateResult = await TokenService + .ValidateTokenAsync(conn, token, jwtConfig.SigningKey, checkRevocation: true) + .ConfigureAwait(false); + if (validateResult is not TokenService.TokenValidationOk ok) + { + return Results.Unauthorized(); + } + + var now = Now(); + var results = new List(); + foreach (var check in request.Checks) + { + var (allowed, _) = await AuthorizationService + .CheckPermissionAsync( + conn, + ok.Claims.UserId, + check.Permission, + check.ResourceType, + check.ResourceId, + now + ) + .ConfigureAwait(false); + results.Add( + new + { + check.Permission, + check.ResourceId, + Allowed = allowed, + } + ); + } + + return Results.Ok(new { Results = results }); + } +); + +app.Run(); + +namespace Gatekeeper.Api +{ + /// + /// Program entry point marker for WebApplicationFactory. + /// + public partial class Program { } + + /// Database connection configuration. + public sealed record DbConfig(string ConnectionString); + + /// JWT signing configuration. + public sealed record JwtConfig(byte[] SigningKey, TimeSpan TokenLifetime); + + /// Request to begin passkey registration. + public sealed record RegisterBeginRequest(string Email, string DisplayName); + + /// Request to begin passkey login. + public sealed record LoginBeginRequest(string? Email); + + /// Request to evaluate multiple permissions. + public sealed record EvaluateRequest(List Checks); + + /// Single permission check. + public sealed record PermissionCheck( + string Permission, + string? ResourceType, + string? ResourceId + ); + + /// Request to complete passkey registration. + public sealed record RegisterCompleteRequest( + string ChallengeId, + string OptionsJson, + AuthenticatorAttestationRawResponse AttestationResponse, + string? DeviceName + ); + + /// Request to complete passkey login. + public sealed record LoginCompleteRequest( + string ChallengeId, + string OptionsJson, + AuthenticatorAssertionRawResponse AssertionResponse + ); + + /// Base64URL encoding utilities for WebAuthn credential IDs. + public static class Base64Url + { + /// Encodes bytes to base64url string. + public static string Encode(byte[] input) => + Convert + .ToBase64String(input) + .Replace("+", "-", StringComparison.Ordinal) + .Replace("/", "_", StringComparison.Ordinal) + .TrimEnd('='); + + /// Decodes base64url string to bytes. + public static byte[] Decode(string input) + { + var padded = input + .Replace("-", "+", StringComparison.Ordinal) + .Replace("_", "/", StringComparison.Ordinal); + var padding = (4 - (padded.Length % 4)) % 4; + padded += new string('=', padding); + return Convert.FromBase64String(padded); + } + } +} diff --git a/Gatekeeper/Gatekeeper.Api/Properties/launchSettings.json b/Gatekeeper/Gatekeeper.Api/Properties/launchSettings.json new file mode 100644 index 0000000..7b7463b --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api/Properties/launchSettings.json @@ -0,0 +1,14 @@ +{ + "profiles": { + "Gatekeeper.Api": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": false, + "applicationUrl": "http://localhost:5002", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development", + "ConnectionStrings__Postgres": "Host=localhost;Database=gatekeeper;Username=gatekeeper;Password=changeme" + } + } + } +} diff --git a/Gatekeeper/Gatekeeper.Api/Sql/CheckPermission.sql b/Gatekeeper/Gatekeeper.Api/Sql/CheckPermission.sql new file mode 100644 index 0000000..1af577b --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api/Sql/CheckPermission.sql @@ -0,0 +1,24 @@ +-- name: CheckPermission +-- Checks if user has a specific permission code (via roles or direct grant) +SELECT 1 AS has_permission +FROM gk_permission p +WHERE p.code = @permissionCode + AND ( + -- Check role permissions + EXISTS ( + SELECT 1 FROM gk_role_permission rp + JOIN gk_user_role ur ON rp.role_id = ur.role_id + WHERE rp.permission_id = p.id + AND ur.user_id = @userId + AND (ur.expires_at IS NULL OR ur.expires_at > @now) + ) + OR + -- Check direct permissions + EXISTS ( + SELECT 1 FROM gk_user_permission up + WHERE up.permission_id = p.id + AND up.user_id = @userId + AND (up.expires_at IS NULL OR up.expires_at > @now) + ) + ) +LIMIT 1; diff --git a/Gatekeeper/Gatekeeper.Api/Sql/CheckResourceGrant.sql b/Gatekeeper/Gatekeeper.Api/Sql/CheckResourceGrant.sql new file mode 100644 index 0000000..1d5f24f --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api/Sql/CheckResourceGrant.sql @@ -0,0 +1,10 @@ +-- name: CheckResourceGrant +SELECT rg.id, rg.user_id, rg.resource_type, rg.resource_id, rg.permission_id, + rg.granted_at, rg.granted_by, rg.expires_at, p.code as permission_code +FROM gk_resource_grant rg +JOIN gk_permission p ON rg.permission_id = p.id +WHERE rg.user_id = @user_id + AND rg.resource_type = @resource_type + AND rg.resource_id = @resource_id + AND p.code = @permission_code + AND (rg.expires_at IS NULL OR rg.expires_at > @now); diff --git a/Gatekeeper/Gatekeeper.Api/Sql/CountSystemRoles.sql b/Gatekeeper/Gatekeeper.Api/Sql/CountSystemRoles.sql new file mode 100644 index 0000000..e1e5836 --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api/Sql/CountSystemRoles.sql @@ -0,0 +1,2 @@ +-- name: CountSystemRoles +SELECT COUNT(*) as cnt FROM gk_role WHERE is_system = true; diff --git a/Gatekeeper/Gatekeeper.Api/Sql/GetActivePolicies.sql b/Gatekeeper/Gatekeeper.Api/Sql/GetActivePolicies.sql new file mode 100644 index 0000000..2e7800b --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api/Sql/GetActivePolicies.sql @@ -0,0 +1,7 @@ +-- name: GetActivePolicies +SELECT id, name, description, resource_type, action, condition, effect, priority +FROM gk_policy +WHERE is_active = true + AND (resource_type = @resource_type OR resource_type = '*') + AND (action = @action OR action = '*') +ORDER BY priority DESC; diff --git a/Gatekeeper/Gatekeeper.Api/Sql/GetAllPermissions.sql b/Gatekeeper/Gatekeeper.Api/Sql/GetAllPermissions.sql new file mode 100644 index 0000000..a2753da --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api/Sql/GetAllPermissions.sql @@ -0,0 +1,4 @@ +-- name: GetAllPermissions +SELECT id, code, resource_type, action, description, created_at +FROM gk_permission +ORDER BY resource_type, action; diff --git a/Gatekeeper/Gatekeeper.Api/Sql/GetAllRoles.sql b/Gatekeeper/Gatekeeper.Api/Sql/GetAllRoles.sql new file mode 100644 index 0000000..00a8e9b --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api/Sql/GetAllRoles.sql @@ -0,0 +1,4 @@ +-- name: GetAllRoles +SELECT id, name, description, is_system, created_at, parent_role_id +FROM gk_role +ORDER BY name; diff --git a/Gatekeeper/Gatekeeper.Api/Sql/GetAllUsers.sql b/Gatekeeper/Gatekeeper.Api/Sql/GetAllUsers.sql new file mode 100644 index 0000000..f3120c5 --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api/Sql/GetAllUsers.sql @@ -0,0 +1,4 @@ +-- name: GetAllUsers +SELECT id, display_name, email, created_at, last_login_at, is_active +FROM gk_user +ORDER BY display_name; diff --git a/Gatekeeper/Gatekeeper.Api/Sql/GetChallengeById.sql b/Gatekeeper/Gatekeeper.Api/Sql/GetChallengeById.sql new file mode 100644 index 0000000..ebb2cd0 --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api/Sql/GetChallengeById.sql @@ -0,0 +1,4 @@ +-- name: GetChallengeById +SELECT id, user_id, challenge, type, created_at, expires_at +FROM gk_challenge +WHERE id = @id AND expires_at > @now; diff --git a/Gatekeeper/Gatekeeper.Api/Sql/GetCredentialById.sql b/Gatekeeper/Gatekeeper.Api/Sql/GetCredentialById.sql new file mode 100644 index 0000000..07106e6 --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api/Sql/GetCredentialById.sql @@ -0,0 +1,7 @@ +-- name: GetCredentialById +SELECT c.id, c.user_id, c.public_key, c.sign_count, c.aaguid, c.credential_type, c.transports, + c.attestation_format, c.created_at, c.last_used_at, c.device_name, c.is_backup_eligible, c.is_backed_up, + u.display_name, u.email +FROM gk_credential c +JOIN gk_user u ON c.user_id = u.id +WHERE c.id = @id AND u.is_active = true; diff --git a/Gatekeeper/Gatekeeper.Api/Sql/GetCredentialsByUserId.sql b/Gatekeeper/Gatekeeper.Api/Sql/GetCredentialsByUserId.sql new file mode 100644 index 0000000..2e4ccf2 --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api/Sql/GetCredentialsByUserId.sql @@ -0,0 +1,6 @@ +-- name: GetCredentialsByUserId +SELECT id, user_id, public_key, sign_count, aaguid, credential_type, transports, + attestation_format, created_at, last_used_at, device_name, + is_backup_eligible, is_backed_up +FROM gk_credential +WHERE user_id = @userId; diff --git a/Gatekeeper/Gatekeeper.Api/Sql/GetPermissionByCode.sql b/Gatekeeper/Gatekeeper.Api/Sql/GetPermissionByCode.sql new file mode 100644 index 0000000..cfd75b9 --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api/Sql/GetPermissionByCode.sql @@ -0,0 +1,4 @@ +-- name: GetPermissionByCode +SELECT id, code, resource_type, action, description, created_at +FROM gk_permission +WHERE code = @code; diff --git a/Gatekeeper/Gatekeeper.Api/Sql/GetRolePermissions.sql b/Gatekeeper/Gatekeeper.Api/Sql/GetRolePermissions.sql new file mode 100644 index 0000000..6b80a6c --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api/Sql/GetRolePermissions.sql @@ -0,0 +1,6 @@ +-- name: GetRolePermissions +SELECT p.id, p.code, p.resource_type, p.action, p.description, p.created_at, + rp.granted_at +FROM gk_permission p +JOIN gk_role_permission rp ON p.id = rp.permission_id +WHERE rp.role_id = @roleId; diff --git a/Gatekeeper/Gatekeeper.Api/Sql/GetSessionById.sql b/Gatekeeper/Gatekeeper.Api/Sql/GetSessionById.sql new file mode 100644 index 0000000..27cf52b --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api/Sql/GetSessionById.sql @@ -0,0 +1,7 @@ +-- name: GetSessionById +SELECT s.id, s.user_id, s.credential_id, s.created_at, s.expires_at, s.last_activity_at, + s.ip_address, s.user_agent, s.is_revoked, + u.display_name, u.email +FROM gk_session s +JOIN gk_user u ON s.user_id = u.id +WHERE s.id = @id AND s.is_revoked = false AND s.expires_at > @now AND u.is_active = true; diff --git a/Gatekeeper/Gatekeeper.Api/Sql/GetSessionForRevoke.sql b/Gatekeeper/Gatekeeper.Api/Sql/GetSessionForRevoke.sql new file mode 100644 index 0000000..19e281e --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api/Sql/GetSessionForRevoke.sql @@ -0,0 +1,6 @@ +-- Gets a session for revocation (no filters) +-- @jti: The session ID (JWT ID) to get +SELECT id, user_id, credential_id, created_at, expires_at, last_activity_at, + ip_address, user_agent, is_revoked +FROM gk_session +WHERE id = @jti; diff --git a/Gatekeeper/Gatekeeper.Api/Sql/GetSessionRevoked.sql b/Gatekeeper/Gatekeeper.Api/Sql/GetSessionRevoked.sql new file mode 100644 index 0000000..58f8e00 --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api/Sql/GetSessionRevoked.sql @@ -0,0 +1,3 @@ +-- Gets the revocation status of a session +-- @jti: The session ID (JWT ID) to check +SELECT is_revoked FROM gk_session WHERE id = @jti; diff --git a/Gatekeeper/Gatekeeper.Api/Sql/GetUserByEmail.sql b/Gatekeeper/Gatekeeper.Api/Sql/GetUserByEmail.sql new file mode 100644 index 0000000..3d2ed92 --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api/Sql/GetUserByEmail.sql @@ -0,0 +1,4 @@ +-- name: GetUserByEmail +SELECT id, display_name, email, created_at, last_login_at, is_active, metadata +FROM gk_user +WHERE email = @email AND is_active = true; diff --git a/Gatekeeper/Gatekeeper.Api/Sql/GetUserById.sql b/Gatekeeper/Gatekeeper.Api/Sql/GetUserById.sql new file mode 100644 index 0000000..c442b58 --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api/Sql/GetUserById.sql @@ -0,0 +1,4 @@ +-- name: GetUserById +SELECT id, display_name, email, created_at, last_login_at, is_active, metadata +FROM gk_user +WHERE id = @id; diff --git a/Gatekeeper/Gatekeeper.Api/Sql/GetUserCredentials.sql b/Gatekeeper/Gatekeeper.Api/Sql/GetUserCredentials.sql new file mode 100644 index 0000000..d47001c --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api/Sql/GetUserCredentials.sql @@ -0,0 +1,5 @@ +-- name: GetUserCredentials +SELECT id, user_id, public_key, sign_count, aaguid, credential_type, transports, + attestation_format, created_at, last_used_at, device_name, is_backup_eligible, is_backed_up +FROM gk_credential +WHERE user_id = @user_id; diff --git a/Gatekeeper/Gatekeeper.Api/Sql/GetUserPermissions.sql b/Gatekeeper/Gatekeeper.Api/Sql/GetUserPermissions.sql new file mode 100644 index 0000000..249de39 --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api/Sql/GetUserPermissions.sql @@ -0,0 +1,26 @@ +-- name: GetUserPermissions +-- Returns all permissions for a user: from roles + direct grants +-- Note: source_type column uses role name prefix to indicate source (role-based vs direct) +SELECT DISTINCT p.id, p.code, p.resource_type, p.action, p.description, + r.name as source_name, + ur.role_id as source_type, + NULL as scope_type, + NULL as scope_value +FROM gk_user_role ur +JOIN gk_role r ON ur.role_id = r.id +JOIN gk_role_permission rp ON r.id = rp.role_id +JOIN gk_permission p ON rp.permission_id = p.id +WHERE ur.user_id = @user_id + AND (ur.expires_at IS NULL OR ur.expires_at > @now) + +UNION ALL + +SELECT p.id, p.code, p.resource_type, p.action, p.description, + p.code as source_name, + up.permission_id as source_type, + COALESCE(up.scope_type, p.resource_type) as scope_type, + COALESCE(up.scope_value, p.action) as scope_value +FROM gk_user_permission up +JOIN gk_permission p ON up.permission_id = p.id +WHERE up.user_id = @user_id + AND (up.expires_at IS NULL OR up.expires_at > @now); diff --git a/Gatekeeper/Gatekeeper.Api/Sql/GetUserRoles.sql b/Gatekeeper/Gatekeeper.Api/Sql/GetUserRoles.sql new file mode 100644 index 0000000..63b6b88 --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api/Sql/GetUserRoles.sql @@ -0,0 +1,6 @@ +-- name: GetUserRoles +SELECT r.id, r.name, r.description, r.is_system, ur.granted_at, ur.expires_at +FROM gk_user_role ur +JOIN gk_role r ON ur.role_id = r.id +WHERE ur.user_id = @user_id + AND (ur.expires_at IS NULL OR ur.expires_at > @now); diff --git a/Gatekeeper/Gatekeeper.Api/Sql/RevokeSession.sql b/Gatekeeper/Gatekeeper.Api/Sql/RevokeSession.sql new file mode 100644 index 0000000..71df552 --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api/Sql/RevokeSession.sql @@ -0,0 +1,3 @@ +-- Revokes a session by setting is_revoked = true +-- @jti: The session ID (JWT ID) to revoke +UPDATE gk_session SET is_revoked = true WHERE id = @jti RETURNING id, is_revoked; diff --git a/Gatekeeper/Gatekeeper.Api/TokenService.cs b/Gatekeeper/Gatekeeper.Api/TokenService.cs new file mode 100644 index 0000000..2947582 --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api/TokenService.cs @@ -0,0 +1,191 @@ +using System.Security.Cryptography; +using System.Text; + +namespace Gatekeeper.Api; + +/// +/// JWT token generation and validation service. +/// +public static class TokenService +{ + /// Token claims data. + public sealed record TokenClaims( + string UserId, + string? DisplayName, + string? Email, + IReadOnlyList Roles, + string Jti, + long Exp + ); + + /// Successful token validation result. + public sealed record TokenValidationOk(TokenClaims Claims); + + /// Failed token validation result. + public sealed record TokenValidationError(string Reason); + + /// + /// Extracts the token from a Bearer authorization header. + /// + public static string? ExtractBearerToken(string? authHeader) => + authHeader?.StartsWith("Bearer ", StringComparison.Ordinal) == true + ? authHeader["Bearer ".Length..] + : null; + + /// + /// Creates a JWT token for the given user. + /// + public static string CreateToken( + string userId, + string? displayName, + string? email, + IReadOnlyList roles, + byte[] signingKey, + TimeSpan lifetime + ) + { + var now = DateTimeOffset.UtcNow; + var exp = now.Add(lifetime); + var jti = Guid.NewGuid().ToString(); + + var header = Base64UrlEncode( + JsonSerializer.SerializeToUtf8Bytes(new { alg = "HS256", typ = "JWT" }) + ); + + var payload = Base64UrlEncode( + JsonSerializer.SerializeToUtf8Bytes( + new + { + sub = userId, + name = displayName, + email, + roles, + jti, + iat = now.ToUnixTimeSeconds(), + exp = exp.ToUnixTimeSeconds(), + } + ) + ); + + var signature = ComputeSignature(header, payload, signingKey); + return $"{header}.{payload}.{signature}"; + } + + /// + /// Validates a JWT token. + /// + public static async Task ValidateTokenAsync( + NpgsqlConnection conn, + string token, + byte[] signingKey, + bool checkRevocation, + ILogger? logger = null + ) + { + try + { + var parts = token.Split('.'); + if (parts.Length != 3) + { + return new TokenValidationError("Invalid token format"); + } + + var expectedSignature = ComputeSignature(parts[0], parts[1], signingKey); + if ( + !CryptographicOperations.FixedTimeEquals( + Encoding.UTF8.GetBytes(expectedSignature), + Encoding.UTF8.GetBytes(parts[2]) + ) + ) + { + return new TokenValidationError("Invalid signature"); + } + + var payloadBytes = Base64UrlDecode(parts[1]); + using var doc = JsonDocument.Parse(payloadBytes); + var root = doc.RootElement; + + var exp = root.GetProperty("exp").GetInt64(); + if (DateTimeOffset.UtcNow.ToUnixTimeSeconds() > exp) + { + return new TokenValidationError("Token expired"); + } + + var jti = root.GetProperty("jti").GetString() ?? string.Empty; + + if (checkRevocation) + { + var isRevoked = await IsTokenRevokedAsync(conn, jti).ConfigureAwait(false); + if (isRevoked) + { + return new TokenValidationError("Token revoked"); + } + } + + var roles = root.TryGetProperty("roles", out var rolesElement) + ? rolesElement.EnumerateArray().Select(e => e.GetString() ?? string.Empty).ToList() + : []; + + var claims = new TokenClaims( + UserId: root.GetProperty("sub").GetString() ?? string.Empty, + DisplayName: root.TryGetProperty("name", out var nameElem) + ? nameElem.GetString() + : null, + Email: root.TryGetProperty("email", out var emailElem) + ? emailElem.GetString() + : null, + Roles: roles, + Jti: jti, + Exp: exp + ); + + return new TokenValidationOk(claims); + } + catch (Exception ex) + { + logger?.LogError(ex, "Token validation failed"); + return new TokenValidationError("Token validation failed"); + } + } + + /// + /// Revokes a token by JTI using DataProvider generated method. + /// + public static async Task RevokeTokenAsync(NpgsqlConnection conn, string jti) => + _ = await conn.RevokeSessionAsync(jti).ConfigureAwait(false); + + private static async Task IsTokenRevokedAsync(NpgsqlConnection conn, string jti) + { + var result = await conn.GetSessionRevokedAsync(jti).ConfigureAwait(false); + return result switch + { + GetSessionRevokedOk ok => ok.Value.FirstOrDefault()?.is_revoked == true, + GetSessionRevokedError => false, + }; + } + + private static string Base64UrlEncode(byte[] input) => + Convert + .ToBase64String(input) + .Replace("+", "-", StringComparison.Ordinal) + .Replace("/", "_", StringComparison.Ordinal) + .TrimEnd('='); + + private static byte[] Base64UrlDecode(string input) + { + var padded = input + .Replace("-", "+", StringComparison.Ordinal) + .Replace("_", "/", StringComparison.Ordinal); + var padding = (4 - (padded.Length % 4)) % 4; + padded += new string('=', padding); + return Convert.FromBase64String(padded); + } + + private static string ComputeSignature(string header, string payload, byte[] key) + { + var data = Encoding.UTF8.GetBytes($"{header}.{payload}"); + using var hmac = new HMACSHA256(key); + var hash = hmac.ComputeHash(data); + return Base64UrlEncode(hash); + } +} diff --git a/Gatekeeper/Gatekeeper.Api/gatekeeper-schema.yaml b/Gatekeeper/Gatekeeper.Api/gatekeeper-schema.yaml new file mode 100644 index 0000000..809eb19 --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api/gatekeeper-schema.yaml @@ -0,0 +1,397 @@ +name: gatekeeper +tables: +- name: gk_user + columns: + - name: id + type: Text + - name: display_name + type: Text + - name: email + type: Text + - name: created_at + type: Text + - name: last_login_at + type: Text + - name: is_active + type: Boolean + defaultValue: "true" + - name: metadata + type: Json + indexes: + - name: idx_user_email + columns: + - email + isUnique: true + primaryKey: + name: PK_gk_user + columns: + - id +- name: gk_credential + columns: + - name: id + type: Text + - name: user_id + type: Text + - name: public_key + type: Blob + - name: sign_count + type: Int + defaultValue: 0 + - name: aaguid + type: Text + - name: credential_type + type: Text + - name: transports + type: Json + - name: attestation_format + type: Text + - name: created_at + type: Text + - name: last_used_at + type: Text + - name: device_name + type: Text + - name: is_backup_eligible + type: Boolean + - name: is_backed_up + type: Boolean + indexes: + - name: idx_credential_user + columns: + - user_id + foreignKeys: + - name: FK_gk_credential_user_id + columns: + - user_id + referencedTable: gk_user + referencedColumns: + - id + onDelete: Cascade + primaryKey: + name: PK_gk_credential + columns: + - id +- name: gk_session + columns: + - name: id + type: Text + - name: user_id + type: Text + - name: credential_id + type: Text + - name: created_at + type: Text + - name: expires_at + type: Text + - name: last_activity_at + type: Text + - name: ip_address + type: Text + - name: user_agent + type: Text + - name: is_revoked + type: Boolean + defaultValue: "false" + indexes: + - name: idx_session_user + columns: + - user_id + - name: idx_session_expires + columns: + - expires_at + foreignKeys: + - name: FK_gk_session_user_id + columns: + - user_id + referencedTable: gk_user + referencedColumns: + - id + onDelete: Cascade + - name: FK_gk_session_credential_id + columns: + - credential_id + referencedTable: gk_credential + referencedColumns: + - id + primaryKey: + name: PK_gk_session + columns: + - id +- name: gk_challenge + columns: + - name: id + type: Text + - name: user_id + type: Text + - name: challenge + type: Blob + - name: type + type: Text + - name: created_at + type: Text + - name: expires_at + type: Text + primaryKey: + name: PK_gk_challenge + columns: + - id +- name: gk_role + columns: + - name: id + type: Text + - name: name + type: Text + - name: description + type: Text + - name: is_system + type: Boolean + defaultValue: "false" + - name: created_at + type: Text + - name: parent_role_id + type: Text + indexes: + - name: idx_role_name + columns: + - name + isUnique: true + foreignKeys: + - name: FK_gk_role_parent_role_id + columns: + - parent_role_id + referencedTable: gk_role + referencedColumns: + - id + primaryKey: + name: PK_gk_role + columns: + - id +- name: gk_user_role + columns: + - name: user_id + type: Text + - name: role_id + type: Text + - name: granted_at + type: Text + - name: granted_by + type: Text + - name: expires_at + type: Text + foreignKeys: + - name: FK_gk_user_role_user_id + columns: + - user_id + referencedTable: gk_user + referencedColumns: + - id + onDelete: Cascade + - name: FK_gk_user_role_role_id + columns: + - role_id + referencedTable: gk_role + referencedColumns: + - id + onDelete: Cascade + - name: FK_gk_user_role_granted_by + columns: + - granted_by + referencedTable: gk_user + referencedColumns: + - id + primaryKey: + name: PK_gk_user_role + columns: + - user_id + - role_id +- name: gk_permission + columns: + - name: id + type: Text + - name: code + type: Text + - name: resource_type + type: Text + - name: action + type: Text + - name: description + type: Text + - name: created_at + type: Text + indexes: + - name: idx_permission_code + columns: + - code + isUnique: true + - name: idx_permission_resource + columns: + - resource_type + primaryKey: + name: PK_gk_permission + columns: + - id +- name: gk_role_permission + columns: + - name: role_id + type: Text + - name: permission_id + type: Text + - name: granted_at + type: Text + foreignKeys: + - name: FK_gk_role_permission_role_id + columns: + - role_id + referencedTable: gk_role + referencedColumns: + - id + onDelete: Cascade + - name: FK_gk_role_permission_permission_id + columns: + - permission_id + referencedTable: gk_permission + referencedColumns: + - id + onDelete: Cascade + primaryKey: + name: PK_gk_role_permission + columns: + - role_id + - permission_id +- name: gk_user_permission + columns: + - name: user_id + type: Text + - name: permission_id + type: Text + - name: scope_type + type: Text + - name: scope_value + type: Text + - name: granted_at + type: Text + - name: granted_by + type: Text + - name: expires_at + type: Text + - name: reason + type: Text + indexes: + - name: idx_user_permission + columns: + - user_id + - permission_id + - scope_value + isUnique: true + foreignKeys: + - name: FK_gk_user_permission_user_id + columns: + - user_id + referencedTable: gk_user + referencedColumns: + - id + onDelete: Cascade + - name: FK_gk_user_permission_permission_id + columns: + - permission_id + referencedTable: gk_permission + referencedColumns: + - id + onDelete: Cascade + - name: FK_gk_user_permission_granted_by + columns: + - granted_by + referencedTable: gk_user + referencedColumns: + - id +- name: gk_resource_grant + columns: + - name: id + type: Text + - name: user_id + type: Text + - name: resource_type + type: Text + - name: resource_id + type: Text + - name: permission_id + type: Text + - name: granted_at + type: Text + - name: granted_by + type: Text + - name: expires_at + type: Text + indexes: + - name: idx_resource_grant_user + columns: + - user_id + - name: idx_resource_grant_resource + columns: + - resource_type + - resource_id + foreignKeys: + - name: FK_gk_resource_grant_user_id + columns: + - user_id + referencedTable: gk_user + referencedColumns: + - id + onDelete: Cascade + - name: FK_gk_resource_grant_permission_id + columns: + - permission_id + referencedTable: gk_permission + referencedColumns: + - id + - name: FK_gk_resource_grant_granted_by + columns: + - granted_by + referencedTable: gk_user + referencedColumns: + - id + primaryKey: + name: PK_gk_resource_grant + columns: + - id + uniqueConstraints: + - name: uq_resource_grant + columns: + - user_id + - resource_type + - resource_id + - permission_id +- name: gk_policy + columns: + - name: id + type: Text + - name: name + type: Text + - name: description + type: Text + - name: resource_type + type: Text + - name: action + type: Text + - name: condition + type: Json + - name: effect + type: Text + defaultValue: "'allow'" + - name: priority + type: Int + defaultValue: 0 + - name: is_active + type: Boolean + defaultValue: "true" + - name: created_at + type: Text + indexes: + - name: idx_policy_name + columns: + - name + isUnique: true + primaryKey: + name: PK_gk_policy + columns: + - id diff --git a/Gatekeeper/Gatekeeper.Api/gatekeeper.db b/Gatekeeper/Gatekeeper.Api/gatekeeper.db new file mode 100644 index 0000000000000000000000000000000000000000..18d58e31a332d72dba0161d73aad2a4279dd0f1a GIT binary patch literal 147456 zcmeI)?Qh%09S3m952Bx)XSP*3(@O)FNW9bwiXdo#RkoSbh$AJAj3!kDf|eMSuq-Je z<=REJ!cLm)ZGi#9iUI43VFL=RuZz9f%kAaMgOR4a0dy0T%UvWAvT zEw39|PR@|mUe2+rIK{k{HST9GYq{WpW+=5(wIAt)x~BnzDIkm3Akc z(NZhfwM@G8($S_%6$Gb`R*k-*Ce*i<;xVUEwD;UcWfFC!)$pq9*pyk#B{}W656&v; zYYXv%3#^n=+zSnzS-0J4qh6q+8np79KYVNHRpY)!T-p}NQyDt8K|waG{uNDczh>w4 z`WZ#NN@`cz)n2F;qcxxPYu-$+-Q6^__6?w=I#kY1=?AZ$Qq+Zo_~A7ku|X3f?L95U zX^_z$DjuE9O8rpfYRx|KELOoIvw??cu4uc3x>Jj!73#LtEt+Wv>eo*v)Y}VPMm=aG z8}Q)p%;W3{MZI`2{&bu7yy4n)HepG}#qX0+zr`uqZFUfvgRL`Fo|8GAw6!n#Z|~I{ z0@ZQm@>xUPn6*ZZRKY5Xd8a+>H zr~jFe0*n_9g%!IFpFHhmi{qN^zU$dLd2Kn9SvOL2ZN8D(T+eC`t+H#A$dM;hu4dKk zir2hJ1+_)*8g!nu21H9aY2-pZ2;U~UkKE!+LQN&Rj2ykHShi;mUY%s~_i&M;7T&eW zWxGI4!MDxn9$lQtH>HdIYGbm-ST~O>a+- z+rxbPU{*w^YqL#->DNoT?Wauooetd;TJnlW_0y?EsQLQVxS}qS%7&%NC{s|=MCY1l z#&*?kXZ`VQMN#MH<4Dw|}BWNeDmy0uX=z1Rwwb2tWV=5P$##e*6Lxw265B z|M3qLS_lCMKmY;|fB*y_009U<00I!`LjceJec+)e1Rwwb2tWV=5P$##AOHafKwv-w z@aO*rWT4PY2tWV=5P$##AOHafKmY;|fIuGt`2ODq9*RN$0uX=z1Rwwb2tWV=5P$## z21EeQ{{u2mXeI<8009U<00Izz00bZa0SG{#4*~r7|32_g6ao-{00bZa0SG_<0uX=z z1RyXV0{H$vAOnSFLI45~fB*y_009U<00Izz00jCF!1I3}cqj@12tWV=5P$##AOHaf zKmY;|7!UzG{}0GOp_veX00bZa0SG_<0uX=z1Rwx`J_PXh|NFp0Q3yZ)0uX=z1Rwwb z2tWV=5P-md2;lqwfD9Cx2>}Q|00Izz00bZa0SG_<0ubm!0N?-nz(Y|8KmY;|fB*y_ z009U<00Izzz<>zg`~QFp6q*SE2tWV=5P$##AOHafKmY;|=tBU{|9#-0C#0uX=z1Rwwb2tWV=5P(1*0{H&l2Of$-00Izz z00bZa0SG_<0uX=z1O`L^-~R_>pwLVRKmY;|fB*y_009U<00IzzKpz75{@({4ib4Pa z5P$##AOHafKmY;|fB*yrL;%nK12Rx(CIlb=0SG_<0uX=z1Rwwb2tc3@0X+Zrfrp|H zfB*y_009U<00Izz00bZafdLV~-~S(wfkHDO009U<00Izz00bZa0SG_<0(}VJ`+pyJ zC<*}xKmY;|fB*y_009U<00Iyg5CMGuACQ4UGatWV=5P$##AOHafKmY=L2uzP% zicKq{v6+9*{&VJcQy-95=dX?0!wyV8REk({)QUc0+#Xzd$7OLeH6ozf3pKc%P(3-QBi%~=s{ zVx+yNr8tfDB@~CvO8rpfYRx|K0JaJqnGHNlb4A-N)SX%+tx&hEZqZCbkc|4!pKmX8 z8TFu%Y`}xVGmo<;6!qf8_|t9P^M-5J*@Pt>7r#$R{T8R_5VC_%-&<#@JSTHJX=`8f z-`=Y^1ghiA<+YHR%PWxPEYBlNDSF~)lc{yiiaNjh$@r5O zd8pCz{$*#R0ON&2Va2Y)Cr`WC;<%=}?|Sx5UR%y&){PWhn{T8x*R$F~tL)k&a^wk> zt66os;x%tlL2c2y2AyZE0nt)U8o5vp!ncX;BS&ufS5nC?BS)_)mhIVtS0~y0JzV6d zg?FuT*{+nRtoS`8@rqOaq~NT40`cQezUB4IG7)6Uv^XuTPq|*xm{RK3rV?t`02TGJ zzKWyi?Fn*wn2#UKiU@UWwy7}vdP%qalu5tSp_@WWUJim5Csm({wZ%lCcF=_Nd?F}MUT82ri7fED0Ryn*uYBK{u zedYsOwp`DoH>h35+Yc?tIj3e?#Ufd!U9oVpzE~wvl}I8pv2O2Hw{5ar>o662PcUKB zy5crb``Lg+X{4zeoNjZ^=stn3jwRHa^Iaw|k3qWd`oG63iRPv!i0YsPY;`7igA_#$ zx8NkpE+Q^SryUWXkKY_&8=j{b9&|y*NL8a!=mi;jtQ@t*R@o_-+cvqw`%8!GlqzPS z+Mt25md+YCjSaCtze1K4%PKWO@f=hY-8Xq;i|^K|buS1(%kym4v*_N*d|0jT1iSxs zD?STuf)Rd7Alt89r(m0rn+yr#EvvBIsF`-zDLLecNrW?Lu78$Xrcn!}f3Jb9Ums1V zT{nLrMH+I!VIn`QsCqKIys-eWcPyt&a?*nlfBfbBb&ypA8%<(MD7`>lKe!WTH~ho* zc#zQy{)LC6z~ZGt0Z??@TG`rGvJd0mj9!Gs~D4}+}J2Mr&r5YxW(PQ*cdRiHdor%8@oBh}9?(`q0A5Q&c zsyzAib6o{G6iB&BdRb;X}LN-(W@LE|9%m^}PiWytTSht&>}I`-PRPR6T-Uo=0uMe@RQI#$1&L@;I0@u0l*%6!fzC!XXbtI(Ecr&K@=5(8a+=3SER6QD}fRT zWX$wmy+~elkjBk*YMj4fi9)Q&TF-_x*E0WgN3<|)6k8=|{ZFhH6!prL_-`KZpo?ZE zj?sh{r67!+r&kXJBd>_>>O|(qCSIh5N(S!;!h1*lpc=Zp@}wg?$kU#;K1}hJN?Wle zWj}kpXjh~Pg3~_UGe4}g_8~+e)zYCGUH6igHUG97L`*n<+eI{83B-F=I&!+6I-gKC zuXLHTV)$A6&7Vs_H;msONW9GYm-imfssvtPsW)2?V zy*g(hi;+|Z?OmIzcb$RyikeXSexZ&JB0ty%k^jGM8P`wucpePqTIG2*wL>c`ti@*OLd7Q@q1Rwwb z2tWV=5P$##AOHafK;T#k;P3w*%V9;QAOHafKmY;|fB*y_009U<00I#KeE*Md-~a*; zfB*y_009U<00Izz00ba#ECulVe=LU;oq_-aAOHafKmY;|fB*y_009U@1n~SH;lKd| zAOHafKmY;|fB*y_009U<;8+Ua`TtlBD>?-M2tWV=5P$##AOHafKmY;|hzQ{S{} Date: Tue, 7 Apr 2026 13:47:09 +1000 Subject: [PATCH 02/59] Point to nuget packages --- Clinical/Clinical.Api/Clinical.Api.csproj | 12 ++++++------ Clinical/Clinical.Sync/Clinical.Sync.csproj | 4 ++-- .../Dashboard.Integration.Tests.csproj | 2 +- .../Gatekeeper.Api.Tests.csproj | 2 +- Gatekeeper/Gatekeeper.Api/Gatekeeper.Api.csproj | 17 +++++++---------- ICD10/ICD10.Api/ICD10.Api.csproj | 10 +++++----- Scheduling/Scheduling.Api/Scheduling.Api.csproj | 12 ++++++------ .../Scheduling.Sync/Scheduling.Sync.csproj | 4 ++-- 8 files changed, 30 insertions(+), 33 deletions(-) diff --git a/Clinical/Clinical.Api/Clinical.Api.csproj b/Clinical/Clinical.Api/Clinical.Api.csproj index 55ca32b..03fbf56 100644 --- a/Clinical/Clinical.Api/Clinical.Api.csproj +++ b/Clinical/Clinical.Api/Clinical.Api.csproj @@ -12,12 +12,12 @@ - - - - - - + + + + + + diff --git a/Clinical/Clinical.Sync/Clinical.Sync.csproj b/Clinical/Clinical.Sync/Clinical.Sync.csproj index 314a31d..afa685e 100644 --- a/Clinical/Clinical.Sync/Clinical.Sync.csproj +++ b/Clinical/Clinical.Sync/Clinical.Sync.csproj @@ -7,8 +7,8 @@ - - + + diff --git a/Dashboard/Dashboard.Integration.Tests/Dashboard.Integration.Tests.csproj b/Dashboard/Dashboard.Integration.Tests/Dashboard.Integration.Tests.csproj index 5ae22d2..24ee7f4 100644 --- a/Dashboard/Dashboard.Integration.Tests/Dashboard.Integration.Tests.csproj +++ b/Dashboard/Dashboard.Integration.Tests/Dashboard.Integration.Tests.csproj @@ -21,7 +21,6 @@ - @@ -29,6 +28,7 @@ + diff --git a/Gatekeeper/Gatekeeper.Api.Tests/Gatekeeper.Api.Tests.csproj b/Gatekeeper/Gatekeeper.Api.Tests/Gatekeeper.Api.Tests.csproj index 45a54eb..4f20821 100644 --- a/Gatekeeper/Gatekeeper.Api.Tests/Gatekeeper.Api.Tests.csproj +++ b/Gatekeeper/Gatekeeper.Api.Tests/Gatekeeper.Api.Tests.csproj @@ -15,6 +15,7 @@ + all runtime; build; native; contentfiles; analyzers; buildtransitive @@ -23,7 +24,6 @@ - diff --git a/Gatekeeper/Gatekeeper.Api/Gatekeeper.Api.csproj b/Gatekeeper/Gatekeeper.Api/Gatekeeper.Api.csproj index 4b85e6f..f4ea34d 100644 --- a/Gatekeeper/Gatekeeper.Api/Gatekeeper.Api.csproj +++ b/Gatekeeper/Gatekeeper.Api/Gatekeeper.Api.csproj @@ -14,14 +14,11 @@ - - - - - - - - + + + + + @@ -36,7 +33,7 @@ - - - - - + + + + + diff --git a/Scheduling/Scheduling.Api/Scheduling.Api.csproj b/Scheduling/Scheduling.Api/Scheduling.Api.csproj index a770e0f..cb91f5c 100644 --- a/Scheduling/Scheduling.Api/Scheduling.Api.csproj +++ b/Scheduling/Scheduling.Api/Scheduling.Api.csproj @@ -12,12 +12,12 @@ - - - - - - + + + + + + diff --git a/Scheduling/Scheduling.Sync/Scheduling.Sync.csproj b/Scheduling/Scheduling.Sync/Scheduling.Sync.csproj index 1967999..c208e7b 100644 --- a/Scheduling/Scheduling.Sync/Scheduling.Sync.csproj +++ b/Scheduling/Scheduling.Sync/Scheduling.Sync.csproj @@ -6,7 +6,7 @@ - - + + From 6040eef54ea5678eb1c3082f9d247435563cfb61 Mon Sep 17 00:00:00 2001 From: Christian Findlay <16697547+MelbourneDeveloper@users.noreply.github.com> Date: Tue, 7 Apr 2026 14:12:19 +1000 Subject: [PATCH 03/59] Point to nuget packages --- .claude/skills/ci-prep/SKILL.md | 33 +++---- .claude/skills/code-dedup/SKILL.md | 84 +++++++++++------- .config/dotnet-tools.json | 34 +++++++ .github/pull_request_template.md | 17 +--- .github/workflows/ci.yml | 35 +------- Clinical/Clinical.Api/Clinical.Api.csproj | 7 +- Clinical/Clinical.Api/DatabaseSetup.cs | 4 +- .../Generated/GetConditionsByPatient.g.cs | 2 +- .../Generated/GetEncountersByPatient.g.cs | 2 +- .../Generated/GetMedicationsByPatient.g.cs | 2 +- .../Generated/GetPatientById.g.cs | 2 +- .../Clinical.Api/Generated/GetPatients.g.cs | 2 +- .../Generated/SearchPatients.g.cs | 2 +- .../Generated/fhir_ConditionOperations.g.cs | 2 +- .../Generated/fhir_EncounterOperations.g.cs | 2 +- .../fhir_MedicationRequestOperations.g.cs | 2 +- .../Generated/fhir_PatientOperations.g.cs | 2 +- Clinical/Clinical.Api/GlobalUsings.cs | 75 ++++++++-------- Clinical/Clinical.Api/clinical.db | Bin 73728 -> 73728 bytes .../Dashboard.Integration.Tests/E2EFixture.cs | 21 ----- Directory.Build.props | 1 - .../Gatekeeper.Api.Tests/GlobalUsings.cs | 26 +++--- .../Gatekeeper.Api/Gatekeeper.Api.csproj | 5 +- .../Generated/CheckPermission.g.cs | 2 +- .../Generated/CheckResourceGrant.g.cs | 24 ++--- .../Generated/CountSystemRoles.g.cs | 2 +- .../Generated/GetActivePolicies.g.cs | 2 +- .../Generated/GetAllPermissions.g.cs | 2 +- .../Gatekeeper.Api/Generated/GetAllRoles.g.cs | 2 +- .../Gatekeeper.Api/Generated/GetAllUsers.g.cs | 2 +- .../Generated/GetChallengeById.g.cs | 2 +- .../Generated/GetCredentialById.g.cs | 2 +- .../Generated/GetCredentialsByUserId.g.cs | 2 +- .../Generated/GetPermissionByCode.g.cs | 2 +- .../Generated/GetRolePermissions.g.cs | 2 +- .../Generated/GetSessionById.g.cs | 2 +- .../Generated/GetSessionForRevoke.g.cs | 2 +- .../Generated/GetSessionRevoked.g.cs | 2 +- .../Generated/GetUserByEmail.g.cs | 2 +- .../Gatekeeper.Api/Generated/GetUserById.g.cs | 2 +- .../Generated/GetUserCredentials.g.cs | 2 +- .../Generated/GetUserPermissions.g.cs | 2 +- .../Generated/GetUserRoles.g.cs | 2 +- .../Generated/RevokeSession.g.cs | 2 +- .../Generated/gk_challengeOperations.g.cs | 2 +- .../Generated/gk_credentialOperations.g.cs | 2 +- .../Generated/gk_permissionOperations.g.cs | 2 +- .../gk_resource_grantOperations.g.cs | 2 +- .../Generated/gk_roleOperations.g.cs | 2 +- .../gk_role_permissionOperations.g.cs | 2 +- .../Generated/gk_sessionOperations.g.cs | 2 +- .../Generated/gk_userOperations.g.cs | 2 +- .../Generated/gk_user_roleOperations.g.cs | 2 +- Gatekeeper/Gatekeeper.Api/GlobalUsings.cs | 46 +++++----- ICD10/ICD10.Api.Tests/ICD10ApiFactory.cs | 4 +- ICD10/ICD10.Api/DatabaseSetup.cs | 4 +- ICD10/ICD10.Api/GlobalUsings.cs | 81 ++++++++--------- ICD10/ICD10.Api/ICD10.Api.csproj | 7 +- ICD10/ICD10.Api/Program.cs | 10 +-- Makefile | 2 +- NuGet.config | 7 ++ Scheduling/Scheduling.Api/DatabaseSetup.cs | 4 +- .../Generated/CheckSchedulingConflicts.g.cs | 2 +- .../Generated/GetAllPractitioners.g.cs | 2 +- .../Generated/GetAppointmentById.g.cs | 2 +- .../Generated/GetAppointmentsByPatient.g.cs | 2 +- .../GetAppointmentsByPractitioner.g.cs | 2 +- .../Generated/GetAppointmentsByStatus.g.cs | 2 +- .../Generated/GetAvailableSlots.g.cs | 2 +- .../Generated/GetPractitionerById.g.cs | 2 +- .../Generated/GetProviderAvailability.g.cs | 2 +- .../Generated/GetProviderDailySchedule.g.cs | 2 +- .../Generated/GetUpcomingAppointments.g.cs | 2 +- .../SearchPractitionersBySpecialty.g.cs | 2 +- .../Generated/fhir_AppointmentOperations.g.cs | 2 +- .../fhir_PractitionerOperations.g.cs | 2 +- Scheduling/Scheduling.Api/GlobalUsings.cs | 84 +++++++++--------- .../Scheduling.Api/Scheduling.Api.csproj | 7 +- Scheduling/Scheduling.Api/scheduling.db | Bin 77824 -> 77824 bytes Shared/Authorization/AuthHelpers.cs | 2 +- 80 files changed, 361 insertions(+), 369 deletions(-) create mode 100644 .config/dotnet-tools.json create mode 100644 NuGet.config diff --git a/.claude/skills/ci-prep/SKILL.md b/.claude/skills/ci-prep/SKILL.md index 86cd81f..82c46a3 100644 --- a/.claude/skills/ci-prep/SKILL.md +++ b/.claude/skills/ci-prep/SKILL.md @@ -3,7 +3,7 @@ name: ci-prep description: Prepares the current branch for CI by running the exact same steps locally and fixing issues. If CI is already failing, fetches the GH Actions logs first to diagnose. Use before pushing, when CI is red, or when the user says "fix ci". argument-hint: "[--failing] [optional job name to focus on]" --- - + # CI Prep @@ -11,12 +11,12 @@ Prepare the current state for CI. If CI is already failing, fetch and analyze th ## Arguments -- `--failing` -- Indicates a GitHub Actions run is already failing. When present, you MUST execute **Step 1** before doing anything else. +- `--failing` — Indicates a GitHub Actions run is already failing. When present, you MUST execute **Step 1** before doing anything else. - Any other argument is treated as a job name to focus on (but all failures are still reported). If `--failing` is NOT passed, skip directly to **Step 2**. -## Step 1 -- Fetch failed CI logs (only when `--failing`) +## Step 1 — Fetch failed CI logs (only when `--failing`) You MUST do this before any other work. @@ -40,23 +40,23 @@ gh run view "$RUN_ID" --log-failed Read **every line** of `--log-failed` output. For each failure note the exact file, line, and error message. If a job name argument was provided, prioritize that job but still report all failures. -## Step 2 -- Analyze the CI workflow +## Step 2 — Analyze the CI workflow 1. Find the CI workflow file. Look in `.github/workflows/` for `ci.yml`, `build.yml`, `test.yml`, `checks.yml`, `main.yml`, `pull_request.yml`, or any workflow triggered on `pull_request` or `push`. 2. Read the workflow file completely. Parse every job and every step. -3. Extract the ordered list of commands the CI actually runs (e.g., `make lint`, `make fmt-check`, `make test`, `make coverage-check`, `make build`, or whatever the workflow specifies -- it may use `npm`, `cargo`, `dotnet`, raw shell commands, or anything else). +3. Extract the ordered list of commands the CI actually runs (e.g., `make lint`, `make fmt-check`, `make test`, `make coverage-check`, `make build`, or whatever the workflow specifies — it may use `npm`, `cargo`, `dotnet`, raw shell commands, or anything else). 4. Note any environment variables, matrix strategies, or conditional steps that affect execution. **Do NOT assume the steps are `make lint`, `make test`, `make coverage-check`, `make build`.** The actual CI may run different commands, in a different order, with different targets. Extract what the CI *actually does*. -## Step 3 -- Run each CI step locally, in order +## Step 3 — Run each CI step locally, in order Work through failures in this priority order: -1. **Formatting** -- run auto-formatters first to clear noise -2. **Compilation errors** -- must compile before lint/test -3. **Lint violations** -- fix the code pattern -4. **Runtime / test failures** -- fix source code to satisfy the test +1. **Formatting** — run auto-formatters first to clear noise +2. **Compilation errors** — must compile before lint/test +3. **Lint violations** — fix the code pattern +4. **Runtime / test failures** — fix source code to satisfy the test For each command extracted from the CI workflow: @@ -67,20 +67,21 @@ For each command extracted from the CI workflow: ### Hard constraints -- **NEVER modify test files** -- fix the source code, not the tests -- **NEVER add suppressions** (`#pragma warning disable`, `// eslint-disable`, `#[allow(...)]`) +- **NEVER modify test files** — fix the source code, not the tests +- **NEVER add suppressions** (`#[allow(...)]`, `// eslint-disable`, `#pragma warning disable`) +- **NEVER use `any` in TypeScript** to silence type errors - **NEVER delete or ignore failing tests** - **NEVER remove assertions** If stuck on the same failure after 5 attempts, ask the user for help. -## Step 4 -- Report +## Step 4 — Report - List every step that was run and its result (pass/fail/fixed). - If any step could not be fixed, report what failed and why. - Confirm whether the branch is ready to push. -## Step 5 -- Commit/Push (only when `--failing`) +## Step 5 — Commit/Push (only when `--failing`) Once all CI steps pass locally: @@ -96,10 +97,10 @@ Once all CI steps pass locally: - Fix issues found in each step before moving to the next - Never skip steps or suppress errors - If the CI workflow has multiple jobs, run all of them (respecting dependency order) -- Skip steps that are CI-infrastructure-only (checkout, setup-node/python/rust actions, cache steps, artifact uploads) -- focus on the actual build/test/lint commands +- Skip steps that are CI-infrastructure-only (checkout, setup-node/python/rust actions, cache steps, artifact uploads) — focus on the actual build/test/lint commands ## Success criteria - Every command that CI runs has been executed locally and passed - All fixes are applied to the working tree -- The CI passes successfully (if you are correcting an existing failure) +- The CI passes successfully (if you are correcting and existing failure) diff --git a/.claude/skills/code-dedup/SKILL.md b/.claude/skills/code-dedup/SKILL.md index 2c4450e..21f29ab 100644 --- a/.claude/skills/code-dedup/SKILL.md +++ b/.claude/skills/code-dedup/SKILL.md @@ -1,20 +1,23 @@ --- name: code-dedup -description: Searches for duplicate code, duplicate tests, and dead code, then safely merges or removes them. Use when the user says "deduplicate", "find duplicates", "remove dead code", "DRY up", or "code dedup". Requires test coverage -- refuses to touch untested code. +description: Searches for duplicate code, duplicate tests, and dead code, then safely merges or removes them. Use when the user says "deduplicate", "find duplicates", "remove dead code", "DRY up", or "code dedup". Requires test coverage — refuses to touch untested code. --- - + # Code Dedup -Carefully search for duplicate code, duplicate tests, and dead code across the repo. Merge duplicates and delete dead code -- but only when test coverage proves the change is safe. +Carefully search for duplicate code, duplicate tests, and dead code across the repo. Merge duplicates and delete dead code — but only when test coverage proves the change is safe. -## Prerequisites -- hard gate +## Prerequisites — hard gate Before touching ANY code, verify these conditions. If any fail, stop and report why. -1. Run `make test` -- all tests must pass. If tests fail, stop. Do not dedup a broken codebase. -2. Run `make coverage-check` -- coverage must meet the repo's threshold. If it doesn't, stop. -3. This is a C# repo with static typing -- proceed. +1. Run `make test` — all tests must pass. If tests fail, stop. Do not dedup a broken codebase. +2. Run `make coverage-check` — coverage must meet the repo's threshold. If it doesn't, stop. +3. Verify the project uses **static typing**. Check for: + - C#: typed by default — proceed + - Python: must have type annotations AND a type checker configured (pyright, mypy, or Basilisk in pyproject.toml / Makefile) — proceed + - **Untyped Python: STOP. Refuse to dedup.** Print: "This codebase has no static type checking. Deduplication without types is reckless — too high a risk of silent breakage. Add type checking first." ## Steps @@ -30,65 +33,80 @@ Dedup Progress: - [ ] Step 6: Verification passed (tests green, coverage stable) ``` -### Step 1 -- Inventory test coverage +### Step 1 — Inventory test coverage + +Before deciding what to touch, understand what is tested. 1. Run `make test` and `make coverage-check` to confirm green baseline -2. Note the current coverage percentage -- this is the floor. It must not drop. +2. Note the current coverage percentage — this is the floor. It must not drop. 3. Identify which files/modules have coverage and which do not. Only files WITH coverage are candidates for dedup. -### Step 2 -- Scan for dead code +### Step 2 — Scan for dead code + +Search for code that is never called, never imported, never referenced. 1. Look for unused exports, unused functions, unused classes, unused variables -2. C# analyzer warnings for unused members -- check `make lint` output -3. For each candidate: **grep the entire codebase** for references. Only mark as dead if truly zero references. +2. Use language-appropriate tools where available: + - C#: analyzer warnings for unused members + - Python: look for functions/classes with zero imports across the codebase +3. For each candidate: **grep the entire codebase** for references (including tests, scripts, configs). Only mark as dead if truly zero references. 4. List all dead code found with file paths and line numbers. Do NOT delete yet. -### Step 3 -- Scan for duplicate code +### Step 3 — Scan for duplicate code + +Search for code blocks that do the same thing in multiple places. 1. Look for functions/methods with identical or near-identical logic 2. Look for copy-pasted blocks (same structure, maybe different variable names) 3. Look for multiple implementations of the same algorithm or pattern -4. Check across module boundaries -- duplicates often hide in different projects -5. For each duplicate pair: note both locations, what they do, and how they differ +4. Check across module boundaries — duplicates often hide in different packages/projects +5. For each duplicate pair: note both locations, what they do, and how they differ (if at all) 6. List all duplicates found. Do NOT merge yet. -### Step 4 -- Scan for duplicate tests +### Step 4 — Scan for duplicate tests + +Search for tests that verify the same behavior. 1. Look for test functions with identical assertions against the same code paths 2. Look for test fixtures/helpers that are duplicated across test files -3. Look for integration tests that fully cover what a unit test also covers (keep the integration test) +3. Look for integration tests that fully cover what a unit test also covers (keep the integration test, mark the unit test as redundant per CLAUDE.md rules) 4. List all duplicate tests found. Do NOT delete yet. -### Step 5 -- Apply changes (one at a time) +### Step 5 — Apply changes (one at a time) -For each change: **change -> test -> verify coverage -> continue or revert**. +For each change, follow this cycle: **change → test → verify coverage → continue or revert**. #### 5a. Remove dead code +- Delete dead code identified in Step 2 - After each deletion: run `make test` and `make coverage-check` -- If tests fail or coverage drops: **revert immediately** +- If tests fail or coverage drops: **revert immediately** and investigate +- Dead code removal should never break tests or drop coverage #### 5b. Merge duplicate code -- Extract shared logic into a single function/module, update all call sites +- For each duplicate pair: extract the shared logic into a single function/module +- Update all call sites to use the shared version - After each merge: run `make test` and `make coverage-check` -- If tests fail: **revert immediately** +- If tests fail: **revert immediately**. The duplicates may have subtle differences you missed. +- If coverage drops: the shared code must have equivalent test coverage. Add tests if needed before proceeding. #### 5c. Remove duplicate tests - Delete the redundant test (keep the more thorough one) - After each deletion: run `make coverage-check` -- If coverage drops: **revert immediately** +- If coverage drops: **revert immediately**. The "duplicate" test was covering something the other wasn't. -### Step 6 -- Final verification +### Step 6 — Final verification -1. Run `make test` -- all tests must still pass -2. Run `make coverage-check` -- coverage must be >= the baseline from Step 1 -3. Run `make lint` and `make fmt-check` -- code must be clean +1. Run `make test` — all tests must still pass +2. Run `make coverage-check` — coverage must be >= the baseline from Step 1 +3. Run `make lint` and `make fmt-check` — code must be clean 4. Report: what was removed, what was merged, final coverage vs baseline ## Rules -- **No test coverage = do not touch.** If a file has no tests covering it, leave it alone entirely. -- **Coverage must not drop.** The coverage floor from Step 1 is sacred. -- **One change at a time.** Never batch multiple dedup changes before testing. -- **When in doubt, leave it.** -- **Preserve public API surface.** -- **Three similar lines is fine.** Only dedup when shared logic is substantial (>10 lines) or 3+ copies. +- **No test coverage = do not touch.** If a file has no tests covering it, leave it alone entirely. You cannot safely dedup what you cannot verify. +- **Coverage must not drop.** If removing or merging code causes coverage to decrease, revert and investigate. The coverage floor from Step 1 is sacred. +- **Untyped code = refuse to dedup.** Untyped Python is too dangerous. Types are the safety net that catches breakage at compile time. Without them, silent runtime errors are near-certain. +- **One change at a time.** Make one dedup change, run tests, verify coverage. Never batch multiple dedup changes before testing. +- **When in doubt, leave it.** If two code blocks look similar but you're not 100% sure they're functionally identical, leave both. False dedup is worse than duplication. +- **Preserve public API surface.** Do not change function signatures, class names, or module exports that external code depends on. Internal refactoring only. +- **Three similar lines is fine.** Do not create abstractions for trivial duplication. The cure must not be worse than the disease. Only dedup when the shared logic is substantial (>10 lines) or when there are 3+ copies. diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json new file mode 100644 index 0000000..d7021f4 --- /dev/null +++ b/.config/dotnet-tools.json @@ -0,0 +1,34 @@ +{ + "version": 1, + "isRoot": true, + "tools": { + "csharpier": { + "version": "1.2.6", + "commands": [ + "csharpier" + ], + "rollForward": false + }, + "nimblesite.dataprovider.migration.cli": { + "version": "0.2.0-beta", + "commands": [ + "migration-cli" + ], + "rollForward": false + }, + "nimblesite.lql.cli.sqlite": { + "version": "0.2.0-beta", + "commands": [ + "lqlcli-sqlite" + ], + "rollForward": false + }, + "nimblesite.dataprovider.sqlite.cli": { + "version": "0.2.0-beta", + "commands": [ + "dataprovider-sqlite" + ], + "rollForward": false + } + } +} \ No newline at end of file diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index cddd9c5..135e75c 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,22 +1,11 @@ - + ## TLDR -## What Was Added? - - -## What Was Changed or Deleted? - +## Details + ## How Do The Automated Tests Prove It Works? - -## Spec / Doc Changes - - - -## Breaking Changes -- [ ] None - diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 206624a..ca1a027 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,4 +1,4 @@ -# agent-pmo:d58c330 +# agent-pmo:29b9dcf name: CI on: @@ -12,8 +12,8 @@ concurrency: cancel-in-progress: true jobs: - lint: - name: Lint + ci: + name: CI runs-on: ubuntu-latest timeout-minutes: 10 steps: @@ -29,21 +29,6 @@ jobs: - name: Lint run: make lint - test: - name: Test - runs-on: ubuntu-latest - timeout-minutes: 10 - needs: lint - steps: - - uses: actions/checkout@v4 - - - uses: actions/setup-dotnet@v4 - with: - dotnet-version: '10.0.x' - - - run: dotnet restore - - run: dotnet tool restore - - name: Test run: make test @@ -61,19 +46,5 @@ jobs: TestResults/**/coverage.* retention-days: 7 - build: - name: Build - runs-on: ubuntu-latest - timeout-minutes: 10 - needs: test - steps: - - uses: actions/checkout@v4 - - - uses: actions/setup-dotnet@v4 - with: - dotnet-version: '10.0.x' - - - run: dotnet restore - - name: Build run: make build diff --git a/Clinical/Clinical.Api/Clinical.Api.csproj b/Clinical/Clinical.Api/Clinical.Api.csproj index 03fbf56..36a37cf 100644 --- a/Clinical/Clinical.Api/Clinical.Api.csproj +++ b/Clinical/Clinical.Api/Clinical.Api.csproj @@ -15,7 +15,6 @@ - @@ -37,7 +36,7 @@ .Error; using InitOk = Outcome.Result.Ok; using InitResult = Outcome.Result; diff --git a/Clinical/Clinical.Api/Generated/GetConditionsByPatient.g.cs b/Clinical/Clinical.Api/Generated/GetConditionsByPatient.g.cs index e23e6af..05418c7 100644 --- a/Clinical/Clinical.Api/Generated/GetConditionsByPatient.g.cs +++ b/Clinical/Clinical.Api/Generated/GetConditionsByPatient.g.cs @@ -4,7 +4,7 @@ using System.Threading.Tasks; using Npgsql; using Outcome; -using Selecta; +using Nimblesite.Sql.Model; namespace Generated; diff --git a/Clinical/Clinical.Api/Generated/GetEncountersByPatient.g.cs b/Clinical/Clinical.Api/Generated/GetEncountersByPatient.g.cs index 15b16da..56f76a9 100644 --- a/Clinical/Clinical.Api/Generated/GetEncountersByPatient.g.cs +++ b/Clinical/Clinical.Api/Generated/GetEncountersByPatient.g.cs @@ -4,7 +4,7 @@ using System.Threading.Tasks; using Npgsql; using Outcome; -using Selecta; +using Nimblesite.Sql.Model; namespace Generated; diff --git a/Clinical/Clinical.Api/Generated/GetMedicationsByPatient.g.cs b/Clinical/Clinical.Api/Generated/GetMedicationsByPatient.g.cs index 65fe481..70d5bee 100644 --- a/Clinical/Clinical.Api/Generated/GetMedicationsByPatient.g.cs +++ b/Clinical/Clinical.Api/Generated/GetMedicationsByPatient.g.cs @@ -4,7 +4,7 @@ using System.Threading.Tasks; using Npgsql; using Outcome; -using Selecta; +using Nimblesite.Sql.Model; namespace Generated; diff --git a/Clinical/Clinical.Api/Generated/GetPatientById.g.cs b/Clinical/Clinical.Api/Generated/GetPatientById.g.cs index 5b2ce69..9c7451d 100644 --- a/Clinical/Clinical.Api/Generated/GetPatientById.g.cs +++ b/Clinical/Clinical.Api/Generated/GetPatientById.g.cs @@ -4,7 +4,7 @@ using System.Threading.Tasks; using Npgsql; using Outcome; -using Selecta; +using Nimblesite.Sql.Model; namespace Generated; diff --git a/Clinical/Clinical.Api/Generated/GetPatients.g.cs b/Clinical/Clinical.Api/Generated/GetPatients.g.cs index 218223f..8a69fed 100644 --- a/Clinical/Clinical.Api/Generated/GetPatients.g.cs +++ b/Clinical/Clinical.Api/Generated/GetPatients.g.cs @@ -4,7 +4,7 @@ using System.Threading.Tasks; using Npgsql; using Outcome; -using Selecta; +using Nimblesite.Sql.Model; namespace Generated; diff --git a/Clinical/Clinical.Api/Generated/SearchPatients.g.cs b/Clinical/Clinical.Api/Generated/SearchPatients.g.cs index 017f3ed..d4f7209 100644 --- a/Clinical/Clinical.Api/Generated/SearchPatients.g.cs +++ b/Clinical/Clinical.Api/Generated/SearchPatients.g.cs @@ -4,7 +4,7 @@ using System.Threading.Tasks; using Npgsql; using Outcome; -using Selecta; +using Nimblesite.Sql.Model; namespace Generated; diff --git a/Clinical/Clinical.Api/Generated/fhir_ConditionOperations.g.cs b/Clinical/Clinical.Api/Generated/fhir_ConditionOperations.g.cs index 6ab81d6..857e6d0 100644 --- a/Clinical/Clinical.Api/Generated/fhir_ConditionOperations.g.cs +++ b/Clinical/Clinical.Api/Generated/fhir_ConditionOperations.g.cs @@ -7,7 +7,7 @@ using System.Threading.Tasks; using Npgsql; using Outcome; -using Selecta; +using Nimblesite.Sql.Model; namespace Generated { diff --git a/Clinical/Clinical.Api/Generated/fhir_EncounterOperations.g.cs b/Clinical/Clinical.Api/Generated/fhir_EncounterOperations.g.cs index b0bf4d7..37a8199 100644 --- a/Clinical/Clinical.Api/Generated/fhir_EncounterOperations.g.cs +++ b/Clinical/Clinical.Api/Generated/fhir_EncounterOperations.g.cs @@ -7,7 +7,7 @@ using System.Threading.Tasks; using Npgsql; using Outcome; -using Selecta; +using Nimblesite.Sql.Model; namespace Generated { diff --git a/Clinical/Clinical.Api/Generated/fhir_MedicationRequestOperations.g.cs b/Clinical/Clinical.Api/Generated/fhir_MedicationRequestOperations.g.cs index 9107a72..5f1621c 100644 --- a/Clinical/Clinical.Api/Generated/fhir_MedicationRequestOperations.g.cs +++ b/Clinical/Clinical.Api/Generated/fhir_MedicationRequestOperations.g.cs @@ -7,7 +7,7 @@ using System.Threading.Tasks; using Npgsql; using Outcome; -using Selecta; +using Nimblesite.Sql.Model; namespace Generated { diff --git a/Clinical/Clinical.Api/Generated/fhir_PatientOperations.g.cs b/Clinical/Clinical.Api/Generated/fhir_PatientOperations.g.cs index 7bd62a9..4ada939 100644 --- a/Clinical/Clinical.Api/Generated/fhir_PatientOperations.g.cs +++ b/Clinical/Clinical.Api/Generated/fhir_PatientOperations.g.cs @@ -7,7 +7,7 @@ using System.Threading.Tasks; using Npgsql; using Outcome; -using Selecta; +using Nimblesite.Sql.Model; namespace Generated { diff --git a/Clinical/Clinical.Api/GlobalUsings.cs b/Clinical/Clinical.Api/GlobalUsings.cs index 3f63934..dbeddb9 100644 --- a/Clinical/Clinical.Api/GlobalUsings.cs +++ b/Clinical/Clinical.Api/GlobalUsings.cs @@ -3,93 +3,94 @@ global using Microsoft.Extensions.Logging; global using Npgsql; global using Outcome; -global using Sync; -global using Sync.Postgres; +global using Nimblesite.Sql.Model; +global using Nimblesite.Sync.Core; +global using Nimblesite.Sync.Postgres; global using GetConditionsError = Outcome.Result< System.Collections.Immutable.ImmutableList, - Selecta.SqlError + Nimblesite.Sql.Model.SqlError >.Error< System.Collections.Immutable.ImmutableList, - Selecta.SqlError + Nimblesite.Sql.Model.SqlError >; // GetConditionsByPatient query result type aliases global using GetConditionsOk = Outcome.Result< System.Collections.Immutable.ImmutableList, - Selecta.SqlError + Nimblesite.Sql.Model.SqlError >.Ok< System.Collections.Immutable.ImmutableList, - Selecta.SqlError + Nimblesite.Sql.Model.SqlError >; global using GetEncountersError = Outcome.Result< System.Collections.Immutable.ImmutableList, - Selecta.SqlError + Nimblesite.Sql.Model.SqlError >.Error< System.Collections.Immutable.ImmutableList, - Selecta.SqlError + Nimblesite.Sql.Model.SqlError >; // GetEncountersByPatient query result type aliases global using GetEncountersOk = Outcome.Result< System.Collections.Immutable.ImmutableList, - Selecta.SqlError + Nimblesite.Sql.Model.SqlError >.Ok< System.Collections.Immutable.ImmutableList, - Selecta.SqlError + Nimblesite.Sql.Model.SqlError >; global using GetMedicationsError = Outcome.Result< System.Collections.Immutable.ImmutableList, - Selecta.SqlError + Nimblesite.Sql.Model.SqlError >.Error< System.Collections.Immutable.ImmutableList, - Selecta.SqlError + Nimblesite.Sql.Model.SqlError >; // GetMedicationsByPatient query result type aliases global using GetMedicationsOk = Outcome.Result< System.Collections.Immutable.ImmutableList, - Selecta.SqlError + Nimblesite.Sql.Model.SqlError >.Ok< System.Collections.Immutable.ImmutableList, - Selecta.SqlError + Nimblesite.Sql.Model.SqlError >; global using GetPatientByIdError = Outcome.Result< System.Collections.Immutable.ImmutableList, - Selecta.SqlError ->.Error, Selecta.SqlError>; + Nimblesite.Sql.Model.SqlError +>.Error, Nimblesite.Sql.Model.SqlError>; // GetPatientById query result type aliases global using GetPatientByIdOk = Outcome.Result< System.Collections.Immutable.ImmutableList, - Selecta.SqlError ->.Ok, Selecta.SqlError>; + Nimblesite.Sql.Model.SqlError +>.Ok, Nimblesite.Sql.Model.SqlError>; global using GetPatientsError = Outcome.Result< System.Collections.Immutable.ImmutableList, - Selecta.SqlError ->.Error, Selecta.SqlError>; + Nimblesite.Sql.Model.SqlError +>.Error, Nimblesite.Sql.Model.SqlError>; // GetPatients query result type aliases global using GetPatientsOk = Outcome.Result< System.Collections.Immutable.ImmutableList, - Selecta.SqlError ->.Ok, Selecta.SqlError>; -global using InsertError = Outcome.Result.Error; + Nimblesite.Sql.Model.SqlError +>.Ok, Nimblesite.Sql.Model.SqlError>; +global using InsertError = Outcome.Result.Error; // Insert result type aliases -global using InsertOk = Outcome.Result.Ok; +global using InsertOk = Outcome.Result.Ok; global using SearchPatientsError = Outcome.Result< System.Collections.Immutable.ImmutableList, - Selecta.SqlError ->.Error, Selecta.SqlError>; + Nimblesite.Sql.Model.SqlError +>.Error, Nimblesite.Sql.Model.SqlError>; // SearchPatients query result type aliases global using SearchPatientsOk = Outcome.Result< System.Collections.Immutable.ImmutableList, - Selecta.SqlError ->.Ok, Selecta.SqlError>; + Nimblesite.Sql.Model.SqlError +>.Ok, Nimblesite.Sql.Model.SqlError>; // Sync result type aliases -global using StringSyncError = Outcome.Result.Error; -global using StringSyncOk = Outcome.Result.Ok; +global using StringSyncError = Outcome.Result.Error; +global using StringSyncOk = Outcome.Result.Ok; global using SyncLogListError = Outcome.Result< - System.Collections.Generic.IReadOnlyList, - Sync.SyncError ->.Error, Sync.SyncError>; + System.Collections.Generic.IReadOnlyList, + Nimblesite.Sync.Core.SyncError +>.Error, Nimblesite.Sync.Core.SyncError>; global using SyncLogListOk = Outcome.Result< - System.Collections.Generic.IReadOnlyList, - Sync.SyncError ->.Ok, Sync.SyncError>; + System.Collections.Generic.IReadOnlyList, + Nimblesite.Sync.Core.SyncError +>.Ok, Nimblesite.Sync.Core.SyncError>; // Update result type aliases -global using UpdateOk = Outcome.Result.Ok; +global using UpdateOk = Outcome.Result.Ok; diff --git a/Clinical/Clinical.Api/clinical.db b/Clinical/Clinical.Api/clinical.db index 1f874dd895e01a45c6d51dd017ab3d3d49295f62..831892ae93f41253209565e8c7774730d2014276 100644 GIT binary patch delta 18 ZcmZoTz|wGlWkM2DRbgYw))dA$@&HG42O - /// Waits for a service to be reachable (any HTTP response). - /// Used in local mode where services may be running but have DB issues. - /// - private static async Task WaitForServiceReachableAsync(string baseUrl, string endpoint) - { - using var client = new HttpClient { Timeout = TimeSpan.FromSeconds(2) }; - for (var i = 0; i < 60; i++) - { - try - { - _ = await client.GetAsync($"{baseUrl}{endpoint}"); - Console.WriteLine($"[E2E] Service reachable: {baseUrl}"); - return; - } - catch { } - await Task.Delay(500); - } - throw new TimeoutException($"Service at {baseUrl} is not reachable"); - } - /// /// Creates an authenticated HTTP client with test JWT token. /// diff --git a/Directory.Build.props b/Directory.Build.props index d030a72..08cd421 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -21,7 +21,6 @@ CA1016;CA1303;EPS06;IDE0290;CA1062;CA1002;IDE0090;CA1017;CS8509;IDE0037;NU1900;NU1901;NU1902;NU1903;NU1904 $(WarningsNotAsErrors);CA1303;EPS06;CA1016;IDE0290;CA1062;CA1002;CA1017;CS8509;IDE0037 9999 - true true All true diff --git a/Gatekeeper/Gatekeeper.Api.Tests/GlobalUsings.cs b/Gatekeeper/Gatekeeper.Api.Tests/GlobalUsings.cs index 90439cd..c488f59 100644 --- a/Gatekeeper/Gatekeeper.Api.Tests/GlobalUsings.cs +++ b/Gatekeeper/Gatekeeper.Api.Tests/GlobalUsings.cs @@ -5,32 +5,32 @@ global using System.Text.Json; global using Generated; global using Microsoft.AspNetCore.Mvc.Testing; -global using Selecta; +global using Nimblesite.Sql.Model; global using Xunit; global using GetPermissionByCodeError = Outcome.Result< System.Collections.Immutable.ImmutableList, - Selecta.SqlError + Nimblesite.Sql.Model.SqlError >.Error< System.Collections.Immutable.ImmutableList, - Selecta.SqlError + Nimblesite.Sql.Model.SqlError >; global using GetPermissionByCodeOk = Outcome.Result< System.Collections.Immutable.ImmutableList, - Selecta.SqlError ->.Ok, Selecta.SqlError>; + Nimblesite.Sql.Model.SqlError +>.Ok, Nimblesite.Sql.Model.SqlError>; global using GetRolePermissionsError = Outcome.Result< System.Collections.Immutable.ImmutableList, - Selecta.SqlError ->.Error, Selecta.SqlError>; + Nimblesite.Sql.Model.SqlError +>.Error, Nimblesite.Sql.Model.SqlError>; global using GetRolePermissionsOk = Outcome.Result< System.Collections.Immutable.ImmutableList, - Selecta.SqlError ->.Ok, Selecta.SqlError>; + Nimblesite.Sql.Model.SqlError +>.Ok, Nimblesite.Sql.Model.SqlError>; global using GetSessionRevokedError = Outcome.Result< System.Collections.Immutable.ImmutableList, - Selecta.SqlError ->.Error, Selecta.SqlError>; + Nimblesite.Sql.Model.SqlError +>.Error, Nimblesite.Sql.Model.SqlError>; global using GetSessionRevokedOk = Outcome.Result< System.Collections.Immutable.ImmutableList, - Selecta.SqlError ->.Ok, Selecta.SqlError>; + Nimblesite.Sql.Model.SqlError +>.Ok, Nimblesite.Sql.Model.SqlError>; diff --git a/Gatekeeper/Gatekeeper.Api/Gatekeeper.Api.csproj b/Gatekeeper/Gatekeeper.Api/Gatekeeper.Api.csproj index f4ea34d..2b4494a 100644 --- a/Gatekeeper/Gatekeeper.Api/Gatekeeper.Api.csproj +++ b/Gatekeeper/Gatekeeper.Api/Gatekeeper.Api.csproj @@ -18,7 +18,6 @@ - @@ -33,7 +32,7 @@ /// Open NpgsqlConnection connection. + /// Query parameter. /// Query parameter. + /// Query parameter. /// Query parameter. /// Query parameter. - /// Query parameter. - /// Query parameter. /// Result of records or SQL error. - public static async Task, SqlError>> CheckResourceGrantAsync(this NpgsqlConnection connection, object resource_type, object now, object resource_id, object user_id, object permission_code) + public static async Task, SqlError>> CheckResourceGrantAsync(this NpgsqlConnection connection, object user_id, object resource_type, object permission_code, object now, object resource_id) { const string sql = @"-- name: CheckResourceGrant SELECT rg.id, rg.user_id, rg.resource_type, rg.resource_id, rg.permission_id, @@ -43,10 +43,18 @@ FROM gk_resource_grant rg using (var command = new NpgsqlCommand(sql, connection)) { + if (user_id is not null and not DBNull) + command.Parameters.AddWithValue("@user_id", user_id); + else + command.Parameters.Add(new NpgsqlParameter("@user_id", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); if (resource_type is not null and not DBNull) command.Parameters.AddWithValue("@resource_type", resource_type); else command.Parameters.Add(new NpgsqlParameter("@resource_type", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); + if (permission_code is not null and not DBNull) + command.Parameters.AddWithValue("@permission_code", permission_code); + else + command.Parameters.Add(new NpgsqlParameter("@permission_code", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); if (now is not null and not DBNull) command.Parameters.AddWithValue("@now", now); else @@ -55,14 +63,6 @@ FROM gk_resource_grant rg command.Parameters.AddWithValue("@resource_id", resource_id); else command.Parameters.Add(new NpgsqlParameter("@resource_id", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); - if (user_id is not null and not DBNull) - command.Parameters.AddWithValue("@user_id", user_id); - else - command.Parameters.Add(new NpgsqlParameter("@user_id", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); - if (permission_code is not null and not DBNull) - command.Parameters.AddWithValue("@permission_code", permission_code); - else - command.Parameters.Add(new NpgsqlParameter("@permission_code", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false)) { diff --git a/Gatekeeper/Gatekeeper.Api/Generated/CountSystemRoles.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/CountSystemRoles.g.cs index 95e0a54..d708ec5 100644 --- a/Gatekeeper/Gatekeeper.Api/Generated/CountSystemRoles.g.cs +++ b/Gatekeeper/Gatekeeper.Api/Generated/CountSystemRoles.g.cs @@ -4,7 +4,7 @@ using System.Threading.Tasks; using Npgsql; using Outcome; -using Selecta; +using Nimblesite.Sql.Model; namespace Generated; diff --git a/Gatekeeper/Gatekeeper.Api/Generated/GetActivePolicies.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/GetActivePolicies.g.cs index 70c34e1..a2e3c29 100644 --- a/Gatekeeper/Gatekeeper.Api/Generated/GetActivePolicies.g.cs +++ b/Gatekeeper/Gatekeeper.Api/Generated/GetActivePolicies.g.cs @@ -4,7 +4,7 @@ using System.Threading.Tasks; using Npgsql; using Outcome; -using Selecta; +using Nimblesite.Sql.Model; namespace Generated; diff --git a/Gatekeeper/Gatekeeper.Api/Generated/GetAllPermissions.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/GetAllPermissions.g.cs index 13611cf..9feeca8 100644 --- a/Gatekeeper/Gatekeeper.Api/Generated/GetAllPermissions.g.cs +++ b/Gatekeeper/Gatekeeper.Api/Generated/GetAllPermissions.g.cs @@ -4,7 +4,7 @@ using System.Threading.Tasks; using Npgsql; using Outcome; -using Selecta; +using Nimblesite.Sql.Model; namespace Generated; diff --git a/Gatekeeper/Gatekeeper.Api/Generated/GetAllRoles.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/GetAllRoles.g.cs index 1298969..e2c11fc 100644 --- a/Gatekeeper/Gatekeeper.Api/Generated/GetAllRoles.g.cs +++ b/Gatekeeper/Gatekeeper.Api/Generated/GetAllRoles.g.cs @@ -4,7 +4,7 @@ using System.Threading.Tasks; using Npgsql; using Outcome; -using Selecta; +using Nimblesite.Sql.Model; namespace Generated; diff --git a/Gatekeeper/Gatekeeper.Api/Generated/GetAllUsers.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/GetAllUsers.g.cs index 6ed530d..7c80d5e 100644 --- a/Gatekeeper/Gatekeeper.Api/Generated/GetAllUsers.g.cs +++ b/Gatekeeper/Gatekeeper.Api/Generated/GetAllUsers.g.cs @@ -4,7 +4,7 @@ using System.Threading.Tasks; using Npgsql; using Outcome; -using Selecta; +using Nimblesite.Sql.Model; namespace Generated; diff --git a/Gatekeeper/Gatekeeper.Api/Generated/GetChallengeById.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/GetChallengeById.g.cs index 6884d4a..2bb9f81 100644 --- a/Gatekeeper/Gatekeeper.Api/Generated/GetChallengeById.g.cs +++ b/Gatekeeper/Gatekeeper.Api/Generated/GetChallengeById.g.cs @@ -4,7 +4,7 @@ using System.Threading.Tasks; using Npgsql; using Outcome; -using Selecta; +using Nimblesite.Sql.Model; namespace Generated; diff --git a/Gatekeeper/Gatekeeper.Api/Generated/GetCredentialById.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/GetCredentialById.g.cs index 8e034b6..a06805a 100644 --- a/Gatekeeper/Gatekeeper.Api/Generated/GetCredentialById.g.cs +++ b/Gatekeeper/Gatekeeper.Api/Generated/GetCredentialById.g.cs @@ -4,7 +4,7 @@ using System.Threading.Tasks; using Npgsql; using Outcome; -using Selecta; +using Nimblesite.Sql.Model; namespace Generated; diff --git a/Gatekeeper/Gatekeeper.Api/Generated/GetCredentialsByUserId.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/GetCredentialsByUserId.g.cs index 67d6c98..84d5574 100644 --- a/Gatekeeper/Gatekeeper.Api/Generated/GetCredentialsByUserId.g.cs +++ b/Gatekeeper/Gatekeeper.Api/Generated/GetCredentialsByUserId.g.cs @@ -4,7 +4,7 @@ using System.Threading.Tasks; using Npgsql; using Outcome; -using Selecta; +using Nimblesite.Sql.Model; namespace Generated; diff --git a/Gatekeeper/Gatekeeper.Api/Generated/GetPermissionByCode.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/GetPermissionByCode.g.cs index 07f17f7..0d82639 100644 --- a/Gatekeeper/Gatekeeper.Api/Generated/GetPermissionByCode.g.cs +++ b/Gatekeeper/Gatekeeper.Api/Generated/GetPermissionByCode.g.cs @@ -4,7 +4,7 @@ using System.Threading.Tasks; using Npgsql; using Outcome; -using Selecta; +using Nimblesite.Sql.Model; namespace Generated; diff --git a/Gatekeeper/Gatekeeper.Api/Generated/GetRolePermissions.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/GetRolePermissions.g.cs index 284dbae..b61ca70 100644 --- a/Gatekeeper/Gatekeeper.Api/Generated/GetRolePermissions.g.cs +++ b/Gatekeeper/Gatekeeper.Api/Generated/GetRolePermissions.g.cs @@ -4,7 +4,7 @@ using System.Threading.Tasks; using Npgsql; using Outcome; -using Selecta; +using Nimblesite.Sql.Model; namespace Generated; diff --git a/Gatekeeper/Gatekeeper.Api/Generated/GetSessionById.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/GetSessionById.g.cs index 15e6c14..2327941 100644 --- a/Gatekeeper/Gatekeeper.Api/Generated/GetSessionById.g.cs +++ b/Gatekeeper/Gatekeeper.Api/Generated/GetSessionById.g.cs @@ -4,7 +4,7 @@ using System.Threading.Tasks; using Npgsql; using Outcome; -using Selecta; +using Nimblesite.Sql.Model; namespace Generated; diff --git a/Gatekeeper/Gatekeeper.Api/Generated/GetSessionForRevoke.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/GetSessionForRevoke.g.cs index 5840dfa..4613a72 100644 --- a/Gatekeeper/Gatekeeper.Api/Generated/GetSessionForRevoke.g.cs +++ b/Gatekeeper/Gatekeeper.Api/Generated/GetSessionForRevoke.g.cs @@ -4,7 +4,7 @@ using System.Threading.Tasks; using Npgsql; using Outcome; -using Selecta; +using Nimblesite.Sql.Model; namespace Generated; diff --git a/Gatekeeper/Gatekeeper.Api/Generated/GetSessionRevoked.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/GetSessionRevoked.g.cs index b57735c..8f83931 100644 --- a/Gatekeeper/Gatekeeper.Api/Generated/GetSessionRevoked.g.cs +++ b/Gatekeeper/Gatekeeper.Api/Generated/GetSessionRevoked.g.cs @@ -4,7 +4,7 @@ using System.Threading.Tasks; using Npgsql; using Outcome; -using Selecta; +using Nimblesite.Sql.Model; namespace Generated; diff --git a/Gatekeeper/Gatekeeper.Api/Generated/GetUserByEmail.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/GetUserByEmail.g.cs index 1b26a87..cef636c 100644 --- a/Gatekeeper/Gatekeeper.Api/Generated/GetUserByEmail.g.cs +++ b/Gatekeeper/Gatekeeper.Api/Generated/GetUserByEmail.g.cs @@ -4,7 +4,7 @@ using System.Threading.Tasks; using Npgsql; using Outcome; -using Selecta; +using Nimblesite.Sql.Model; namespace Generated; diff --git a/Gatekeeper/Gatekeeper.Api/Generated/GetUserById.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/GetUserById.g.cs index 872f743..94f0278 100644 --- a/Gatekeeper/Gatekeeper.Api/Generated/GetUserById.g.cs +++ b/Gatekeeper/Gatekeeper.Api/Generated/GetUserById.g.cs @@ -4,7 +4,7 @@ using System.Threading.Tasks; using Npgsql; using Outcome; -using Selecta; +using Nimblesite.Sql.Model; namespace Generated; diff --git a/Gatekeeper/Gatekeeper.Api/Generated/GetUserCredentials.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/GetUserCredentials.g.cs index 089d0d8..725a67c 100644 --- a/Gatekeeper/Gatekeeper.Api/Generated/GetUserCredentials.g.cs +++ b/Gatekeeper/Gatekeeper.Api/Generated/GetUserCredentials.g.cs @@ -4,7 +4,7 @@ using System.Threading.Tasks; using Npgsql; using Outcome; -using Selecta; +using Nimblesite.Sql.Model; namespace Generated; diff --git a/Gatekeeper/Gatekeeper.Api/Generated/GetUserPermissions.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/GetUserPermissions.g.cs index c695a43..2b881ab 100644 --- a/Gatekeeper/Gatekeeper.Api/Generated/GetUserPermissions.g.cs +++ b/Gatekeeper/Gatekeeper.Api/Generated/GetUserPermissions.g.cs @@ -4,7 +4,7 @@ using System.Threading.Tasks; using Npgsql; using Outcome; -using Selecta; +using Nimblesite.Sql.Model; namespace Generated; diff --git a/Gatekeeper/Gatekeeper.Api/Generated/GetUserRoles.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/GetUserRoles.g.cs index ed3f6ea..c024210 100644 --- a/Gatekeeper/Gatekeeper.Api/Generated/GetUserRoles.g.cs +++ b/Gatekeeper/Gatekeeper.Api/Generated/GetUserRoles.g.cs @@ -4,7 +4,7 @@ using System.Threading.Tasks; using Npgsql; using Outcome; -using Selecta; +using Nimblesite.Sql.Model; namespace Generated; diff --git a/Gatekeeper/Gatekeeper.Api/Generated/RevokeSession.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/RevokeSession.g.cs index 7bd6353..052b1cf 100644 --- a/Gatekeeper/Gatekeeper.Api/Generated/RevokeSession.g.cs +++ b/Gatekeeper/Gatekeeper.Api/Generated/RevokeSession.g.cs @@ -4,7 +4,7 @@ using System.Threading.Tasks; using Npgsql; using Outcome; -using Selecta; +using Nimblesite.Sql.Model; namespace Generated; diff --git a/Gatekeeper/Gatekeeper.Api/Generated/gk_challengeOperations.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/gk_challengeOperations.g.cs index 575f8f2..d846599 100644 --- a/Gatekeeper/Gatekeeper.Api/Generated/gk_challengeOperations.g.cs +++ b/Gatekeeper/Gatekeeper.Api/Generated/gk_challengeOperations.g.cs @@ -7,7 +7,7 @@ using System.Threading.Tasks; using Npgsql; using Outcome; -using Selecta; +using Nimblesite.Sql.Model; namespace Generated { diff --git a/Gatekeeper/Gatekeeper.Api/Generated/gk_credentialOperations.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/gk_credentialOperations.g.cs index 7fe648c..fb37582 100644 --- a/Gatekeeper/Gatekeeper.Api/Generated/gk_credentialOperations.g.cs +++ b/Gatekeeper/Gatekeeper.Api/Generated/gk_credentialOperations.g.cs @@ -7,7 +7,7 @@ using System.Threading.Tasks; using Npgsql; using Outcome; -using Selecta; +using Nimblesite.Sql.Model; namespace Generated { diff --git a/Gatekeeper/Gatekeeper.Api/Generated/gk_permissionOperations.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/gk_permissionOperations.g.cs index c635e21..5e21816 100644 --- a/Gatekeeper/Gatekeeper.Api/Generated/gk_permissionOperations.g.cs +++ b/Gatekeeper/Gatekeeper.Api/Generated/gk_permissionOperations.g.cs @@ -7,7 +7,7 @@ using System.Threading.Tasks; using Npgsql; using Outcome; -using Selecta; +using Nimblesite.Sql.Model; namespace Generated { diff --git a/Gatekeeper/Gatekeeper.Api/Generated/gk_resource_grantOperations.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/gk_resource_grantOperations.g.cs index 4b3aada..6d13572 100644 --- a/Gatekeeper/Gatekeeper.Api/Generated/gk_resource_grantOperations.g.cs +++ b/Gatekeeper/Gatekeeper.Api/Generated/gk_resource_grantOperations.g.cs @@ -7,7 +7,7 @@ using System.Threading.Tasks; using Npgsql; using Outcome; -using Selecta; +using Nimblesite.Sql.Model; namespace Generated { diff --git a/Gatekeeper/Gatekeeper.Api/Generated/gk_roleOperations.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/gk_roleOperations.g.cs index 8223b8a..cdd5d4d 100644 --- a/Gatekeeper/Gatekeeper.Api/Generated/gk_roleOperations.g.cs +++ b/Gatekeeper/Gatekeeper.Api/Generated/gk_roleOperations.g.cs @@ -7,7 +7,7 @@ using System.Threading.Tasks; using Npgsql; using Outcome; -using Selecta; +using Nimblesite.Sql.Model; namespace Generated { diff --git a/Gatekeeper/Gatekeeper.Api/Generated/gk_role_permissionOperations.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/gk_role_permissionOperations.g.cs index 7b7c600..32067ed 100644 --- a/Gatekeeper/Gatekeeper.Api/Generated/gk_role_permissionOperations.g.cs +++ b/Gatekeeper/Gatekeeper.Api/Generated/gk_role_permissionOperations.g.cs @@ -7,7 +7,7 @@ using System.Threading.Tasks; using Npgsql; using Outcome; -using Selecta; +using Nimblesite.Sql.Model; namespace Generated { diff --git a/Gatekeeper/Gatekeeper.Api/Generated/gk_sessionOperations.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/gk_sessionOperations.g.cs index 11ab2c7..035254c 100644 --- a/Gatekeeper/Gatekeeper.Api/Generated/gk_sessionOperations.g.cs +++ b/Gatekeeper/Gatekeeper.Api/Generated/gk_sessionOperations.g.cs @@ -7,7 +7,7 @@ using System.Threading.Tasks; using Npgsql; using Outcome; -using Selecta; +using Nimblesite.Sql.Model; namespace Generated { diff --git a/Gatekeeper/Gatekeeper.Api/Generated/gk_userOperations.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/gk_userOperations.g.cs index 31b93cb..e3980c4 100644 --- a/Gatekeeper/Gatekeeper.Api/Generated/gk_userOperations.g.cs +++ b/Gatekeeper/Gatekeeper.Api/Generated/gk_userOperations.g.cs @@ -7,7 +7,7 @@ using System.Threading.Tasks; using Npgsql; using Outcome; -using Selecta; +using Nimblesite.Sql.Model; namespace Generated { diff --git a/Gatekeeper/Gatekeeper.Api/Generated/gk_user_roleOperations.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/gk_user_roleOperations.g.cs index f283f89..044e4a4 100644 --- a/Gatekeeper/Gatekeeper.Api/Generated/gk_user_roleOperations.g.cs +++ b/Gatekeeper/Gatekeeper.Api/Generated/gk_user_roleOperations.g.cs @@ -7,7 +7,7 @@ using System.Threading.Tasks; using Npgsql; using Outcome; -using Selecta; +using Nimblesite.Sql.Model; namespace Generated { diff --git a/Gatekeeper/Gatekeeper.Api/GlobalUsings.cs b/Gatekeeper/Gatekeeper.Api/GlobalUsings.cs index 60d2c0d..597dc01 100644 --- a/Gatekeeper/Gatekeeper.Api/GlobalUsings.cs +++ b/Gatekeeper/Gatekeeper.Api/GlobalUsings.cs @@ -9,51 +9,51 @@ global using Microsoft.Extensions.Logging; global using Npgsql; global using Outcome; -global using Selecta; +global using Nimblesite.Sql.Model; global using CheckResourceGrantOk = Outcome.Result< System.Collections.Immutable.ImmutableList, - Selecta.SqlError ->.Ok, Selecta.SqlError>; + Nimblesite.Sql.Model.SqlError +>.Ok, Nimblesite.Sql.Model.SqlError>; // Insert result type alias global using GetChallengeByIdOk = Outcome.Result< System.Collections.Immutable.ImmutableList, - Selecta.SqlError ->.Ok, Selecta.SqlError>; + Nimblesite.Sql.Model.SqlError +>.Ok, Nimblesite.Sql.Model.SqlError>; // Additional query result type aliases global using GetCredentialByIdOk = Outcome.Result< System.Collections.Immutable.ImmutableList, - Selecta.SqlError ->.Ok, Selecta.SqlError>; + Nimblesite.Sql.Model.SqlError +>.Ok, Nimblesite.Sql.Model.SqlError>; global using GetSessionRevokedError = Outcome.Result< System.Collections.Immutable.ImmutableList, - Selecta.SqlError ->.Error, Selecta.SqlError>; + Nimblesite.Sql.Model.SqlError +>.Error, Nimblesite.Sql.Model.SqlError>; global using GetSessionRevokedOk = Outcome.Result< System.Collections.Immutable.ImmutableList, - Selecta.SqlError ->.Ok, Selecta.SqlError>; + Nimblesite.Sql.Model.SqlError +>.Ok, Nimblesite.Sql.Model.SqlError>; // Query result type aliases global using GetUserByEmailOk = Outcome.Result< System.Collections.Immutable.ImmutableList, - Selecta.SqlError ->.Ok, Selecta.SqlError>; + Nimblesite.Sql.Model.SqlError +>.Ok, Nimblesite.Sql.Model.SqlError>; global using GetUserByIdOk = Outcome.Result< System.Collections.Immutable.ImmutableList, - Selecta.SqlError ->.Ok, Selecta.SqlError>; + Nimblesite.Sql.Model.SqlError +>.Ok, Nimblesite.Sql.Model.SqlError>; global using GetUserCredentialsError = Outcome.Result< System.Collections.Immutable.ImmutableList, - Selecta.SqlError ->.Error, Selecta.SqlError>; + Nimblesite.Sql.Model.SqlError +>.Error, Nimblesite.Sql.Model.SqlError>; global using GetUserCredentialsOk = Outcome.Result< System.Collections.Immutable.ImmutableList, - Selecta.SqlError ->.Ok, Selecta.SqlError>; + Nimblesite.Sql.Model.SqlError +>.Ok, Nimblesite.Sql.Model.SqlError>; global using GetUserPermissionsOk = Outcome.Result< System.Collections.Immutable.ImmutableList, - Selecta.SqlError ->.Ok, Selecta.SqlError>; + Nimblesite.Sql.Model.SqlError +>.Ok, Nimblesite.Sql.Model.SqlError>; global using GetUserRolesOk = Outcome.Result< System.Collections.Immutable.ImmutableList, - Selecta.SqlError ->.Ok, Selecta.SqlError>; + Nimblesite.Sql.Model.SqlError +>.Ok, Nimblesite.Sql.Model.SqlError>; diff --git a/ICD10/ICD10.Api.Tests/ICD10ApiFactory.cs b/ICD10/ICD10.Api.Tests/ICD10ApiFactory.cs index 5dde012..39682f8 100644 --- a/ICD10/ICD10.Api.Tests/ICD10ApiFactory.cs +++ b/ICD10/ICD10.Api.Tests/ICD10ApiFactory.cs @@ -1,7 +1,7 @@ using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc.Testing; -using Migration; -using Migration.Postgres; +using Nimblesite.DataProvider.Migration.Core; +using Nimblesite.DataProvider.Migration.Postgres; using Npgsql; namespace ICD10.Api.Tests; diff --git a/ICD10/ICD10.Api/DatabaseSetup.cs b/ICD10/ICD10.Api/DatabaseSetup.cs index e9fc36a..739dd70 100644 --- a/ICD10/ICD10.Api/DatabaseSetup.cs +++ b/ICD10/ICD10.Api/DatabaseSetup.cs @@ -1,5 +1,5 @@ -using Migration; -using Migration.Postgres; +using Nimblesite.DataProvider.Migration.Core; +using Nimblesite.DataProvider.Migration.Postgres; using InitError = Outcome.Result.Error; using InitOk = Outcome.Result.Ok; using InitResult = Outcome.Result; diff --git a/ICD10/ICD10.Api/GlobalUsings.cs b/ICD10/ICD10.Api/GlobalUsings.cs index dce7ddf..e9da852 100644 --- a/ICD10/ICD10.Api/GlobalUsings.cs +++ b/ICD10/ICD10.Api/GlobalUsings.cs @@ -4,99 +4,100 @@ global using Microsoft.Extensions.Logging; global using Npgsql; global using Outcome; +global using Nimblesite.Sql.Model; global using GetAchiBlocksError = Outcome.Result< System.Collections.Immutable.ImmutableList, - Selecta.SqlError ->.Error, Selecta.SqlError>; + Nimblesite.Sql.Model.SqlError +>.Error, Nimblesite.Sql.Model.SqlError>; // GetAchiBlocks query result type aliases global using GetAchiBlocksOk = Outcome.Result< System.Collections.Immutable.ImmutableList, - Selecta.SqlError ->.Ok, Selecta.SqlError>; + Nimblesite.Sql.Model.SqlError +>.Ok, Nimblesite.Sql.Model.SqlError>; global using GetAchiCodeByCodeError = Outcome.Result< System.Collections.Immutable.ImmutableList, - Selecta.SqlError ->.Error, Selecta.SqlError>; + Nimblesite.Sql.Model.SqlError +>.Error, Nimblesite.Sql.Model.SqlError>; // GetAchiCodeByCode query result type aliases global using GetAchiCodeByCodeOk = Outcome.Result< System.Collections.Immutable.ImmutableList, - Selecta.SqlError ->.Ok, Selecta.SqlError>; + Nimblesite.Sql.Model.SqlError +>.Ok, Nimblesite.Sql.Model.SqlError>; global using GetAchiCodesByBlockError = Outcome.Result< System.Collections.Immutable.ImmutableList, - Selecta.SqlError + Nimblesite.Sql.Model.SqlError >.Error< System.Collections.Immutable.ImmutableList, - Selecta.SqlError + Nimblesite.Sql.Model.SqlError >; // GetAchiCodesByBlock query result type aliases global using GetAchiCodesByBlockOk = Outcome.Result< System.Collections.Immutable.ImmutableList, - Selecta.SqlError ->.Ok, Selecta.SqlError>; + Nimblesite.Sql.Model.SqlError +>.Ok, Nimblesite.Sql.Model.SqlError>; global using GetBlocksByChapterError = Outcome.Result< System.Collections.Immutable.ImmutableList, - Selecta.SqlError ->.Error, Selecta.SqlError>; + Nimblesite.Sql.Model.SqlError +>.Error, Nimblesite.Sql.Model.SqlError>; // GetBlocksByChapter query result type aliases global using GetBlocksByChapterOk = Outcome.Result< System.Collections.Immutable.ImmutableList, - Selecta.SqlError ->.Ok, Selecta.SqlError>; + Nimblesite.Sql.Model.SqlError +>.Ok, Nimblesite.Sql.Model.SqlError>; global using GetCategoriesByBlockError = Outcome.Result< System.Collections.Immutable.ImmutableList, - Selecta.SqlError + Nimblesite.Sql.Model.SqlError >.Error< System.Collections.Immutable.ImmutableList, - Selecta.SqlError + Nimblesite.Sql.Model.SqlError >; // GetCategoriesByBlock query result type aliases global using GetCategoriesByBlockOk = Outcome.Result< System.Collections.Immutable.ImmutableList, - Selecta.SqlError ->.Ok, Selecta.SqlError>; + Nimblesite.Sql.Model.SqlError +>.Ok, Nimblesite.Sql.Model.SqlError>; global using GetChaptersError = Outcome.Result< System.Collections.Immutable.ImmutableList, - Selecta.SqlError ->.Error, Selecta.SqlError>; + Nimblesite.Sql.Model.SqlError +>.Error, Nimblesite.Sql.Model.SqlError>; // GetChapters query result type aliases global using GetChaptersOk = Outcome.Result< System.Collections.Immutable.ImmutableList, - Selecta.SqlError ->.Ok, Selecta.SqlError>; + Nimblesite.Sql.Model.SqlError +>.Ok, Nimblesite.Sql.Model.SqlError>; global using GetCodeByCodeError = Outcome.Result< System.Collections.Immutable.ImmutableList, - Selecta.SqlError ->.Error, Selecta.SqlError>; + Nimblesite.Sql.Model.SqlError +>.Error, Nimblesite.Sql.Model.SqlError>; // GetCodeByCode query result type aliases global using GetCodeByCodeOk = Outcome.Result< System.Collections.Immutable.ImmutableList, - Selecta.SqlError ->.Ok, Selecta.SqlError>; + Nimblesite.Sql.Model.SqlError +>.Ok, Nimblesite.Sql.Model.SqlError>; global using GetCodesByCategoryError = Outcome.Result< System.Collections.Immutable.ImmutableList, - Selecta.SqlError ->.Error, Selecta.SqlError>; + Nimblesite.Sql.Model.SqlError +>.Error, Nimblesite.Sql.Model.SqlError>; // GetCodesByCategory query result type aliases global using GetCodesByCategoryOk = Outcome.Result< System.Collections.Immutable.ImmutableList, - Selecta.SqlError ->.Ok, Selecta.SqlError>; + Nimblesite.Sql.Model.SqlError +>.Ok, Nimblesite.Sql.Model.SqlError>; global using SearchAchiCodesError = Outcome.Result< System.Collections.Immutable.ImmutableList, - Selecta.SqlError ->.Error, Selecta.SqlError>; + Nimblesite.Sql.Model.SqlError +>.Error, Nimblesite.Sql.Model.SqlError>; // SearchAchiCodes query result type aliases global using SearchAchiCodesOk = Outcome.Result< System.Collections.Immutable.ImmutableList, - Selecta.SqlError ->.Ok, Selecta.SqlError>; + Nimblesite.Sql.Model.SqlError +>.Ok, Nimblesite.Sql.Model.SqlError>; global using SearchIcd10CodesError = Outcome.Result< System.Collections.Immutable.ImmutableList, - Selecta.SqlError ->.Error, Selecta.SqlError>; + Nimblesite.Sql.Model.SqlError +>.Error, Nimblesite.Sql.Model.SqlError>; // SearchIcd10Codes query result type aliases global using SearchIcd10CodesOk = Outcome.Result< System.Collections.Immutable.ImmutableList, - Selecta.SqlError ->.Ok, Selecta.SqlError>; + Nimblesite.Sql.Model.SqlError +>.Ok, Nimblesite.Sql.Model.SqlError>; diff --git a/ICD10/ICD10.Api/ICD10.Api.csproj b/ICD10/ICD10.Api/ICD10.Api.csproj index e964c2f..32e9694 100644 --- a/ICD10/ICD10.Api/ICD10.Api.csproj +++ b/ICD10/ICD10.Api/ICD10.Api.csproj @@ -14,7 +14,6 @@ - @@ -39,7 +38,7 @@ -/// Enriches a code record with derived hierarchy info when DB values are null. -/// Uses Icd10Chapters to derive chapter/category from code prefix. -/// +// Enriches a code record with derived hierarchy info when DB values are null. +// Uses Icd10Chapters to derive chapter/category from code prefix. static GetCodeByCode EnrichCodeWithDerivedHierarchy(GetCodeByCode code) { var (chapterNum, chapterTitle) = string.IsNullOrEmpty(code.ChapterNumber) @@ -548,9 +546,7 @@ static object ToFhirProcedure(GetAchiCodeByCode code) => Property = new[] { new { Code = "block", ValueString = code.BlockNumber } }, }; -/// -/// Enriches search result with derived hierarchy when DB values are null. -/// +// Enriches search result with derived hierarchy when DB values are null. static object EnrichSearchResult(SearchIcd10Codes code) { var codeValue = code.Code ?? ""; diff --git a/Makefile b/Makefile index b835eb8..3635883 100644 --- a/Makefile +++ b/Makefile @@ -100,8 +100,8 @@ coverage-check: ## setup: Post-create dev environment setup setup: @echo "==> Setting up development environment..." - dotnet restore dotnet tool restore + dotnet restore @echo "==> Setup complete. Run 'make ci' to validate." # ============================================================================= diff --git a/NuGet.config b/NuGet.config new file mode 100644 index 0000000..30bd234 --- /dev/null +++ b/NuGet.config @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Scheduling/Scheduling.Api/DatabaseSetup.cs b/Scheduling/Scheduling.Api/DatabaseSetup.cs index 3c02dd6..fccdae2 100644 --- a/Scheduling/Scheduling.Api/DatabaseSetup.cs +++ b/Scheduling/Scheduling.Api/DatabaseSetup.cs @@ -1,5 +1,5 @@ -using Migration; -using Migration.Postgres; +using Nimblesite.DataProvider.Migration.Core; +using Nimblesite.DataProvider.Migration.Postgres; using InitError = Outcome.Result.Error; using InitOk = Outcome.Result.Ok; using InitResult = Outcome.Result; diff --git a/Scheduling/Scheduling.Api/Generated/CheckSchedulingConflicts.g.cs b/Scheduling/Scheduling.Api/Generated/CheckSchedulingConflicts.g.cs index e62b956..94dcb2d 100644 --- a/Scheduling/Scheduling.Api/Generated/CheckSchedulingConflicts.g.cs +++ b/Scheduling/Scheduling.Api/Generated/CheckSchedulingConflicts.g.cs @@ -4,7 +4,7 @@ using System.Threading.Tasks; using Npgsql; using Outcome; -using Selecta; +using Nimblesite.Sql.Model; namespace Generated; diff --git a/Scheduling/Scheduling.Api/Generated/GetAllPractitioners.g.cs b/Scheduling/Scheduling.Api/Generated/GetAllPractitioners.g.cs index 32b2386..5b874f8 100644 --- a/Scheduling/Scheduling.Api/Generated/GetAllPractitioners.g.cs +++ b/Scheduling/Scheduling.Api/Generated/GetAllPractitioners.g.cs @@ -4,7 +4,7 @@ using System.Threading.Tasks; using Npgsql; using Outcome; -using Selecta; +using Nimblesite.Sql.Model; namespace Generated; diff --git a/Scheduling/Scheduling.Api/Generated/GetAppointmentById.g.cs b/Scheduling/Scheduling.Api/Generated/GetAppointmentById.g.cs index 3f5abfa..676c8be 100644 --- a/Scheduling/Scheduling.Api/Generated/GetAppointmentById.g.cs +++ b/Scheduling/Scheduling.Api/Generated/GetAppointmentById.g.cs @@ -4,7 +4,7 @@ using System.Threading.Tasks; using Npgsql; using Outcome; -using Selecta; +using Nimblesite.Sql.Model; namespace Generated; diff --git a/Scheduling/Scheduling.Api/Generated/GetAppointmentsByPatient.g.cs b/Scheduling/Scheduling.Api/Generated/GetAppointmentsByPatient.g.cs index f8b0a9c..ae25ca2 100644 --- a/Scheduling/Scheduling.Api/Generated/GetAppointmentsByPatient.g.cs +++ b/Scheduling/Scheduling.Api/Generated/GetAppointmentsByPatient.g.cs @@ -4,7 +4,7 @@ using System.Threading.Tasks; using Npgsql; using Outcome; -using Selecta; +using Nimblesite.Sql.Model; namespace Generated; diff --git a/Scheduling/Scheduling.Api/Generated/GetAppointmentsByPractitioner.g.cs b/Scheduling/Scheduling.Api/Generated/GetAppointmentsByPractitioner.g.cs index 3d705c7..e676140 100644 --- a/Scheduling/Scheduling.Api/Generated/GetAppointmentsByPractitioner.g.cs +++ b/Scheduling/Scheduling.Api/Generated/GetAppointmentsByPractitioner.g.cs @@ -4,7 +4,7 @@ using System.Threading.Tasks; using Npgsql; using Outcome; -using Selecta; +using Nimblesite.Sql.Model; namespace Generated; diff --git a/Scheduling/Scheduling.Api/Generated/GetAppointmentsByStatus.g.cs b/Scheduling/Scheduling.Api/Generated/GetAppointmentsByStatus.g.cs index da0f10e..a87c26c 100644 --- a/Scheduling/Scheduling.Api/Generated/GetAppointmentsByStatus.g.cs +++ b/Scheduling/Scheduling.Api/Generated/GetAppointmentsByStatus.g.cs @@ -4,7 +4,7 @@ using System.Threading.Tasks; using Npgsql; using Outcome; -using Selecta; +using Nimblesite.Sql.Model; namespace Generated; diff --git a/Scheduling/Scheduling.Api/Generated/GetAvailableSlots.g.cs b/Scheduling/Scheduling.Api/Generated/GetAvailableSlots.g.cs index 1fde898..0def083 100644 --- a/Scheduling/Scheduling.Api/Generated/GetAvailableSlots.g.cs +++ b/Scheduling/Scheduling.Api/Generated/GetAvailableSlots.g.cs @@ -4,7 +4,7 @@ using System.Threading.Tasks; using Npgsql; using Outcome; -using Selecta; +using Nimblesite.Sql.Model; namespace Generated; diff --git a/Scheduling/Scheduling.Api/Generated/GetPractitionerById.g.cs b/Scheduling/Scheduling.Api/Generated/GetPractitionerById.g.cs index 76bdf39..026be47 100644 --- a/Scheduling/Scheduling.Api/Generated/GetPractitionerById.g.cs +++ b/Scheduling/Scheduling.Api/Generated/GetPractitionerById.g.cs @@ -4,7 +4,7 @@ using System.Threading.Tasks; using Npgsql; using Outcome; -using Selecta; +using Nimblesite.Sql.Model; namespace Generated; diff --git a/Scheduling/Scheduling.Api/Generated/GetProviderAvailability.g.cs b/Scheduling/Scheduling.Api/Generated/GetProviderAvailability.g.cs index 20eb91d..e55ef4f 100644 --- a/Scheduling/Scheduling.Api/Generated/GetProviderAvailability.g.cs +++ b/Scheduling/Scheduling.Api/Generated/GetProviderAvailability.g.cs @@ -4,7 +4,7 @@ using System.Threading.Tasks; using Npgsql; using Outcome; -using Selecta; +using Nimblesite.Sql.Model; namespace Generated; diff --git a/Scheduling/Scheduling.Api/Generated/GetProviderDailySchedule.g.cs b/Scheduling/Scheduling.Api/Generated/GetProviderDailySchedule.g.cs index 437fc7f..6cf7bbe 100644 --- a/Scheduling/Scheduling.Api/Generated/GetProviderDailySchedule.g.cs +++ b/Scheduling/Scheduling.Api/Generated/GetProviderDailySchedule.g.cs @@ -4,7 +4,7 @@ using System.Threading.Tasks; using Npgsql; using Outcome; -using Selecta; +using Nimblesite.Sql.Model; namespace Generated; diff --git a/Scheduling/Scheduling.Api/Generated/GetUpcomingAppointments.g.cs b/Scheduling/Scheduling.Api/Generated/GetUpcomingAppointments.g.cs index 338564a..4a02c4a 100644 --- a/Scheduling/Scheduling.Api/Generated/GetUpcomingAppointments.g.cs +++ b/Scheduling/Scheduling.Api/Generated/GetUpcomingAppointments.g.cs @@ -4,7 +4,7 @@ using System.Threading.Tasks; using Npgsql; using Outcome; -using Selecta; +using Nimblesite.Sql.Model; namespace Generated; diff --git a/Scheduling/Scheduling.Api/Generated/SearchPractitionersBySpecialty.g.cs b/Scheduling/Scheduling.Api/Generated/SearchPractitionersBySpecialty.g.cs index c28dc12..56845d3 100644 --- a/Scheduling/Scheduling.Api/Generated/SearchPractitionersBySpecialty.g.cs +++ b/Scheduling/Scheduling.Api/Generated/SearchPractitionersBySpecialty.g.cs @@ -4,7 +4,7 @@ using System.Threading.Tasks; using Npgsql; using Outcome; -using Selecta; +using Nimblesite.Sql.Model; namespace Generated; diff --git a/Scheduling/Scheduling.Api/Generated/fhir_AppointmentOperations.g.cs b/Scheduling/Scheduling.Api/Generated/fhir_AppointmentOperations.g.cs index 5b36202..ca5f6f6 100644 --- a/Scheduling/Scheduling.Api/Generated/fhir_AppointmentOperations.g.cs +++ b/Scheduling/Scheduling.Api/Generated/fhir_AppointmentOperations.g.cs @@ -7,7 +7,7 @@ using System.Threading.Tasks; using Npgsql; using Outcome; -using Selecta; +using Nimblesite.Sql.Model; namespace Generated { diff --git a/Scheduling/Scheduling.Api/Generated/fhir_PractitionerOperations.g.cs b/Scheduling/Scheduling.Api/Generated/fhir_PractitionerOperations.g.cs index 29bd56d..1be97c1 100644 --- a/Scheduling/Scheduling.Api/Generated/fhir_PractitionerOperations.g.cs +++ b/Scheduling/Scheduling.Api/Generated/fhir_PractitionerOperations.g.cs @@ -7,7 +7,7 @@ using System.Threading.Tasks; using Npgsql; using Outcome; -using Selecta; +using Nimblesite.Sql.Model; namespace Generated { diff --git a/Scheduling/Scheduling.Api/GlobalUsings.cs b/Scheduling/Scheduling.Api/GlobalUsings.cs index 3a661bb..ab00815 100644 --- a/Scheduling/Scheduling.Api/GlobalUsings.cs +++ b/Scheduling/Scheduling.Api/GlobalUsings.cs @@ -3,114 +3,114 @@ global using Microsoft.Extensions.Logging; global using Npgsql; global using Outcome; -global using Selecta; -global using Sync; -global using Sync.Postgres; +global using Nimblesite.Sql.Model; +global using Nimblesite.Sync.Core; +global using Nimblesite.Sync.Postgres; // Sync result type aliases -global using BoolSyncError = Outcome.Result.Error; +global using BoolSyncError = Outcome.Result.Error; global using GetAllPractitionersError = Outcome.Result< System.Collections.Immutable.ImmutableList, - Selecta.SqlError + Nimblesite.Sql.Model.SqlError >.Error< System.Collections.Immutable.ImmutableList, - Selecta.SqlError + Nimblesite.Sql.Model.SqlError >; // GetAllPractitioners query result type aliases global using GetAllPractitionersOk = Outcome.Result< System.Collections.Immutable.ImmutableList, - Selecta.SqlError ->.Ok, Selecta.SqlError>; + Nimblesite.Sql.Model.SqlError +>.Ok, Nimblesite.Sql.Model.SqlError>; global using GetAppointmentByIdError = Outcome.Result< System.Collections.Immutable.ImmutableList, - Selecta.SqlError ->.Error, Selecta.SqlError>; + Nimblesite.Sql.Model.SqlError +>.Error, Nimblesite.Sql.Model.SqlError>; // GetAppointmentById query result type aliases global using GetAppointmentByIdOk = Outcome.Result< System.Collections.Immutable.ImmutableList, - Selecta.SqlError ->.Ok, Selecta.SqlError>; + Nimblesite.Sql.Model.SqlError +>.Ok, Nimblesite.Sql.Model.SqlError>; global using GetAppointmentsByPatientError = Outcome.Result< System.Collections.Immutable.ImmutableList, - Selecta.SqlError + Nimblesite.Sql.Model.SqlError >.Error< System.Collections.Immutable.ImmutableList, - Selecta.SqlError + Nimblesite.Sql.Model.SqlError >; // GetAppointmentsByPatient query result type aliases global using GetAppointmentsByPatientOk = Outcome.Result< System.Collections.Immutable.ImmutableList, - Selecta.SqlError + Nimblesite.Sql.Model.SqlError >.Ok< System.Collections.Immutable.ImmutableList, - Selecta.SqlError + Nimblesite.Sql.Model.SqlError >; global using GetAppointmentsByPractitionerError = Outcome.Result< System.Collections.Immutable.ImmutableList, - Selecta.SqlError + Nimblesite.Sql.Model.SqlError >.Error< System.Collections.Immutable.ImmutableList, - Selecta.SqlError + Nimblesite.Sql.Model.SqlError >; // GetAppointmentsByPractitioner query result type aliases global using GetAppointmentsByPractitionerOk = Outcome.Result< System.Collections.Immutable.ImmutableList, - Selecta.SqlError + Nimblesite.Sql.Model.SqlError >.Ok< System.Collections.Immutable.ImmutableList, - Selecta.SqlError + Nimblesite.Sql.Model.SqlError >; global using GetPractitionerByIdError = Outcome.Result< System.Collections.Immutable.ImmutableList, - Selecta.SqlError + Nimblesite.Sql.Model.SqlError >.Error< System.Collections.Immutable.ImmutableList, - Selecta.SqlError + Nimblesite.Sql.Model.SqlError >; // GetPractitionerById query result type aliases global using GetPractitionerByIdOk = Outcome.Result< System.Collections.Immutable.ImmutableList, - Selecta.SqlError ->.Ok, Selecta.SqlError>; + Nimblesite.Sql.Model.SqlError +>.Ok, Nimblesite.Sql.Model.SqlError>; global using GetUpcomingAppointmentsError = Outcome.Result< System.Collections.Immutable.ImmutableList, - Selecta.SqlError + Nimblesite.Sql.Model.SqlError >.Error< System.Collections.Immutable.ImmutableList, - Selecta.SqlError + Nimblesite.Sql.Model.SqlError >; // GetUpcomingAppointments query result type aliases global using GetUpcomingAppointmentsOk = Outcome.Result< System.Collections.Immutable.ImmutableList, - Selecta.SqlError + Nimblesite.Sql.Model.SqlError >.Ok< System.Collections.Immutable.ImmutableList, - Selecta.SqlError + Nimblesite.Sql.Model.SqlError >; -global using InsertError = Outcome.Result.Error; +global using InsertError = Outcome.Result.Error; // Insert result type aliases -global using InsertOk = Outcome.Result.Ok; +global using InsertOk = Outcome.Result.Ok; global using SearchPractitionersError = Outcome.Result< System.Collections.Immutable.ImmutableList, - Selecta.SqlError + Nimblesite.Sql.Model.SqlError >.Error< System.Collections.Immutable.ImmutableList, - Selecta.SqlError + Nimblesite.Sql.Model.SqlError >; // SearchPractitionersBySpecialty query result type aliases global using SearchPractitionersOk = Outcome.Result< System.Collections.Immutable.ImmutableList, - Selecta.SqlError + Nimblesite.Sql.Model.SqlError >.Ok< System.Collections.Immutable.ImmutableList, - Selecta.SqlError + Nimblesite.Sql.Model.SqlError >; -global using StringSyncError = Outcome.Result.Error; -global using StringSyncOk = Outcome.Result.Ok; +global using StringSyncError = Outcome.Result.Error; +global using StringSyncOk = Outcome.Result.Ok; global using SyncLogListError = Outcome.Result< - System.Collections.Generic.IReadOnlyList, - Sync.SyncError ->.Error, Sync.SyncError>; + System.Collections.Generic.IReadOnlyList, + Nimblesite.Sync.Core.SyncError +>.Error, Nimblesite.Sync.Core.SyncError>; global using SyncLogListOk = Outcome.Result< - System.Collections.Generic.IReadOnlyList, - Sync.SyncError ->.Ok, Sync.SyncError>; + System.Collections.Generic.IReadOnlyList, + Nimblesite.Sync.Core.SyncError +>.Ok, Nimblesite.Sync.Core.SyncError>; diff --git a/Scheduling/Scheduling.Api/Scheduling.Api.csproj b/Scheduling/Scheduling.Api/Scheduling.Api.csproj index cb91f5c..b5da2d4 100644 --- a/Scheduling/Scheduling.Api/Scheduling.Api.csproj +++ b/Scheduling/Scheduling.Api/Scheduling.Api.csproj @@ -15,7 +15,6 @@ - @@ -37,7 +36,7 @@ CheckPermissionAsync( } catch (Exception ex) { - return new PermissionResult(false, $"Permission check failed: {ex.Message}"); + return new PermissionResult(false, $"Permission check failed: {ex}"); } } From 99ca007a529a5160e26cfb050afd91989563d11f Mon Sep 17 00:00:00 2001 From: Christian Findlay <16697547+MelbourneDeveloper@users.noreply.github.com> Date: Tue, 7 Apr 2026 16:07:18 +1000 Subject: [PATCH 04/59] Fixes --- .claude/skills/spec-check/SKILL.md | 254 +++++++++++++++--- .claude/skills/submit-pr/SKILL.md | 8 +- .claude/skills/upgrade-packages/SKILL.md | 82 ++++-- .claude/skills/website-audit/SKILL.md | 60 +++-- .clinerules/00-read-instructions.md | 2 +- .github/copilot-instructions.md | 2 +- .gitignore | 2 +- AGENTS.md | 2 +- CLAUDE.md | 2 +- Clinical/Clinical.Api/GlobalUsings.cs | 69 +++-- Directory.Build.props | 1 - .../Gatekeeper.Api.Tests/GlobalUsings.cs | 25 +- Gatekeeper/Gatekeeper.Api/GlobalUsings.cs | 57 +++- ICD10/ICD10.Api/GlobalUsings.cs | 92 +++++-- Makefile | 6 +- Scheduling/Scheduling.Api/GlobalUsings.cs | 59 +++- coverlet.runsettings | 2 +- opencode.json | 2 +- 18 files changed, 566 insertions(+), 161 deletions(-) diff --git a/.claude/skills/spec-check/SKILL.md b/.claude/skills/spec-check/SKILL.md index d411db8..683cfb7 100644 --- a/.claude/skills/spec-check/SKILL.md +++ b/.claude/skills/spec-check/SKILL.md @@ -3,7 +3,7 @@ name: spec-check description: Audit spec/plan documents against the codebase. Ensures every spec section has implementing code, tests, and matching logic. Use when the user says "check specs", "spec audit", or "verify specs". argument-hint: "[optional spec ID or filename filter]" --- - + # spec-check @@ -13,7 +13,7 @@ Audit spec/plan documents against the codebase. Ensures every spec section has i ## Arguments -- `$ARGUMENTS` -- optional spec name or ID to check (e.g., `AUTH-TOKEN-VERIFY` or `repo-standards`). If empty, check ALL specs. Spec IDs are descriptive slugs, NEVER numbered (see Step 1). +- `$ARGUMENTS` — optional spec name or ID to check (e.g., `AUTH-TOKEN-VERIFY` or `repo-standards`). If empty, check ALL specs. Spec IDs are descriptive slugs, NEVER numbered (see Step 1). ## Instructions @@ -28,13 +28,22 @@ Before checking code/test references, verify that the specs themselves are well- 1. Find all spec documents (see locations in Step 2). 2. Extract every section ID using the regex `\[([A-Z][A-Z0-9]*(-[A-Z0-9]+)+)\]`. 3. **Flag invalid IDs:** - - Numbered IDs (`[SPEC-001]`, `[REQ-003]`, `[CI-004]`) -- must be renamed to descriptive hierarchical slugs. - - Single-word IDs (`[TIMEOUT]`) -- must have a group prefix. - - IDs with trailing numbers (`[FEAT-AUTH-01]`) -- the number is meaningless, remove it. + - Numbered IDs (`[SPEC-001]`, `[REQ-003]`, `[CI-004]`) — must be renamed to descriptive hierarchical slugs. + - Single-word IDs (`[TIMEOUT]`) — must have a group prefix. + - IDs with trailing numbers (`[FEAT-AUTH-01]`) — the number is meaningless, remove it. 4. **Check group clustering:** The first word of each ID is its group. All sections in the same group MUST appear together (adjacent) in the document. If they're scattered, flag it. 5. **Check for missing IDs:** Any heading that defines a requirement or behavior should have an ID. Flag headings in spec files that look like they define behavior but lack an ID. -If any ID violations are found, report them all and **STOP**. +If any ID violations are found, report them all and **STOP**: +``` +SPEC ID VIOLATIONS: + +- docs/specs/AUTH-SPEC.md line 12: [SPEC-001] → rename to descriptive ID (e.g., [AUTH-LOGIN]) +- docs/specs/AUTH-SPEC.md line 30: [AUTH-TOKEN-VERIFY] and [AUTH-LOGIN] are not adjacent (scattered group) +- docs/specs/CI-SPEC.md line 5: "## Coverage thresholds" has no spec ID + +Fix spec IDs first, then re-run spec-check. +``` If all IDs are valid, proceed to Step 2. @@ -52,23 +61,45 @@ Search for markdown files that contain spec sections with IDs. Look in these loc Use Glob to find candidate files, then use Grep to confirm they contain spec IDs. -**Spec ID patterns** -- IDs appear in square brackets, typically at the start of a heading or section line. Match this regex pattern: +**Spec ID patterns** — IDs appear in square brackets, typically at the start of a heading or section line. Match this regex pattern: ``` \[([A-Z][A-Z0-9]*(-[A-Z0-9]+)+)\] ``` -Spec IDs are **hierarchical descriptive slugs, NEVER numbered.** The format is `[GROUP-TOPIC]` or `[GROUP-TOPIC-DETAIL]`. +Spec IDs are **hierarchical descriptive slugs, NEVER numbered.** The format is `[GROUP-TOPIC]` or `[GROUP-TOPIC-DETAIL]`. The first word is the **group** — all sections sharing the same group MUST appear together in the spec's table of contents. IDs are uppercase, hyphen-separated, unique across the repo, and MUST NOT contain sequential numbers. + +The hierarchy depth varies by repo: two words for simple repos (`[AUTH-LOGIN]`), three for most (`[AUTH-TOKEN-VERIFY]`), four for complex domains (`[AUTH-OAUTH-REFRESH-FLOW]`). The hierarchy mirrors the spec document's heading structure. + +Examples of valid spec IDs (note how groups cluster): +- `[AUTH-LOGIN]`, `[AUTH-TOKEN-VERIFY]`, `[AUTH-TOKEN-REFRESH]` — all in the AUTH group +- `[CI-TIMEOUT]`, `[CI-LINT]`, `[CI-COVERAGE]` — all in the CI group +- `[LINT-ESLINT]`, `[LINT-RUFF]` — all in the LINT group +- `[FEAT-DARK-MODE]`, `[FEAT-SEARCH-FILTER]` — all in the FEAT group -For each file, extract every spec ID and its associated section title and full section content. +Examples of INVALID spec IDs: +- `[SPEC-001]` — numbered, meaningless +- `[FEAT-AUTH-01]` — trailing number +- `[REQ-003]` — sequential index, no group hierarchy +- `[CI-004]` — numbered, tells the reader nothing +- `[TIMEOUT]` — no group prefix, ungrouped + +For each file, extract every spec ID and its associated section title (the heading text after the ID) and the full section content (everything until the next heading of equal or higher level). --- ### Step 3: Filter specs -- If `$ARGUMENTS` is non-empty, filter the discovered specs. +- If `$ARGUMENTS` is non-empty, filter the discovered specs: + - If it matches a spec ID exactly (e.g., `AUTH-TOKEN-VERIFY`), check only that spec. + - If it matches a partial name (e.g., `repo-standards`), check all specs in files whose path contains that string. - If `$ARGUMENTS` is empty, process ALL discovered specs. +If filtering produces zero specs, report an error: +``` +ERROR: No specs found matching "$ARGUMENTS". Discovered spec files: [list them] +``` + --- ### Step 4: Check each spec section @@ -77,59 +108,222 @@ For EACH spec section that has an ID, perform checks A, B, and C below. **Stop o #### Check A: Code references the spec ID -Search the entire codebase for the spec ID string, **excluding** `docs/`, `node_modules/`, `.git/`, and `*.md` files. +Search the entire codebase for the spec ID string, **excluding** these directories: +- `docs/` +- `node_modules/` +- `.git/` +- `*.md` files (markdown is docs, not code) + +Use Grep with the literal spec ID (e.g., `[AUTH-TOKEN-VERIFY]`) to find references in code files. + +Code files should contain comments referencing the spec ID. The search must catch **all** comment styles across languages: -Any comment containing the exact spec ID string counts as a valid code reference. +**C-style `//` comments** (JavaScript, TypeScript, Rust, C#, F#, Java, Kotlin, Go, Swift, Dart): +- `// Implements [AUTH-TOKEN-VERIFY]` +- `// [AUTH-TOKEN-VERIFY]` +- `// Tests [AUTH-TOKEN-VERIFY]` (also counts as a code reference) +- `/// Implements [AUTH-TOKEN-VERIFY]` (doc comments) + +**Hash `#` comments** (Python, Ruby, Shell/Bash, YAML, TOML): +- `# Implements [AUTH-TOKEN-VERIFY]` +- `# [AUTH-TOKEN-VERIFY]` +- `# Tests [AUTH-TOKEN-VERIFY]` + +**HTML/XML comments** (HTML, CSS, SVG, XML, XAML, JSX templates): +- `` +- `` + +**ML-style comments** (F#, OCaml): +- `(* Implements [AUTH-TOKEN-VERIFY] *)` + +**Lua comments:** +- `-- Implements [AUTH-TOKEN-VERIFY]` + +**CSS comments:** +- `/* Implements [AUTH-TOKEN-VERIFY] */` + +**The key rule:** any comment in any language containing the exact spec ID string (e.g., `[AUTH-TOKEN-VERIFY]`) counts as a valid code reference. The Grep search uses the literal spec ID string, so it naturally matches all comment styles. Do NOT restrict the search to specific comment prefixes — just search for the spec ID string itself. **If NO code files reference the spec ID:** ``` -SPEC VIOLATION: [ID] "Section Title" has no implementing code. +SPEC VIOLATION: [AUTH-TOKEN-VERIFY] "Section Title" has no implementing code. -ACTION REQUIRED: Add a comment referencing [ID] in the file(s) that implement +Every spec section must have at least one code file that references it via a comment +containing the spec ID (e.g., `// Implements [AUTH-TOKEN-VERIFY]`). + +ACTION REQUIRED: Add a comment referencing [AUTH-TOKEN-VERIFY] in the file(s) that implement this spec section, then re-run spec-check. ``` -**STOP HERE.** +**STOP HERE. Do not continue to other checks.** #### Check B: Tests reference the spec ID -Search test files (`**/*.Tests/**`, `**/*Tests.*`, `**/*Test.*`) for the literal spec ID string. +Search test files for the spec ID. Test files are found in: +- `test/` +- `tests/` +- `**/*.test.*` +- `**/*.spec.*` +- `**/*_test.*` +- `**/test_*.*` +- `**/*Tests.*` +- `**/*Test.*` + +Use Grep to search these locations for the literal spec ID string. + +Tests should contain the spec ID in comments, test names, or annotations. The search must catch **all** test frameworks across languages: + +**JavaScript/TypeScript** (Jest, Mocha, Vitest, Playwright): +- `// Tests [AUTH-TOKEN-VERIFY]` +- `describe('[AUTH-TOKEN-VERIFY] Authentication flow', () => ...)` +- `test('[AUTH-TOKEN-VERIFY] should verify token', () => ...)` +- `it('[AUTH-TOKEN-VERIFY] verifies token', () => ...)` + +**Python** (pytest, unittest): +- `# Tests [AUTH-TOKEN-VERIFY]` +- `def test_auth_token_verify_flow():` +- `class TestAuthTokenVerify:` + +**Rust:** +- `// Tests [AUTH-TOKEN-VERIFY]` +- `#[test] // Tests [AUTH-TOKEN-VERIFY]` + +**C#** (xUnit, NUnit, MSTest): +- `// Tests [AUTH-TOKEN-VERIFY]` +- `[Fact] // Tests [AUTH-TOKEN-VERIFY]` +- `[Test] // Tests [AUTH-TOKEN-VERIFY]` +- `[TestMethod] // Tests [AUTH-TOKEN-VERIFY]` + +**F#** (xUnit, Expecto): +- `// Tests [AUTH-TOKEN-VERIFY]` +- `[] // Tests [AUTH-TOKEN-VERIFY]` +- `testCase "[AUTH-TOKEN-VERIFY] description" <| fun () ->` + +**Java/Kotlin** (JUnit, TestNG): +- `// Tests [AUTH-TOKEN-VERIFY]` +- `@Test // Tests [AUTH-TOKEN-VERIFY]` + +**Go:** +- `// Tests [AUTH-TOKEN-VERIFY]` +- `func TestAuthTokenVerify(t *testing.T) { // Tests [AUTH-TOKEN-VERIFY]` + +**Swift** (XCTest): +- `// Tests [AUTH-TOKEN-VERIFY]` +- `func testAuthTokenVerify() { // Tests [AUTH-TOKEN-VERIFY]` + +**Dart** (flutter_test): +- `// Tests [AUTH-TOKEN-VERIFY]` +- `test('[AUTH-TOKEN-VERIFY] description', () { ... });` + +**Ruby** (RSpec, Minitest): +- `# Tests [AUTH-TOKEN-VERIFY]` +- `describe '[AUTH-TOKEN-VERIFY] Authentication' do` +- `it '[AUTH-TOKEN-VERIFY] verifies token' do` + +**Shell** (bats, shunit2): +- `# Tests [AUTH-TOKEN-VERIFY]` +- `@test "[AUTH-TOKEN-VERIFY] description" {` + +**The key rule:** same as Check A — search for the literal spec ID string in test files. Any occurrence of the exact spec ID in a test file counts. Do NOT restrict to specific patterns — just search for the spec ID string itself. **If NO test files reference the spec ID:** ``` -SPEC VIOLATION: [ID] "Section Title" has no tests. +SPEC VIOLATION: [AUTH-TOKEN-VERIFY] "Section Title" has no tests. + +Every spec section must have corresponding tests that reference the spec ID. -ACTION REQUIRED: Add tests for [ID] with a comment or test name containing +ACTION REQUIRED: Add tests for [AUTH-TOKEN-VERIFY] with a comment or test name containing the spec ID, then re-run spec-check. ``` -**STOP HERE.** +**STOP HERE. Do not continue to other checks.** #### Check C: Code logic matches the spec -1. Read the spec section content carefully. -2. Read the implementing code. -3. Compare spec vs. code. Be SENSITIVE and PEDANTIC. Check for ordering violations, missing conditions, wrong logic, missing steps, wrong defaults. -4. If the code deviates from the spec, report a detailed error with quotes from both spec and code. +This is the most critical check. You must: + +1. **Read the spec section content carefully.** Understand exactly what behavior, logic, ordering, conditions, and constraints the spec describes. -**STOP HERE on any deviation.** +2. **Read the implementing code.** Use the references found in Check A to locate the implementing files. Read the relevant functions/sections. -5. If the code matches the spec, this check passes. Move to the next spec. +3. **Compare spec vs. code.** Be SENSITIVE and PEDANTIC. Check for: + - **Ordering violations** — If the spec says A happens before B, the code must do A before B. + - **Missing conditions** — If the spec says "only when X", the code must have that condition. + - **Extra behavior** — If the code does something the spec doesn't mention, flag it only if it contradicts the spec. + - **Wrong logic** — If the spec says "greater than" but code uses "greater than or equal", that's a violation. + - **Missing steps** — If the spec describes 5 steps but code only implements 3, that's a violation. + - **Wrong defaults** — If the spec says "default to X" but code defaults to Y, that's a violation. + +4. **If the code deviates from the spec**, report a detailed error: + +``` +SPEC VIOLATION: [AUTH-TOKEN-VERIFY] Code does not match spec. + +SPEC SAYS: +> "The authentication flow must verify the token expiry before checking permissions" +> (from docs/specs/AUTH-SPEC.md, line 42) + +CODE DOES: +> `if (hasPermission(user)) { verifyToken(token); }` (src/auth.ts:42) + +DEVIATION: The code checks permissions BEFORE verifying token expiry. +The spec explicitly requires token expiry verification FIRST. + +ACTION REQUIRED: Reorder the logic in src/auth.ts to verify token expiry +before checking permissions, as specified in [AUTH-TOKEN-VERIFY]. +``` + +**STOP HERE. Do not continue to other specs.** + +5. **If the code matches the spec**, this check passes. Move to the next spec. --- ### Step 5: Report results -On failure: output ONLY the first violation found. +#### On failure (any check fails): + +Output ONLY the first violation found. Use the exact error format shown above. Do not summarize other specs. Do not offer to fix the code. Just report the violation. + +End with: +``` +spec-check FAILED. Fix the violation above and re-run. +``` + +#### On success (all specs pass): + +Output a summary table: + +``` +spec-check PASSED. All specs verified. + +| Spec ID | Title | Code References | Test References | Logic Match | +|----------------|--------------------------|-----------------|-----------------|-------------| +| [AUTH-TOKEN-VERIFY] | Authentication flow | src/auth.ts | tests/auth.test.ts | PASS | +| [RATE-LIMIT-CONFIG] | Rate limiting | src/rate.ts | tests/rate.test.ts | PASS | +| ... | ... | ... | ... | ... | + +Checked N spec sections across M files. All have implementing code, tests, and matching logic. +``` + +--- + +## Search strategy summary -On success: output a summary table of all specs checked. +1. **Validate spec IDs:** Check all IDs are hierarchical, descriptive, grouped, and non-numbered +2. **Find spec files:** Glob for `docs/**/*.md`, `SPEC.md`, `PLAN.md`, `specs/**/*.md` +3. **Extract spec IDs:** Grep for `\[[A-Z][A-Z0-9]*(-[A-Z0-9]+)+\]` in those files +4. **Find code refs:** Grep for the literal spec ID in all files, excluding `docs/`, `node_modules/`, `.git/`, `*.md` +5. **Find test refs:** Grep for the literal spec ID in test directories and test file patterns +6. **Read and compare:** Read the spec section content and the implementing code, compare logic ## Key principles - **Fail fast.** Stop on the first violation. One fix at a time. -- **Be pedantic.** If the spec says it, the code must do it. -- **Quote everything.** Always quote the spec text and the code in error messages. +- **Be pedantic.** If the spec says it, the code must do it. No "close enough". +- **Quote everything.** Always quote the spec text and the code in error messages so the developer sees exactly what's wrong. - **Be actionable.** Every error must tell the developer what file to change and what to do. -- **No numbered IDs.** Spec IDs are hierarchical descriptive slugs, NEVER sequential numbers. +- **Exclude docs from code search.** Markdown files are documentation, not implementation. Only search actual code files for spec references. +- **No numbered IDs.** Spec IDs are hierarchical descriptive slugs (`[AUTH-TOKEN-VERIFY]`), NEVER sequential numbers (`[SPEC-001]`). The first word is the group — sections sharing a group must be adjacent in the TOC. If you encounter numbered or ungrouped IDs, flag them as a violation. diff --git a/.claude/skills/submit-pr/SKILL.md b/.claude/skills/submit-pr/SKILL.md index 33dd896..72526cc 100644 --- a/.claude/skills/submit-pr/SKILL.md +++ b/.claude/skills/submit-pr/SKILL.md @@ -3,7 +3,7 @@ name: submit-pr description: Creates a pull request with a well-structured description after verifying CI passes. Use when the user asks to submit, create, or open a pull request. disable-model-invocation: true --- - + # Submit PR @@ -11,9 +11,9 @@ Create a pull request for the current branch with a well-structured description. ## Steps -1. Run `make ci` -- must pass completely before creating PR +1. Run `make ci` — must pass completely before creating PR 2. **Generate the diff against main.** Run `git diff main...HEAD > /tmp/pr-diff.txt` to capture the full diff between the current branch and the head of main. This is the ONLY source of truth for what the PR contains. **Warning:** the diff can be very large. If the diff file exceeds context limits, process it in chunks (e.g., read sections with `head`/`tail` or split by file) rather than trying to load it all at once. -3. **Derive the PR title and description SOLELY from the diff.** Read the diff output and summarize what changed. Ignore commit messages, branch names, and any other metadata -- only the actual code/content diff matters. +3. **Derive the PR title and description SOLELY from the diff.** Read the diff output and summarize what changed. Ignore commit messages, branch names, and any other metadata — only the actual code/content diff matters. 4. Write PR body using the template in `.github/pull_request_template.md` 5. Fill in (based on the diff analysis from step 3): - TLDR: one sentence @@ -27,7 +27,7 @@ Create a pull request for the current branch with a well-structured description. ## Rules - Never create a PR if `make ci` fails -- PR description must be specific and tight -- no vague placeholders +- PR description must be specific and tight — no vague placeholders - Link to the relevant GitHub issue if one exists ## Success criteria diff --git a/.claude/skills/upgrade-packages/SKILL.md b/.claude/skills/upgrade-packages/SKILL.md index 11326c6..b2eb963 100644 --- a/.claude/skills/upgrade-packages/SKILL.md +++ b/.claude/skills/upgrade-packages/SKILL.md @@ -1,45 +1,71 @@ --- name: upgrade-packages -description: Upgrade all dependencies/packages to their latest versions for C#/.NET. Use when the user says "upgrade packages", "update dependencies", "bump versions", "update packages", or "upgrade deps". +description: Upgrade all dependencies/packages to their latest versions for C#/.NET and Python. Use when the user says "upgrade packages", "update dependencies", "bump versions", "update packages", or "upgrade deps". argument-hint: "[--check-only] [--major] [package-name]" --- - + # Upgrade Packages -Upgrade all project dependencies to their latest compatible (or latest major, if `--major`) versions. +Upgrade all project dependencies to their latest compatible (or latest major, if `--major`) versions for HealthcareSamples (C#/.NET primary, Python embedding service + scripts). ## Arguments -- `--check-only` -- List outdated packages without upgrading. Stop after Step 2. -- `--major` -- Include major version bumps (breaking changes). Without this flag, stay within semver-compatible ranges. +- `--check-only` — List outdated packages without upgrading. Stop after Step 2. +- `--major` — Include major version bumps (breaking changes). Without this flag, stay within semver-compatible ranges. - Any other argument is treated as a specific package name to upgrade (instead of all packages). -## Step 1 -- Detect language and package manager +## Step 1 — Detect language and package manager -This is a C#/.NET repo. Manifest files: -- `HealthcareSamples.sln` -- `Directory.Build.props` -- Individual `.csproj` files across Clinical, Scheduling, ICD10, Dashboard, and Shared projects +Inspect the repo for these manifest files: -## Step 2 -- List outdated packages +| Manifest file | Language | Package manager | +|---|---|---| +| `*.csproj` / `*.sln` | C# / .NET | NuGet (dotnet) | +| `Directory.Build.props` | C# / .NET | NuGet (dotnet) — central version pinning | +| `requirements.txt` | Python (ICD10/embedding-service, ICD10/scripts/CreateDb) | pip | +This repo uses both. Process .NET first, then Python. + +## Step 2 — List outdated packages + +Run the appropriate command BEFORE upgrading anything. Show the user what will change. + +### C# / .NET (NuGet) ```bash -dotnet list package --outdated +dotnet list HealthcareSamples.sln package --outdated ``` - -For transitive dependencies too: `dotnet list package --outdated --include-transitive` +For transitive dependencies too: `dotnet list HealthcareSamples.sln package --outdated --include-transitive` **Read the docs:** https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-list-package +### Python (pip) +The Python pieces use plain `requirements.txt` files. Install each in a venv and run `pip list --outdated`: +```bash +# embedding service +python -m venv /tmp/embedding-venv +/tmp/embedding-venv/bin/pip install -r ICD10/embedding-service/requirements.txt +/tmp/embedding-venv/bin/pip list --outdated + +# DB scripts +python -m venv /tmp/scripts-venv +/tmp/scripts-venv/bin/pip install -r ICD10/scripts/CreateDb/requirements.txt +/tmp/scripts-venv/bin/pip list --outdated +``` + +**Read the docs:** https://pip.pypa.io/en/stable/cli/pip_install/#cmdoption-U + If `--check-only` was passed, **stop here** and report the outdated list. -## Step 3 -- Read the official upgrade docs +## Step 3 — Read the official upgrade docs **Before running any upgrade command, you MUST fetch and read the official documentation URL listed above for the detected package manager.** Use WebFetch to retrieve the page. This ensures you use the correct flags and understand the behavior. Do not guess at flags or options from memory. -## Step 4 -- Upgrade packages +## Step 4 — Upgrade packages + +Run the upgrade. If a specific package name was given as an argument, upgrade only that package. +### C# / .NET (NuGet) There is NO single `dotnet upgrade-all` command. You must upgrade each package individually: ```bash # For each outdated package from Step 2: @@ -58,7 +84,17 @@ dotnet outdated --upgrade ``` **Read the docs:** https://github.com/dotnet-outdated/dotnet-outdated -## Step 5 -- Verify the upgrade +### Python (pip) +For `requirements.txt`: +```bash +/tmp/embedding-venv/bin/pip install --upgrade -r ICD10/embedding-service/requirements.txt +/tmp/embedding-venv/bin/pip freeze > ICD10/embedding-service/requirements.txt + +/tmp/scripts-venv/bin/pip install --upgrade -r ICD10/scripts/CreateDb/requirements.txt +/tmp/scripts-venv/bin/pip freeze > ICD10/scripts/CreateDb/requirements.txt +``` + +## Step 5 — Verify the upgrade After upgrading, run the project's build and test suite to confirm nothing broke: @@ -68,17 +104,17 @@ make ci If tests fail: 1. Read the failure output carefully -2. Check the changelog / migration guide for the upgraded packages +2. Check the changelog / migration guide for the upgraded packages (fetch the release notes URL if available) 3. Fix breaking changes in the code 4. Re-run tests -5. If stuck after 3 attempts on the same failure, report it to the user +5. If stuck after 3 attempts on the same failure, report it to the user with the error details and the package that caused it -## Step 6 -- Report +## Step 6 — Report Provide a summary: - Packages upgraded (old version -> new version) -- Packages skipped (and why) +- Packages skipped (and why, e.g., major version bump without `--major` flag) - Build/test result after upgrade - Any breaking changes that were fixed - Any packages that could not be upgraded (with error details) @@ -90,8 +126,8 @@ Provide a summary: - **Always run tests after upgrading** to catch breakage immediately - **Never remove packages** unless they were explicitly deprecated and replaced - **Never downgrade packages** unless rolling back a broken upgrade -- **Never modify lockfiles manually** -- let the package manager regenerate them -- **Commit nothing** -- leave changes in the working tree for the user to review +- **Never modify lockfiles manually** — let the package manager regenerate them +- **Commit nothing** — leave changes in the working tree for the user to review ## Success criteria diff --git a/.claude/skills/website-audit/SKILL.md b/.claude/skills/website-audit/SKILL.md index b511de6..5948cbf 100644 --- a/.claude/skills/website-audit/SKILL.md +++ b/.claude/skills/website-audit/SKILL.md @@ -2,7 +2,7 @@ name: website-audit description: Audits a website for SEO, AI search performance, structured data, mobile usability, broken links, and social media cards. Fixes issues found. Use when the user mentions "audit website", "SEO", "fix search ranking", "AI search", "structured data", "social media cards", or "website performance". --- - + # Website Audit @@ -26,11 +26,11 @@ Audit Progress: - [ ] Step 12: Report findings ``` -- Check the outputted HTML/CSS/JavaScript AFTER the website is generated by the static content generator. - Don't just check the static content before the website is generated. +- Check the outputted HTML/CSS/JavaScript AFTER the website is generated by the static content generator. - Don't just check the static content before the website is generated. - Fix issues at the core where the static content templates are stored - not in the outputted HTML (e.g. _site) - Never manually edit the generated website content directly -## Step 1 -- Read guidelines +## Step 1 — Read guidelines Fetch and read each of these before auditing. These are the authoritative references for every step that follows. @@ -38,40 +38,42 @@ Fetch and read each of these before auditing. These are the authoritative refere - [Top ways to ensure content performs well in Google's AI experiences](https://developers.google.com/search/blog/2025/05/succeeding-in-ai-search) - [SEO Starter Guide](https://developers.google.com/search/docs/fundamentals/seo-starter-guide) +If the repo has a business plan doc, take it into account + Identify the website source files in the repo. Determine the framework (static site generator, Next.js, Hugo, etc.) so you know where to find templates, metadata, and content. -## Step 2 -- Audit AI search readiness +## Step 2 — Audit AI search readiness Apply the guidance from the AI search article. Check: -1. **Content quality** -- Is content original, expert-level, and comprehensive? Flag thin or duplicated pages. -2. **Clear structure** -- Do pages use descriptive headings, lists, and concise answers to likely questions? -3. **Entity clarity** -- Are key terms, products, and concepts defined clearly so AI can extract them? -4. **Freshness signals** -- Are dates, update timestamps, and authorship present? +1. **Content quality** — Is content original, expert-level, and comprehensive? Flag thin or duplicated pages. +2. **Clear structure** — Do pages use descriptive headings, lists, and concise answers to likely questions? +3. **Entity clarity** — Are key terms, products, and concepts defined clearly so AI can extract them? +4. **Freshness signals** — Are dates, update timestamps, and authorship present? Fix issues directly in the source files. For each fix, note what changed and why. -## Step 3 -- Audit SEO and keywords +## Step 3 — Audit SEO and keywords 1. Search [Google Trends](https://trends.google.com/home) for trending keywords related to the website's content. 2. Review each page's ``, `<meta name="description">`, and `<h1>` tags. -3. Check for keyword opportunities -- can trending terms be naturally inserted into headings, descriptions, or body content? +3. Check for keyword opportunities — can trending terms be naturally inserted into headings, descriptions, or body content? 4. Verify each page has a unique, descriptive title (50-60 chars) and meta description (150-160 chars). 5. Check image `alt` attributes describe the image content and include relevant keywords where natural. Apply the [SEO Starter Guide](https://developers.google.com/search/docs/fundamentals/seo-starter-guide) principles. Fix issues directly. -## Step 4 -- Audit crawling and indexing +## Step 4 — Audit crawling and indexing Reference: [Overview of crawling and indexing topics](https://developers.google.com/search/docs/crawling-indexing) -1. **robots.txt** -- Locate and review it. Verify it doesn't block important pages. Reference: [robots.txt spec](https://developers.google.com/search/docs/crawling-indexing/robots-txt) -2. **Sitemap** -- Locate the sitemap (or sitemap index). Verify all important pages are listed and no dead URLs are included. Reference: [Sitemap guidelines](https://developers.google.com/search/docs/crawling-indexing/sitemaps/large-sitemaps) -3. **Meta robots tags** -- Check for unintended `noindex` or `nofollow` directives on pages that should be indexed. +1. **robots.txt** — Locate and review it. Verify it doesn't block important pages. Reference: [robots.txt spec](https://developers.google.com/search/docs/crawling-indexing/robots-txt) +2. **Sitemap** — Locate the sitemap (or sitemap index). Verify all important pages are listed and no dead URLs are included. Reference: [Sitemap guidelines](https://developers.google.com/search/docs/crawling-indexing/sitemaps/large-sitemaps) +3. **Meta robots tags** — Check for unintended `noindex` or `nofollow` directives on pages that should be indexed. Note: robots.txt and sitemaps are often auto-generated. If so, check the generator config rather than the output file. -## Step 5 -- Audit broken links and canonicalization +## Step 5 — Audit broken links and canonicalization Reference: [What is canonicalization](https://developers.google.com/search/docs/crawling-indexing/canonicalization) @@ -80,7 +82,7 @@ Reference: [What is canonicalization](https://developers.google.com/search/docs/ 3. Check for duplicate content accessible via multiple URLs (with/without trailing slash, www vs non-www). 4. Verify redirects use 301 (permanent) not 302 (temporary) where appropriate. -## Step 6 -- Audit mobile usability +## Step 6 — Audit mobile usability Reference: [Mobile-first indexing best practices](https://developers.google.com/search/docs/crawling-indexing/mobile/mobile-sites-mobile-first-indexing) @@ -89,7 +91,7 @@ Reference: [Mobile-first indexing best practices](https://developers.google.com/ 3. Verify touch targets are adequately sized (min 48x48px). 4. Check font sizes are readable without zooming (min 16px body text). -## Step 7 -- Audit structured data +## Step 7 — Audit structured data Reference: [Structured data guidelines](https://developers.google.com/search/docs/appearance/structured-data/sd-policies) @@ -102,7 +104,7 @@ Reference: [Structured data guidelines](https://developers.google.com/search/doc - **FAQ** for pages with question/answer content 4. Validate JSON-LD syntax is correct. -## Step 8 -- Audit social media cards +## Step 8 — Audit social media cards Reference: [Implementing Social Media Preview Cards](https://documentation.platformos.com/use-cases/implementing-social-media-preview-cards) @@ -124,31 +126,31 @@ Ensure that all claims are backed up with a link to a reputable source. As an ex Search for the authoritative URL and add a link to the URL. If it is not available, change the claim to something that can be substatiated. -## Step 10 -- Audit Design Compliance +## Step 10 — Audit Design Compliance Read the design system docs and view the design screens in the designsystem folder. -## Step 11 -- Test with Playwright +## Step 11 — Test with Playwright Build and run the website locally using `make website-run` (or the project's equivalent dev server command). **Desktop tests (1280x720):** -1. Navigate to the homepage -- take a screenshot. -2. Navigate to each major section -- verify pages load without errors. +1. Navigate to the homepage — take a screenshot. +2. Navigate to each major section — verify pages load without errors. 3. Check the browser console for JavaScript errors. 4. Verify all navigation links work. **Mobile tests (375x667, iPhone SE):** 1. Resize the browser to mobile dimensions. -2. Navigate to the homepage -- take a screenshot. +2. Navigate to the homepage — take a screenshot. 3. Verify the layout is responsive (no horizontal overflow, readable text). 4. Test navigation menu (hamburger menu if applicable). If any page fails to load or has console errors, fix the issue and retest. -## Step 12 -- Report findings +## Step 12 — Report findings Summarize the audit results: @@ -170,8 +172,8 @@ Summarize the audit results: ## Rules -- **Fix issues directly** -- don't just report them. Only flag issues as warnings when they require human judgment (e.g., content tone, keyword selection). -- **One step at a time** -- complete each step before moving to the next. -- **Preserve existing content** -- improve structure and metadata without rewriting the author's voice. -- **No keyword stuffing** -- keywords must read naturally in context. -- **Respect the framework** -- edit templates/configs, not generated output files. +- **Fix issues directly** — don't just report them. Only flag issues as warnings when they require human judgment (e.g., content tone, keyword selection). +- **One step at a time** — complete each step before moving to the next. +- **Preserve existing content** — improve structure and metadata without rewriting the author's voice. +- **No keyword stuffing** — keywords must read naturally in context. +- **Respect the framework** — edit templates/configs, not generated output files. diff --git a/.clinerules/00-read-instructions.md b/.clinerules/00-read-instructions.md index 3af39da..f0ce473 100644 --- a/.clinerules/00-read-instructions.md +++ b/.clinerules/00-read-instructions.md @@ -1,4 +1,4 @@ -<!-- agent-pmo:d58c330 --> +<!-- agent-pmo:29b9dcf --> # Single Source of Truth diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 0e46e98..7595149 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -1,4 +1,4 @@ -<!-- agent-pmo:d58c330 --> +<!-- agent-pmo:29b9dcf --> @CLAUDE.md diff --git a/.gitignore b/.gitignore index f2ac821..68b9e6a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -# agent-pmo:d58c330 +# agent-pmo:29b9dcf # ============================================================================= # UNIVERSAL diff --git a/AGENTS.md b/AGENTS.md index 3af39da..f0ce473 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,4 +1,4 @@ -<!-- agent-pmo:d58c330 --> +<!-- agent-pmo:29b9dcf --> # Single Source of Truth diff --git a/CLAUDE.md b/CLAUDE.md index 9ca39ee..8939651 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,4 +1,4 @@ -<!-- agent-pmo:d58c330 --> +<!-- agent-pmo:29b9dcf --> # HealthcareSamples -- Agent Instructions diff --git a/Clinical/Clinical.Api/GlobalUsings.cs b/Clinical/Clinical.Api/GlobalUsings.cs index dbeddb9..a820655 100644 --- a/Clinical/Clinical.Api/GlobalUsings.cs +++ b/Clinical/Clinical.Api/GlobalUsings.cs @@ -1,11 +1,11 @@ global using System; global using Generated; global using Microsoft.Extensions.Logging; -global using Npgsql; -global using Outcome; global using Nimblesite.Sql.Model; global using Nimblesite.Sync.Core; global using Nimblesite.Sync.Postgres; +global using Npgsql; +global using Outcome; global using GetConditionsError = Outcome.Result< System.Collections.Immutable.ImmutableList<Generated.GetConditionsByPatient>, Nimblesite.Sql.Model.SqlError @@ -54,43 +54,82 @@ global using GetPatientByIdError = Outcome.Result< System.Collections.Immutable.ImmutableList<Generated.GetPatientById>, Nimblesite.Sql.Model.SqlError ->.Error<System.Collections.Immutable.ImmutableList<Generated.GetPatientById>, Nimblesite.Sql.Model.SqlError>; +>.Error< + System.Collections.Immutable.ImmutableList<Generated.GetPatientById>, + Nimblesite.Sql.Model.SqlError +>; // GetPatientById query result type aliases global using GetPatientByIdOk = Outcome.Result< System.Collections.Immutable.ImmutableList<Generated.GetPatientById>, Nimblesite.Sql.Model.SqlError ->.Ok<System.Collections.Immutable.ImmutableList<Generated.GetPatientById>, Nimblesite.Sql.Model.SqlError>; +>.Ok< + System.Collections.Immutable.ImmutableList<Generated.GetPatientById>, + Nimblesite.Sql.Model.SqlError +>; global using GetPatientsError = Outcome.Result< System.Collections.Immutable.ImmutableList<Generated.GetPatients>, Nimblesite.Sql.Model.SqlError ->.Error<System.Collections.Immutable.ImmutableList<Generated.GetPatients>, Nimblesite.Sql.Model.SqlError>; +>.Error< + System.Collections.Immutable.ImmutableList<Generated.GetPatients>, + Nimblesite.Sql.Model.SqlError +>; // GetPatients query result type aliases global using GetPatientsOk = Outcome.Result< System.Collections.Immutable.ImmutableList<Generated.GetPatients>, Nimblesite.Sql.Model.SqlError ->.Ok<System.Collections.Immutable.ImmutableList<Generated.GetPatients>, Nimblesite.Sql.Model.SqlError>; -global using InsertError = Outcome.Result<int, Nimblesite.Sql.Model.SqlError>.Error<int, Nimblesite.Sql.Model.SqlError>; +>.Ok< + System.Collections.Immutable.ImmutableList<Generated.GetPatients>, + Nimblesite.Sql.Model.SqlError +>; +global using InsertError = Outcome.Result<int, Nimblesite.Sql.Model.SqlError>.Error< + int, + Nimblesite.Sql.Model.SqlError +>; // Insert result type aliases -global using InsertOk = Outcome.Result<int, Nimblesite.Sql.Model.SqlError>.Ok<int, Nimblesite.Sql.Model.SqlError>; +global using InsertOk = Outcome.Result<int, Nimblesite.Sql.Model.SqlError>.Ok< + int, + Nimblesite.Sql.Model.SqlError +>; global using SearchPatientsError = Outcome.Result< System.Collections.Immutable.ImmutableList<Generated.SearchPatients>, Nimblesite.Sql.Model.SqlError ->.Error<System.Collections.Immutable.ImmutableList<Generated.SearchPatients>, Nimblesite.Sql.Model.SqlError>; +>.Error< + System.Collections.Immutable.ImmutableList<Generated.SearchPatients>, + Nimblesite.Sql.Model.SqlError +>; // SearchPatients query result type aliases global using SearchPatientsOk = Outcome.Result< System.Collections.Immutable.ImmutableList<Generated.SearchPatients>, Nimblesite.Sql.Model.SqlError ->.Ok<System.Collections.Immutable.ImmutableList<Generated.SearchPatients>, Nimblesite.Sql.Model.SqlError>; +>.Ok< + System.Collections.Immutable.ImmutableList<Generated.SearchPatients>, + Nimblesite.Sql.Model.SqlError +>; // Sync result type aliases -global using StringSyncError = Outcome.Result<string, Nimblesite.Sync.Core.SyncError>.Error<string, Nimblesite.Sync.Core.SyncError>; -global using StringSyncOk = Outcome.Result<string, Nimblesite.Sync.Core.SyncError>.Ok<string, Nimblesite.Sync.Core.SyncError>; +global using StringSyncError = Outcome.Result<string, Nimblesite.Sync.Core.SyncError>.Error< + string, + Nimblesite.Sync.Core.SyncError +>; +global using StringSyncOk = Outcome.Result<string, Nimblesite.Sync.Core.SyncError>.Ok< + string, + Nimblesite.Sync.Core.SyncError +>; global using SyncLogListError = Outcome.Result< System.Collections.Generic.IReadOnlyList<Nimblesite.Sync.Core.SyncLogEntry>, Nimblesite.Sync.Core.SyncError ->.Error<System.Collections.Generic.IReadOnlyList<Nimblesite.Sync.Core.SyncLogEntry>, Nimblesite.Sync.Core.SyncError>; +>.Error< + System.Collections.Generic.IReadOnlyList<Nimblesite.Sync.Core.SyncLogEntry>, + Nimblesite.Sync.Core.SyncError +>; global using SyncLogListOk = Outcome.Result< System.Collections.Generic.IReadOnlyList<Nimblesite.Sync.Core.SyncLogEntry>, Nimblesite.Sync.Core.SyncError ->.Ok<System.Collections.Generic.IReadOnlyList<Nimblesite.Sync.Core.SyncLogEntry>, Nimblesite.Sync.Core.SyncError>; +>.Ok< + System.Collections.Generic.IReadOnlyList<Nimblesite.Sync.Core.SyncLogEntry>, + Nimblesite.Sync.Core.SyncError +>; // Update result type aliases -global using UpdateOk = Outcome.Result<int, Nimblesite.Sql.Model.SqlError>.Ok<int, Nimblesite.Sql.Model.SqlError>; +global using UpdateOk = Outcome.Result<int, Nimblesite.Sql.Model.SqlError>.Ok< + int, + Nimblesite.Sql.Model.SqlError +>; diff --git a/Directory.Build.props b/Directory.Build.props index 08cd421..3e7308b 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -91,5 +91,4 @@ <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference> </ItemGroup> - </Project> diff --git a/Gatekeeper/Gatekeeper.Api.Tests/GlobalUsings.cs b/Gatekeeper/Gatekeeper.Api.Tests/GlobalUsings.cs index c488f59..70958fe 100644 --- a/Gatekeeper/Gatekeeper.Api.Tests/GlobalUsings.cs +++ b/Gatekeeper/Gatekeeper.Api.Tests/GlobalUsings.cs @@ -17,20 +17,35 @@ global using GetPermissionByCodeOk = Outcome.Result< System.Collections.Immutable.ImmutableList<Generated.GetPermissionByCode>, Nimblesite.Sql.Model.SqlError ->.Ok<System.Collections.Immutable.ImmutableList<Generated.GetPermissionByCode>, Nimblesite.Sql.Model.SqlError>; +>.Ok< + System.Collections.Immutable.ImmutableList<Generated.GetPermissionByCode>, + Nimblesite.Sql.Model.SqlError +>; global using GetRolePermissionsError = Outcome.Result< System.Collections.Immutable.ImmutableList<Generated.GetRolePermissions>, Nimblesite.Sql.Model.SqlError ->.Error<System.Collections.Immutable.ImmutableList<Generated.GetRolePermissions>, Nimblesite.Sql.Model.SqlError>; +>.Error< + System.Collections.Immutable.ImmutableList<Generated.GetRolePermissions>, + Nimblesite.Sql.Model.SqlError +>; global using GetRolePermissionsOk = Outcome.Result< System.Collections.Immutable.ImmutableList<Generated.GetRolePermissions>, Nimblesite.Sql.Model.SqlError ->.Ok<System.Collections.Immutable.ImmutableList<Generated.GetRolePermissions>, Nimblesite.Sql.Model.SqlError>; +>.Ok< + System.Collections.Immutable.ImmutableList<Generated.GetRolePermissions>, + Nimblesite.Sql.Model.SqlError +>; global using GetSessionRevokedError = Outcome.Result< System.Collections.Immutable.ImmutableList<Generated.GetSessionRevoked>, Nimblesite.Sql.Model.SqlError ->.Error<System.Collections.Immutable.ImmutableList<Generated.GetSessionRevoked>, Nimblesite.Sql.Model.SqlError>; +>.Error< + System.Collections.Immutable.ImmutableList<Generated.GetSessionRevoked>, + Nimblesite.Sql.Model.SqlError +>; global using GetSessionRevokedOk = Outcome.Result< System.Collections.Immutable.ImmutableList<Generated.GetSessionRevoked>, Nimblesite.Sql.Model.SqlError ->.Ok<System.Collections.Immutable.ImmutableList<Generated.GetSessionRevoked>, Nimblesite.Sql.Model.SqlError>; +>.Ok< + System.Collections.Immutable.ImmutableList<Generated.GetSessionRevoked>, + Nimblesite.Sql.Model.SqlError +>; diff --git a/Gatekeeper/Gatekeeper.Api/GlobalUsings.cs b/Gatekeeper/Gatekeeper.Api/GlobalUsings.cs index 597dc01..a557fca 100644 --- a/Gatekeeper/Gatekeeper.Api/GlobalUsings.cs +++ b/Gatekeeper/Gatekeeper.Api/GlobalUsings.cs @@ -7,53 +7,86 @@ global using Fido2NetLib.Objects; global using Generated; global using Microsoft.Extensions.Logging; +global using Nimblesite.Sql.Model; global using Npgsql; global using Outcome; -global using Nimblesite.Sql.Model; global using CheckResourceGrantOk = Outcome.Result< System.Collections.Immutable.ImmutableList<Generated.CheckResourceGrant>, Nimblesite.Sql.Model.SqlError ->.Ok<System.Collections.Immutable.ImmutableList<Generated.CheckResourceGrant>, Nimblesite.Sql.Model.SqlError>; +>.Ok< + System.Collections.Immutable.ImmutableList<Generated.CheckResourceGrant>, + Nimblesite.Sql.Model.SqlError +>; // Insert result type alias global using GetChallengeByIdOk = Outcome.Result< System.Collections.Immutable.ImmutableList<Generated.GetChallengeById>, Nimblesite.Sql.Model.SqlError ->.Ok<System.Collections.Immutable.ImmutableList<Generated.GetChallengeById>, Nimblesite.Sql.Model.SqlError>; +>.Ok< + System.Collections.Immutable.ImmutableList<Generated.GetChallengeById>, + Nimblesite.Sql.Model.SqlError +>; // Additional query result type aliases global using GetCredentialByIdOk = Outcome.Result< System.Collections.Immutable.ImmutableList<Generated.GetCredentialById>, Nimblesite.Sql.Model.SqlError ->.Ok<System.Collections.Immutable.ImmutableList<Generated.GetCredentialById>, Nimblesite.Sql.Model.SqlError>; +>.Ok< + System.Collections.Immutable.ImmutableList<Generated.GetCredentialById>, + Nimblesite.Sql.Model.SqlError +>; global using GetSessionRevokedError = Outcome.Result< System.Collections.Immutable.ImmutableList<Generated.GetSessionRevoked>, Nimblesite.Sql.Model.SqlError ->.Error<System.Collections.Immutable.ImmutableList<Generated.GetSessionRevoked>, Nimblesite.Sql.Model.SqlError>; +>.Error< + System.Collections.Immutable.ImmutableList<Generated.GetSessionRevoked>, + Nimblesite.Sql.Model.SqlError +>; global using GetSessionRevokedOk = Outcome.Result< System.Collections.Immutable.ImmutableList<Generated.GetSessionRevoked>, Nimblesite.Sql.Model.SqlError ->.Ok<System.Collections.Immutable.ImmutableList<Generated.GetSessionRevoked>, Nimblesite.Sql.Model.SqlError>; +>.Ok< + System.Collections.Immutable.ImmutableList<Generated.GetSessionRevoked>, + Nimblesite.Sql.Model.SqlError +>; // Query result type aliases global using GetUserByEmailOk = Outcome.Result< System.Collections.Immutable.ImmutableList<Generated.GetUserByEmail>, Nimblesite.Sql.Model.SqlError ->.Ok<System.Collections.Immutable.ImmutableList<Generated.GetUserByEmail>, Nimblesite.Sql.Model.SqlError>; +>.Ok< + System.Collections.Immutable.ImmutableList<Generated.GetUserByEmail>, + Nimblesite.Sql.Model.SqlError +>; global using GetUserByIdOk = Outcome.Result< System.Collections.Immutable.ImmutableList<Generated.GetUserById>, Nimblesite.Sql.Model.SqlError ->.Ok<System.Collections.Immutable.ImmutableList<Generated.GetUserById>, Nimblesite.Sql.Model.SqlError>; +>.Ok< + System.Collections.Immutable.ImmutableList<Generated.GetUserById>, + Nimblesite.Sql.Model.SqlError +>; global using GetUserCredentialsError = Outcome.Result< System.Collections.Immutable.ImmutableList<Generated.GetUserCredentials>, Nimblesite.Sql.Model.SqlError ->.Error<System.Collections.Immutable.ImmutableList<Generated.GetUserCredentials>, Nimblesite.Sql.Model.SqlError>; +>.Error< + System.Collections.Immutable.ImmutableList<Generated.GetUserCredentials>, + Nimblesite.Sql.Model.SqlError +>; global using GetUserCredentialsOk = Outcome.Result< System.Collections.Immutable.ImmutableList<Generated.GetUserCredentials>, Nimblesite.Sql.Model.SqlError ->.Ok<System.Collections.Immutable.ImmutableList<Generated.GetUserCredentials>, Nimblesite.Sql.Model.SqlError>; +>.Ok< + System.Collections.Immutable.ImmutableList<Generated.GetUserCredentials>, + Nimblesite.Sql.Model.SqlError +>; global using GetUserPermissionsOk = Outcome.Result< System.Collections.Immutable.ImmutableList<Generated.GetUserPermissions>, Nimblesite.Sql.Model.SqlError ->.Ok<System.Collections.Immutable.ImmutableList<Generated.GetUserPermissions>, Nimblesite.Sql.Model.SqlError>; +>.Ok< + System.Collections.Immutable.ImmutableList<Generated.GetUserPermissions>, + Nimblesite.Sql.Model.SqlError +>; global using GetUserRolesOk = Outcome.Result< System.Collections.Immutable.ImmutableList<Generated.GetUserRoles>, Nimblesite.Sql.Model.SqlError ->.Ok<System.Collections.Immutable.ImmutableList<Generated.GetUserRoles>, Nimblesite.Sql.Model.SqlError>; +>.Ok< + System.Collections.Immutable.ImmutableList<Generated.GetUserRoles>, + Nimblesite.Sql.Model.SqlError +>; diff --git a/ICD10/ICD10.Api/GlobalUsings.cs b/ICD10/ICD10.Api/GlobalUsings.cs index e9da852..a97f387 100644 --- a/ICD10/ICD10.Api/GlobalUsings.cs +++ b/ICD10/ICD10.Api/GlobalUsings.cs @@ -2,27 +2,39 @@ global using System.Collections.Immutable; global using Generated; global using Microsoft.Extensions.Logging; +global using Nimblesite.Sql.Model; global using Npgsql; global using Outcome; -global using Nimblesite.Sql.Model; global using GetAchiBlocksError = Outcome.Result< System.Collections.Immutable.ImmutableList<Generated.GetAchiBlocks>, Nimblesite.Sql.Model.SqlError ->.Error<System.Collections.Immutable.ImmutableList<Generated.GetAchiBlocks>, Nimblesite.Sql.Model.SqlError>; +>.Error< + System.Collections.Immutable.ImmutableList<Generated.GetAchiBlocks>, + Nimblesite.Sql.Model.SqlError +>; // GetAchiBlocks query result type aliases global using GetAchiBlocksOk = Outcome.Result< System.Collections.Immutable.ImmutableList<Generated.GetAchiBlocks>, Nimblesite.Sql.Model.SqlError ->.Ok<System.Collections.Immutable.ImmutableList<Generated.GetAchiBlocks>, Nimblesite.Sql.Model.SqlError>; +>.Ok< + System.Collections.Immutable.ImmutableList<Generated.GetAchiBlocks>, + Nimblesite.Sql.Model.SqlError +>; global using GetAchiCodeByCodeError = Outcome.Result< System.Collections.Immutable.ImmutableList<Generated.GetAchiCodeByCode>, Nimblesite.Sql.Model.SqlError ->.Error<System.Collections.Immutable.ImmutableList<Generated.GetAchiCodeByCode>, Nimblesite.Sql.Model.SqlError>; +>.Error< + System.Collections.Immutable.ImmutableList<Generated.GetAchiCodeByCode>, + Nimblesite.Sql.Model.SqlError +>; // GetAchiCodeByCode query result type aliases global using GetAchiCodeByCodeOk = Outcome.Result< System.Collections.Immutable.ImmutableList<Generated.GetAchiCodeByCode>, Nimblesite.Sql.Model.SqlError ->.Ok<System.Collections.Immutable.ImmutableList<Generated.GetAchiCodeByCode>, Nimblesite.Sql.Model.SqlError>; +>.Ok< + System.Collections.Immutable.ImmutableList<Generated.GetAchiCodeByCode>, + Nimblesite.Sql.Model.SqlError +>; global using GetAchiCodesByBlockError = Outcome.Result< System.Collections.Immutable.ImmutableList<Generated.GetAchiCodesByBlock>, Nimblesite.Sql.Model.SqlError @@ -34,16 +46,25 @@ global using GetAchiCodesByBlockOk = Outcome.Result< System.Collections.Immutable.ImmutableList<Generated.GetAchiCodesByBlock>, Nimblesite.Sql.Model.SqlError ->.Ok<System.Collections.Immutable.ImmutableList<Generated.GetAchiCodesByBlock>, Nimblesite.Sql.Model.SqlError>; +>.Ok< + System.Collections.Immutable.ImmutableList<Generated.GetAchiCodesByBlock>, + Nimblesite.Sql.Model.SqlError +>; global using GetBlocksByChapterError = Outcome.Result< System.Collections.Immutable.ImmutableList<Generated.GetBlocksByChapter>, Nimblesite.Sql.Model.SqlError ->.Error<System.Collections.Immutable.ImmutableList<Generated.GetBlocksByChapter>, Nimblesite.Sql.Model.SqlError>; +>.Error< + System.Collections.Immutable.ImmutableList<Generated.GetBlocksByChapter>, + Nimblesite.Sql.Model.SqlError +>; // GetBlocksByChapter query result type aliases global using GetBlocksByChapterOk = Outcome.Result< System.Collections.Immutable.ImmutableList<Generated.GetBlocksByChapter>, Nimblesite.Sql.Model.SqlError ->.Ok<System.Collections.Immutable.ImmutableList<Generated.GetBlocksByChapter>, Nimblesite.Sql.Model.SqlError>; +>.Ok< + System.Collections.Immutable.ImmutableList<Generated.GetBlocksByChapter>, + Nimblesite.Sql.Model.SqlError +>; global using GetCategoriesByBlockError = Outcome.Result< System.Collections.Immutable.ImmutableList<Generated.GetCategoriesByBlock>, Nimblesite.Sql.Model.SqlError @@ -55,49 +76,82 @@ global using GetCategoriesByBlockOk = Outcome.Result< System.Collections.Immutable.ImmutableList<Generated.GetCategoriesByBlock>, Nimblesite.Sql.Model.SqlError ->.Ok<System.Collections.Immutable.ImmutableList<Generated.GetCategoriesByBlock>, Nimblesite.Sql.Model.SqlError>; +>.Ok< + System.Collections.Immutable.ImmutableList<Generated.GetCategoriesByBlock>, + Nimblesite.Sql.Model.SqlError +>; global using GetChaptersError = Outcome.Result< System.Collections.Immutable.ImmutableList<Generated.GetChapters>, Nimblesite.Sql.Model.SqlError ->.Error<System.Collections.Immutable.ImmutableList<Generated.GetChapters>, Nimblesite.Sql.Model.SqlError>; +>.Error< + System.Collections.Immutable.ImmutableList<Generated.GetChapters>, + Nimblesite.Sql.Model.SqlError +>; // GetChapters query result type aliases global using GetChaptersOk = Outcome.Result< System.Collections.Immutable.ImmutableList<Generated.GetChapters>, Nimblesite.Sql.Model.SqlError ->.Ok<System.Collections.Immutable.ImmutableList<Generated.GetChapters>, Nimblesite.Sql.Model.SqlError>; +>.Ok< + System.Collections.Immutable.ImmutableList<Generated.GetChapters>, + Nimblesite.Sql.Model.SqlError +>; global using GetCodeByCodeError = Outcome.Result< System.Collections.Immutable.ImmutableList<Generated.GetCodeByCode>, Nimblesite.Sql.Model.SqlError ->.Error<System.Collections.Immutable.ImmutableList<Generated.GetCodeByCode>, Nimblesite.Sql.Model.SqlError>; +>.Error< + System.Collections.Immutable.ImmutableList<Generated.GetCodeByCode>, + Nimblesite.Sql.Model.SqlError +>; // GetCodeByCode query result type aliases global using GetCodeByCodeOk = Outcome.Result< System.Collections.Immutable.ImmutableList<Generated.GetCodeByCode>, Nimblesite.Sql.Model.SqlError ->.Ok<System.Collections.Immutable.ImmutableList<Generated.GetCodeByCode>, Nimblesite.Sql.Model.SqlError>; +>.Ok< + System.Collections.Immutable.ImmutableList<Generated.GetCodeByCode>, + Nimblesite.Sql.Model.SqlError +>; global using GetCodesByCategoryError = Outcome.Result< System.Collections.Immutable.ImmutableList<Generated.GetCodesByCategory>, Nimblesite.Sql.Model.SqlError ->.Error<System.Collections.Immutable.ImmutableList<Generated.GetCodesByCategory>, Nimblesite.Sql.Model.SqlError>; +>.Error< + System.Collections.Immutable.ImmutableList<Generated.GetCodesByCategory>, + Nimblesite.Sql.Model.SqlError +>; // GetCodesByCategory query result type aliases global using GetCodesByCategoryOk = Outcome.Result< System.Collections.Immutable.ImmutableList<Generated.GetCodesByCategory>, Nimblesite.Sql.Model.SqlError ->.Ok<System.Collections.Immutable.ImmutableList<Generated.GetCodesByCategory>, Nimblesite.Sql.Model.SqlError>; +>.Ok< + System.Collections.Immutable.ImmutableList<Generated.GetCodesByCategory>, + Nimblesite.Sql.Model.SqlError +>; global using SearchAchiCodesError = Outcome.Result< System.Collections.Immutable.ImmutableList<Generated.SearchAchiCodes>, Nimblesite.Sql.Model.SqlError ->.Error<System.Collections.Immutable.ImmutableList<Generated.SearchAchiCodes>, Nimblesite.Sql.Model.SqlError>; +>.Error< + System.Collections.Immutable.ImmutableList<Generated.SearchAchiCodes>, + Nimblesite.Sql.Model.SqlError +>; // SearchAchiCodes query result type aliases global using SearchAchiCodesOk = Outcome.Result< System.Collections.Immutable.ImmutableList<Generated.SearchAchiCodes>, Nimblesite.Sql.Model.SqlError ->.Ok<System.Collections.Immutable.ImmutableList<Generated.SearchAchiCodes>, Nimblesite.Sql.Model.SqlError>; +>.Ok< + System.Collections.Immutable.ImmutableList<Generated.SearchAchiCodes>, + Nimblesite.Sql.Model.SqlError +>; global using SearchIcd10CodesError = Outcome.Result< System.Collections.Immutable.ImmutableList<Generated.SearchIcd10Codes>, Nimblesite.Sql.Model.SqlError ->.Error<System.Collections.Immutable.ImmutableList<Generated.SearchIcd10Codes>, Nimblesite.Sql.Model.SqlError>; +>.Error< + System.Collections.Immutable.ImmutableList<Generated.SearchIcd10Codes>, + Nimblesite.Sql.Model.SqlError +>; // SearchIcd10Codes query result type aliases global using SearchIcd10CodesOk = Outcome.Result< System.Collections.Immutable.ImmutableList<Generated.SearchIcd10Codes>, Nimblesite.Sql.Model.SqlError ->.Ok<System.Collections.Immutable.ImmutableList<Generated.SearchIcd10Codes>, Nimblesite.Sql.Model.SqlError>; +>.Ok< + System.Collections.Immutable.ImmutableList<Generated.SearchIcd10Codes>, + Nimblesite.Sql.Model.SqlError +>; diff --git a/Makefile b/Makefile index 3635883..a705740 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -# agent-pmo:d58c330 +# agent-pmo:29b9dcf # ============================================================================= # Standard Makefile — HealthcareSamples # Cross-platform: Linux, macOS, Windows (via GNU Make) @@ -49,12 +49,12 @@ lint: fmt-check ## fmt: Format all code in-place fmt: @echo "==> Formatting..." - dotnet csharpier . + dotnet csharpier format . ## fmt-check: Check formatting without modifying fmt-check: @echo "==> Checking format..." - dotnet csharpier . --check + dotnet csharpier check . ## clean: Remove all build artifacts clean: diff --git a/Scheduling/Scheduling.Api/GlobalUsings.cs b/Scheduling/Scheduling.Api/GlobalUsings.cs index ab00815..76582a4 100644 --- a/Scheduling/Scheduling.Api/GlobalUsings.cs +++ b/Scheduling/Scheduling.Api/GlobalUsings.cs @@ -1,13 +1,16 @@ global using System; global using Generated; global using Microsoft.Extensions.Logging; -global using Npgsql; -global using Outcome; global using Nimblesite.Sql.Model; global using Nimblesite.Sync.Core; global using Nimblesite.Sync.Postgres; +global using Npgsql; +global using Outcome; // Sync result type aliases -global using BoolSyncError = Outcome.Result<bool, Nimblesite.Sync.Core.SyncError>.Error<bool, Nimblesite.Sync.Core.SyncError>; +global using BoolSyncError = Outcome.Result<bool, Nimblesite.Sync.Core.SyncError>.Error< + bool, + Nimblesite.Sync.Core.SyncError +>; global using GetAllPractitionersError = Outcome.Result< System.Collections.Immutable.ImmutableList<Generated.GetAllPractitioners>, Nimblesite.Sql.Model.SqlError @@ -19,16 +22,25 @@ global using GetAllPractitionersOk = Outcome.Result< System.Collections.Immutable.ImmutableList<Generated.GetAllPractitioners>, Nimblesite.Sql.Model.SqlError ->.Ok<System.Collections.Immutable.ImmutableList<Generated.GetAllPractitioners>, Nimblesite.Sql.Model.SqlError>; +>.Ok< + System.Collections.Immutable.ImmutableList<Generated.GetAllPractitioners>, + Nimblesite.Sql.Model.SqlError +>; global using GetAppointmentByIdError = Outcome.Result< System.Collections.Immutable.ImmutableList<Generated.GetAppointmentById>, Nimblesite.Sql.Model.SqlError ->.Error<System.Collections.Immutable.ImmutableList<Generated.GetAppointmentById>, Nimblesite.Sql.Model.SqlError>; +>.Error< + System.Collections.Immutable.ImmutableList<Generated.GetAppointmentById>, + Nimblesite.Sql.Model.SqlError +>; // GetAppointmentById query result type aliases global using GetAppointmentByIdOk = Outcome.Result< System.Collections.Immutable.ImmutableList<Generated.GetAppointmentById>, Nimblesite.Sql.Model.SqlError ->.Ok<System.Collections.Immutable.ImmutableList<Generated.GetAppointmentById>, Nimblesite.Sql.Model.SqlError>; +>.Ok< + System.Collections.Immutable.ImmutableList<Generated.GetAppointmentById>, + Nimblesite.Sql.Model.SqlError +>; global using GetAppointmentsByPatientError = Outcome.Result< System.Collections.Immutable.ImmutableList<Generated.GetAppointmentsByPatient>, Nimblesite.Sql.Model.SqlError @@ -70,7 +82,10 @@ global using GetPractitionerByIdOk = Outcome.Result< System.Collections.Immutable.ImmutableList<Generated.GetPractitionerById>, Nimblesite.Sql.Model.SqlError ->.Ok<System.Collections.Immutable.ImmutableList<Generated.GetPractitionerById>, Nimblesite.Sql.Model.SqlError>; +>.Ok< + System.Collections.Immutable.ImmutableList<Generated.GetPractitionerById>, + Nimblesite.Sql.Model.SqlError +>; global using GetUpcomingAppointmentsError = Outcome.Result< System.Collections.Immutable.ImmutableList<Generated.GetUpcomingAppointments>, Nimblesite.Sql.Model.SqlError @@ -86,9 +101,15 @@ System.Collections.Immutable.ImmutableList<Generated.GetUpcomingAppointments>, Nimblesite.Sql.Model.SqlError >; -global using InsertError = Outcome.Result<int, Nimblesite.Sql.Model.SqlError>.Error<int, Nimblesite.Sql.Model.SqlError>; +global using InsertError = Outcome.Result<int, Nimblesite.Sql.Model.SqlError>.Error< + int, + Nimblesite.Sql.Model.SqlError +>; // Insert result type aliases -global using InsertOk = Outcome.Result<int, Nimblesite.Sql.Model.SqlError>.Ok<int, Nimblesite.Sql.Model.SqlError>; +global using InsertOk = Outcome.Result<int, Nimblesite.Sql.Model.SqlError>.Ok< + int, + Nimblesite.Sql.Model.SqlError +>; global using SearchPractitionersError = Outcome.Result< System.Collections.Immutable.ImmutableList<Generated.SearchPractitionersBySpecialty>, Nimblesite.Sql.Model.SqlError @@ -104,13 +125,25 @@ System.Collections.Immutable.ImmutableList<Generated.SearchPractitionersBySpecialty>, Nimblesite.Sql.Model.SqlError >; -global using StringSyncError = Outcome.Result<string, Nimblesite.Sync.Core.SyncError>.Error<string, Nimblesite.Sync.Core.SyncError>; -global using StringSyncOk = Outcome.Result<string, Nimblesite.Sync.Core.SyncError>.Ok<string, Nimblesite.Sync.Core.SyncError>; +global using StringSyncError = Outcome.Result<string, Nimblesite.Sync.Core.SyncError>.Error< + string, + Nimblesite.Sync.Core.SyncError +>; +global using StringSyncOk = Outcome.Result<string, Nimblesite.Sync.Core.SyncError>.Ok< + string, + Nimblesite.Sync.Core.SyncError +>; global using SyncLogListError = Outcome.Result< System.Collections.Generic.IReadOnlyList<Nimblesite.Sync.Core.SyncLogEntry>, Nimblesite.Sync.Core.SyncError ->.Error<System.Collections.Generic.IReadOnlyList<Nimblesite.Sync.Core.SyncLogEntry>, Nimblesite.Sync.Core.SyncError>; +>.Error< + System.Collections.Generic.IReadOnlyList<Nimblesite.Sync.Core.SyncLogEntry>, + Nimblesite.Sync.Core.SyncError +>; global using SyncLogListOk = Outcome.Result< System.Collections.Generic.IReadOnlyList<Nimblesite.Sync.Core.SyncLogEntry>, Nimblesite.Sync.Core.SyncError ->.Ok<System.Collections.Generic.IReadOnlyList<Nimblesite.Sync.Core.SyncLogEntry>, Nimblesite.Sync.Core.SyncError>; +>.Ok< + System.Collections.Generic.IReadOnlyList<Nimblesite.Sync.Core.SyncLogEntry>, + Nimblesite.Sync.Core.SyncError +>; diff --git a/coverlet.runsettings b/coverlet.runsettings index a740cec..289d2e2 100644 --- a/coverlet.runsettings +++ b/coverlet.runsettings @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" ?> -<!-- agent-pmo:d58c330 --> +<!-- agent-pmo:29b9dcf --> <RunSettings> <DataCollectionRunSettings> <DataCollectors> diff --git a/opencode.json b/opencode.json index e35e90a..c881b86 100644 --- a/opencode.json +++ b/opencode.json @@ -1,5 +1,5 @@ { - "_agent_pmo": "d58c330", + "_agent_pmo": "29b9dcf", "$schema": "https://opencode.ai/config.json", "instructions": ["CLAUDE.md"] } From cf817ba0856fdd1fbb6a072b83028e6a92873d99 Mon Sep 17 00:00:00 2001 From: Christian Findlay <16697547+MelbourneDeveloper@users.noreply.github.com> Date: Tue, 7 Apr 2026 17:09:21 +1000 Subject: [PATCH 05/59] fixes --- .config/dotnet-tools.json | 7 +++++++ CLAUDE.md | 4 ++-- Dashboard/Dashboard.Web/.config/dotnet-tools.json | 13 ------------- 3 files changed, 9 insertions(+), 15 deletions(-) delete mode 100644 Dashboard/Dashboard.Web/.config/dotnet-tools.json diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index d7021f4..f5967de 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -29,6 +29,13 @@ "dataprovider-sqlite" ], "rollForward": false + }, + "h5-compiler": { + "version": "26.3.64893", + "commands": [ + "h5" + ], + "rollForward": false } } } \ No newline at end of file diff --git a/CLAUDE.md b/CLAUDE.md index 8939651..b8213a3 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -44,7 +44,7 @@ If the TMC server is available: ## Logging Standards -- **Use a structured logging library.** Never use `Console.WriteLine` or `Debug.WriteLine` for diagnostics. Use `Microsoft.Extensions.Logging` with Serilog. +- **Use a structured logging library.** Never use `Console.WriteLine` or `Debug.WriteLine` for diagnostics. Use `Microsoft.Extensions.Logging`. - **Log at entry/exit of all significant operations.** Use appropriate levels: `error`, `warn`, `info`, `debug`, `trace`. - **Logging must be throughout the app.** Every service, handler, and non-trivial operation should log. Silent failures are forbidden. - **SaaS / server apps:** Log to the database for persistence and queryability. Log calls that write to the database or file MUST be async or run on a background thread -- never block the request path with I/O logging. @@ -56,7 +56,7 @@ If the TMC server is available: | Language | Library | Notes | |----------|---------|-------| -| C# | `Microsoft.Extensions.Logging` | With Serilog for structured output | +| C# | `Microsoft.Extensions.Logging` | | ## Hard Rules -- C# diff --git a/Dashboard/Dashboard.Web/.config/dotnet-tools.json b/Dashboard/Dashboard.Web/.config/dotnet-tools.json deleted file mode 100644 index c93ea06..0000000 --- a/Dashboard/Dashboard.Web/.config/dotnet-tools.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "version": 1, - "isRoot": true, - "tools": { - "h5-compiler": { - "version": "26.3.64893", - "commands": [ - "h5" - ], - "rollForward": false - } - } -} \ No newline at end of file From f947ce126b8382f4982eadf0277e7a4b58fafd2e Mon Sep 17 00:00:00 2001 From: Christian Findlay <16697547+MelbourneDeveloper@users.noreply.github.com> Date: Tue, 7 Apr 2026 19:11:09 +1000 Subject: [PATCH 06/59] stuff --- .github/workflows/ci.yml | 41 +++++- .gitignore | 1 + .../Dashboard.Integration.Tests.csproj | 1 + .../Dashboard.Integration.Tests/E2EFixture.cs | 131 ++++-------------- HealthcareSamples.sln | 15 ++ ICD10/ICD10.Api.Tests/ICD10.Api.Tests.csproj | 1 + ICD10/ICD10.Api.Tests/ICD10ApiFactory.cs | 1 + .../ICD10.TestSupport.csproj | 12 ++ ICD10/ICD10.TestSupport/Icd10TestDatabase.cs | 45 ++++++ .../TestDataSeeder.cs | 38 ++++- Makefile | 2 +- coverlet.runsettings | 2 +- 12 files changed, 180 insertions(+), 110 deletions(-) create mode 100644 ICD10/ICD10.TestSupport/ICD10.TestSupport.csproj create mode 100644 ICD10/ICD10.TestSupport/Icd10TestDatabase.cs rename ICD10/{ICD10.Api.Tests => ICD10.TestSupport}/TestDataSeeder.cs (95%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ca1a027..30c4bb6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,7 +15,23 @@ jobs: ci: name: CI runs-on: ubuntu-latest - timeout-minutes: 10 + timeout-minutes: 30 + services: + postgres: + image: pgvector/pgvector:pg16 + env: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: changeme + ports: + - 5432:5432 + options: >- + --health-cmd "pg_isready -U postgres" + --health-interval 5s + --health-timeout 3s + --health-retries 10 + env: + TEST_POSTGRES_CONNECTION: Host=localhost;Database=postgres;Username=postgres;Password=changeme + ICD10_TEST_CONNECTION_STRING: Host=localhost;Database=postgres;Username=postgres;Password=changeme steps: - uses: actions/checkout@v4 @@ -23,9 +39,32 @@ jobs: with: dotnet-version: '10.0.x' + - name: Start embedding service + run: | + cd ICD10/embedding-service + docker compose up -d --build + # Wait until /health responds 200 (model load can take ~60s) + for i in $(seq 1 60); do + if curl -sf http://localhost:8000/health > /dev/null; then + echo "Embedding service ready" + exit 0 + fi + sleep 2 + done + echo "Embedding service failed to become healthy" + docker compose logs + exit 1 + - run: dotnet restore - run: dotnet tool restore + - name: Install Playwright browsers + run: | + dotnet build Dashboard/Dashboard.Integration.Tests/Dashboard.Integration.Tests.csproj --configuration Release + dotnet tool install --global Microsoft.Playwright.CLI || true + export PATH="$PATH:$HOME/.dotnet/tools" + playwright install --with-deps chromium + - name: Lint run: make lint diff --git a/.gitignore b/.gitignore index 68b9e6a..cf4417e 100644 --- a/.gitignore +++ b/.gitignore @@ -79,6 +79,7 @@ artifacts/ project.lock.json *.nupkg *.snupkg +!nupkgs/*.nupkg **/packages/* !**/packages/build/ !**/packages/repositories.config diff --git a/Dashboard/Dashboard.Integration.Tests/Dashboard.Integration.Tests.csproj b/Dashboard/Dashboard.Integration.Tests/Dashboard.Integration.Tests.csproj index 24ee7f4..21ecd4b 100644 --- a/Dashboard/Dashboard.Integration.Tests/Dashboard.Integration.Tests.csproj +++ b/Dashboard/Dashboard.Integration.Tests/Dashboard.Integration.Tests.csproj @@ -29,6 +29,7 @@ <ProjectReference Include="../../Scheduling/Scheduling.Api/Scheduling.Api.csproj" /> <ProjectReference Include="../../Scheduling/Scheduling.Sync/Scheduling.Sync.csproj" /> <ProjectReference Include="../../Gatekeeper/Gatekeeper.Api/Gatekeeper.Api.csproj" /> + <ProjectReference Include="../../ICD10/ICD10.TestSupport/ICD10.TestSupport.csproj" /> </ItemGroup> <!-- Copy Dashboard.Web wwwroot for Playwright tests --> diff --git a/Dashboard/Dashboard.Integration.Tests/E2EFixture.cs b/Dashboard/Dashboard.Integration.Tests/E2EFixture.cs index 6159e98..4ffd00e 100644 --- a/Dashboard/Dashboard.Integration.Tests/E2EFixture.cs +++ b/Dashboard/Dashboard.Integration.Tests/E2EFixture.cs @@ -3,6 +3,7 @@ using System.Security.Cryptography; using System.Text; using System.Text.Json; +using ICD10.TestSupport; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting.Server; @@ -141,14 +142,28 @@ await Task.WhenAll( var samplesDir = Path.GetFullPath( Path.Combine(testAssemblyDir, "..", "..", "..", "..", "..") ); - var rootDir = Path.GetFullPath(Path.Combine(samplesDir, "..")); - // Run ICD-10 migration and import official CDC data - await SetupIcd10DatabaseAsync(icd10ConnStr, samplesDir, rootDir); + // Run ICD-10 migration and import official CDC data. + // ICD-10 is optional in the E2E suite (see ICD-10 API skip block below) - if + // setup fails (e.g. embedding service or Python toolchain unavailable), continue + // without it instead of failing the entire fixture. + var icd10Ready = false; + try + { + await SetupIcd10DatabaseAsync(icd10ConnStr, samplesDir); + icd10Ready = true; + } + catch (Exception ex) + { + Console.WriteLine( + $"[E2E] WARNING: ICD-10 database setup failed ({ex.Message}); " + + "ICD-10 dependent tests will be skipped" + ); + } var clinicalProjectDir = Path.Combine(samplesDir, "Clinical", "Clinical.Api"); var schedulingProjectDir = Path.Combine(samplesDir, "Scheduling", "Scheduling.Api"); - var gatekeeperProjectDir = Path.Combine(rootDir, "Gatekeeper", "Gatekeeper.Api"); + var gatekeeperProjectDir = Path.Combine(samplesDir, "Gatekeeper", "Gatekeeper.Api"); var icd10ProjectDir = Path.Combine(samplesDir, "ICD10", "ICD10.Api"); var configuration = ResolveBuildConfiguration(testAssemblyDir); @@ -226,12 +241,12 @@ await Task.WhenAll( ["ConnectionStrings__Postgres"] = icd10ConnStr, ["ConnectionStrings__DefaultConnection"] = icd10ConnStr, }; - if (File.Exists(icd10Dll)) + if (icd10Ready && File.Exists(icd10Dll)) { _icd10Process = StartApiFromDll(icd10Dll, icd10ProjectDir, Icd10Url, icd10Env); Console.WriteLine($"[E2E] ICD-10 API starting on {Icd10Url}"); } - else + else if (!File.Exists(icd10Dll)) { Console.WriteLine($"[E2E] ICD-10 API DLL missing: {icd10Dll}"); } @@ -1040,117 +1055,27 @@ private static async Task SeedAsync(HttpClient client, string url, string json) /// Sets up the ICD-10 database by running migration and importing official CDC data. /// Skips import if data already exists in the database. /// </summary> - private static async Task SetupIcd10DatabaseAsync( - string connectionString, - string samplesDir, - string rootDir - ) + private static async Task SetupIcd10DatabaseAsync(string connectionString, string samplesDir) { Console.WriteLine("[E2E] Setting up ICD-10 database..."); var icd10ProjectDir = Path.Combine(samplesDir, "ICD10", "ICD10.Api"); var schemaPath = Path.Combine(icd10ProjectDir, "icd10-schema.yaml"); - var migrationCliDir = Path.Combine(rootDir, "Migration", "Migration.Cli"); - var scriptsDir = Path.Combine(samplesDir, "ICD10", "scripts", "CreateDb"); // Check if schema already exists and has data if (await Icd10DatabaseHasDataAsync(connectionString)) { Console.WriteLine( - "[E2E] ICD-10 database already has data - skipping migration and import" + "[E2E] ICD-10 database already has data - skipping migration and seed" ); return; } - // Step 1: Run migration to create schema - Console.WriteLine("[E2E] Running ICD-10 schema migration..."); - var configuration = ResolveBuildConfiguration( - Path.GetDirectoryName(typeof(E2EFixture).Assembly.Location)! - ); - var migrationDll = Path.Combine( - migrationCliDir, - "bin", - configuration, - "net10.0", - "Migration.Cli.dll" - ); - - int migrationResult; - if (File.Exists(migrationDll)) - { - Console.WriteLine($"[E2E] Using pre-built Migration.Cli: {migrationDll}"); - migrationResult = await RunProcessAsync( - "dotnet", - $"exec \"{migrationDll}\" --schema \"{schemaPath}\" --output \"{connectionString}\" --provider postgres", - rootDir, - timeoutMs: 600_000 - ); - } - else - { - Console.WriteLine( - $"[E2E] Migration.Cli DLL not found at {migrationDll}, falling back to dotnet run" - ); - migrationResult = await RunProcessAsync( - "dotnet", - $"run --project \"{migrationCliDir}\" -- --schema \"{schemaPath}\" --output \"{connectionString}\" --provider postgres", - rootDir, - timeoutMs: 600_000 - ); - } - - if (migrationResult != 0) - { - throw new Exception($"ICD-10 migration failed with exit code {migrationResult}"); - } - - Console.WriteLine("[E2E] ICD-10 schema created successfully"); - - // Step 2: Set up Python virtual environment - var venvDir = Path.Combine(samplesDir, "ICD10", ".venv"); - var pythonScript = Path.Combine(scriptsDir, "import_postgres.py"); - - if (!File.Exists(pythonScript)) - { - throw new FileNotFoundException($"ICD-10 import script not found: {pythonScript}"); - } - - Console.WriteLine("[E2E] Setting up Python environment..."); - if (!Directory.Exists(venvDir)) - { - var venvResult = await RunProcessAsync("python3", $"-m venv \"{venvDir}\"", scriptsDir); - if (venvResult != 0) - { - throw new Exception($"Failed to create Python virtual environment"); - } - } - - // Install requirements - var requirementsPath = Path.Combine(scriptsDir, "requirements.txt"); - var pipResult = await RunProcessAsync( - $"{venvDir}/bin/pip", - $"install -r \"{requirementsPath}\"", - scriptsDir - ); - if (pipResult != 0) - { - throw new Exception($"Failed to install Python dependencies"); - } - - // Step 3: Import official CDC ICD-10 data - Console.WriteLine("[E2E] Importing official CDC ICD-10 data..."); - var importResult = await RunProcessAsync( - $"{venvDir}/bin/python", - $"\"{pythonScript}\" --connection-string \"{connectionString}\"", - scriptsDir, - timeoutMs: 600_000 - ); - - if (importResult != 0) - { - throw new Exception($"ICD-10 data import failed with exit code {importResult}"); - } - + // Apply schema and seed deterministic E2E reference data via the shared + // ICD10.TestSupport library. This avoids the ~3-minute Python CDC import + // (44k codes + embeddings) that previously made every dashboard run hang. + Console.WriteLine("[E2E] Applying ICD-10 schema and seeding test data..."); + await Task.Run(() => Icd10TestDatabase.Initialize(connectionString, schemaPath)); Console.WriteLine("[E2E] ICD-10 database setup complete"); } diff --git a/HealthcareSamples.sln b/HealthcareSamples.sln index c18567c..33c90da 100644 --- a/HealthcareSamples.sln +++ b/HealthcareSamples.sln @@ -45,6 +45,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Gatekeeper.Api", "Gatekeepe EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Gatekeeper.Api.Tests", "Gatekeeper\Gatekeeper.Api.Tests\Gatekeeper.Api.Tests.csproj", "{0FC88CC8-1203-4215-AEFC-6CFA0A8DB358}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICD10.TestSupport", "ICD10\ICD10.TestSupport\ICD10.TestSupport.csproj", "{817E658D-F40C-43E5-8D25-92FE882D1760}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -235,6 +237,18 @@ Global {0FC88CC8-1203-4215-AEFC-6CFA0A8DB358}.Release|x64.Build.0 = Release|Any CPU {0FC88CC8-1203-4215-AEFC-6CFA0A8DB358}.Release|x86.ActiveCfg = Release|Any CPU {0FC88CC8-1203-4215-AEFC-6CFA0A8DB358}.Release|x86.Build.0 = Release|Any CPU + {817E658D-F40C-43E5-8D25-92FE882D1760}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {817E658D-F40C-43E5-8D25-92FE882D1760}.Debug|Any CPU.Build.0 = Debug|Any CPU + {817E658D-F40C-43E5-8D25-92FE882D1760}.Debug|x64.ActiveCfg = Debug|Any CPU + {817E658D-F40C-43E5-8D25-92FE882D1760}.Debug|x64.Build.0 = Debug|Any CPU + {817E658D-F40C-43E5-8D25-92FE882D1760}.Debug|x86.ActiveCfg = Debug|Any CPU + {817E658D-F40C-43E5-8D25-92FE882D1760}.Debug|x86.Build.0 = Debug|Any CPU + {817E658D-F40C-43E5-8D25-92FE882D1760}.Release|Any CPU.ActiveCfg = Release|Any CPU + {817E658D-F40C-43E5-8D25-92FE882D1760}.Release|Any CPU.Build.0 = Release|Any CPU + {817E658D-F40C-43E5-8D25-92FE882D1760}.Release|x64.ActiveCfg = Release|Any CPU + {817E658D-F40C-43E5-8D25-92FE882D1760}.Release|x64.Build.0 = Release|Any CPU + {817E658D-F40C-43E5-8D25-92FE882D1760}.Release|x86.ActiveCfg = Release|Any CPU + {817E658D-F40C-43E5-8D25-92FE882D1760}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -255,5 +269,6 @@ Global {CA395494-F072-4A5B-9DD4-950530A69E0E} = {A1B2C3D4-0001-0001-0001-000000000005} {3A6684C8-1A85-4BF7-8B5C-E07F4E123F12} = {048F5F03-6DDC-C04F-70D5-B8139DC8E373} {0FC88CC8-1203-4215-AEFC-6CFA0A8DB358} = {048F5F03-6DDC-C04F-70D5-B8139DC8E373} + {817E658D-F40C-43E5-8D25-92FE882D1760} = {A1B2C3D4-0001-0001-0001-000000000003} EndGlobalSection EndGlobal diff --git a/ICD10/ICD10.Api.Tests/ICD10.Api.Tests.csproj b/ICD10/ICD10.Api.Tests/ICD10.Api.Tests.csproj index fcb64e0..e680c03 100644 --- a/ICD10/ICD10.Api.Tests/ICD10.Api.Tests.csproj +++ b/ICD10/ICD10.Api.Tests/ICD10.Api.Tests.csproj @@ -23,6 +23,7 @@ <ItemGroup> <ProjectReference Include="..\ICD10.Api\ICD10.Api.csproj" /> + <ProjectReference Include="..\ICD10.TestSupport\ICD10.TestSupport.csproj" /> <ProjectReference Include="..\..\Shared\Authorization\Authorization.csproj" /> </ItemGroup> </Project> diff --git a/ICD10/ICD10.Api.Tests/ICD10ApiFactory.cs b/ICD10/ICD10.Api.Tests/ICD10ApiFactory.cs index 39682f8..5537cbd 100644 --- a/ICD10/ICD10.Api.Tests/ICD10ApiFactory.cs +++ b/ICD10/ICD10.Api.Tests/ICD10ApiFactory.cs @@ -1,3 +1,4 @@ +using ICD10.TestSupport; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc.Testing; using Nimblesite.DataProvider.Migration.Core; diff --git a/ICD10/ICD10.TestSupport/ICD10.TestSupport.csproj b/ICD10/ICD10.TestSupport/ICD10.TestSupport.csproj new file mode 100644 index 0000000..904f5f6 --- /dev/null +++ b/ICD10/ICD10.TestSupport/ICD10.TestSupport.csproj @@ -0,0 +1,12 @@ +<Project Sdk="Microsoft.NET.Sdk"> + <PropertyGroup> + <RootNamespace>ICD10.TestSupport</RootNamespace> + <NoWarn>CA1707;CA1062;CA1515;CA2100;CA1812;CA1849</NoWarn> + </PropertyGroup> + + <ItemGroup> + <PackageReference Include="Npgsql" Version="9.0.2" /> + <PackageReference Include="Nimblesite.DataProvider.Migration.Core" Version="0.2.0-beta" /> + <PackageReference Include="Nimblesite.DataProvider.Migration.Postgres" Version="0.2.0-beta" /> + </ItemGroup> +</Project> diff --git a/ICD10/ICD10.TestSupport/Icd10TestDatabase.cs b/ICD10/ICD10.TestSupport/Icd10TestDatabase.cs new file mode 100644 index 0000000..f0497e3 --- /dev/null +++ b/ICD10/ICD10.TestSupport/Icd10TestDatabase.cs @@ -0,0 +1,45 @@ +using Nimblesite.DataProvider.Migration.Core; +using Nimblesite.DataProvider.Migration.Postgres; +using Npgsql; + +namespace ICD10.TestSupport; + +/// <summary> +/// Helpers to provision an ICD-10 test database (schema + seed data) without +/// running the heavyweight Python CDC import (~3 minutes for 44k embeddings). +/// </summary> +public static class Icd10TestDatabase +{ + /// <summary> + /// Enables pgvector, applies the icd10-schema.yaml schema via the Migration + /// library, then seeds reference data and (if the embedding service at + /// http://localhost:8000 is available) embeddings. + /// </summary> + /// <param name="connectionString">Connection string to a fresh database.</param> + /// <param name="schemaYamlPath">Absolute path to icd10-schema.yaml.</param> + public static void Initialize(string connectionString, string schemaYamlPath) + { + if (!File.Exists(schemaYamlPath)) + { + throw new FileNotFoundException( + $"icd10-schema.yaml not found at '{schemaYamlPath}'", + schemaYamlPath + ); + } + + using var conn = new NpgsqlConnection(connectionString); + conn.Open(); + + using (var cmd = conn.CreateCommand()) + { + cmd.CommandText = "CREATE EXTENSION IF NOT EXISTS vector"; + cmd.ExecuteNonQuery(); + } + + var schema = SchemaYamlSerializer.FromYamlFile(schemaYamlPath); + PostgresDdlGenerator.MigrateSchema(conn, schema); + + TestDataSeeder.Seed(conn); + TestDataSeeder.SeedEmbeddings(conn); + } +} diff --git a/ICD10/ICD10.Api.Tests/TestDataSeeder.cs b/ICD10/ICD10.TestSupport/TestDataSeeder.cs similarity index 95% rename from ICD10/ICD10.Api.Tests/TestDataSeeder.cs rename to ICD10/ICD10.TestSupport/TestDataSeeder.cs index 35949a7..7535027 100644 --- a/ICD10/ICD10.Api.Tests/TestDataSeeder.cs +++ b/ICD10/ICD10.TestSupport/TestDataSeeder.cs @@ -1,14 +1,20 @@ +using System.Net.Http.Json; +using System.Text.Json; using Npgsql; -namespace ICD10.Api.Tests; +namespace ICD10.TestSupport; /// <summary> /// Seeds ICD-10 reference data into a PostgreSQL test database. /// All column names are lowercase to match PostgresDdlGenerator output. /// </summary> -internal static class TestDataSeeder +public static class TestDataSeeder { - internal static void Seed(NpgsqlConnection conn) + /// <summary> + /// Seeds chapters, blocks, categories, codes, ACHI blocks and ACHI codes + /// required by both API and Dashboard E2E tests. + /// </summary> + public static void Seed(NpgsqlConnection conn) { SeedChapters(conn); SeedBlocks(conn); @@ -22,7 +28,7 @@ internal static void Seed(NpgsqlConnection conn) /// Seeds embeddings by calling the embedding service at localhost:8000. /// If the service is unavailable, silently returns (search tests will fail via skip check). /// </summary> - internal static void SeedEmbeddings(NpgsqlConnection conn) + public static void SeedEmbeddings(NpgsqlConnection conn) { var icdItems = new (string EmbId, string CodeId, string Text)[] { @@ -455,6 +461,30 @@ string Synonyms "Type 2 diabetes mellitus without complications", "adult-onset diabetes; non-insulin-dependent diabetes" ), + ( + "code-e11-0", + "cat-e11", + "E11.0", + "Type 2 diabetes mellitus with hyperosmolarity", + "Type 2 diabetes mellitus with hyperosmolarity", + "" + ), + ( + "code-e11-21", + "cat-e11", + "E11.21", + "Type 2 diabetes mellitus with diabetic nephropathy", + "Type 2 diabetes mellitus with diabetic nephropathy", + "type 2 diabetes with kidney complications" + ), + ( + "code-e11-65", + "cat-e11", + "E11.65", + "Type 2 diabetes mellitus with hyperglycemia", + "Type 2 diabetes mellitus with hyperglycemia", + "" + ), ( "code-g43-909", "cat-g43", diff --git a/Makefile b/Makefile index a705740..568753e 100644 --- a/Makefile +++ b/Makefile @@ -87,7 +87,7 @@ coverage-check: @echo "==> Checking coverage thresholds..." @COBERTURA=$$(find TestResults -name 'coverage.cobertura.xml' | head -1); \ if [ -z "$$COBERTURA" ]; then echo "FAIL: No coverage.cobertura.xml found"; exit 1; fi; \ - LINE_RATE=$$(grep -oP 'line-rate="\K[^"]+' "$$COBERTURA" | head -1); \ + LINE_RATE=$$(awk 'match($$0, /line-rate="[0-9.]+"/) { s=substr($$0, RSTART+11, RLENGTH-12); print s; exit }' "$$COBERTURA"); \ PCT=$$(awk "BEGIN{printf \"%.1f\", $${LINE_RATE:-0}*100}"); \ PCT_INT=$$(awk "BEGIN{printf \"%d\", $${LINE_RATE:-0}*100}"); \ echo "Line coverage: $${PCT}% (threshold: $(COVERAGE_THRESHOLD)%)"; \ diff --git a/coverlet.runsettings b/coverlet.runsettings index 289d2e2..e4a0779 100644 --- a/coverlet.runsettings +++ b/coverlet.runsettings @@ -5,7 +5,7 @@ <DataCollectors> <DataCollector friendlyName="XPlat Code Coverage"> <Configuration> - <Format>json,lcov,opencover,cobertura</Format> + <Format>json,cobertura</Format> <Exclude>[*]*.Generated*,[*]*.g.*</Exclude> <ExcludeByFile>**/obj/**/*,**/bin/**/*,**/Migrations/**/*</ExcludeByFile> <ExcludeByAttribute> From 6fff4f35dd65433948b6cf78148afe6dbcbcb281 Mon Sep 17 00:00:00 2001 From: Christian Findlay <16697547+MelbourneDeveloper@users.noreply.github.com> Date: Wed, 8 Apr 2026 06:30:30 +1000 Subject: [PATCH 07/59] add spec --- docs/specs/gatekeeper-spec.md | 910 ++++++++++++++++++++++++++++++++++ 1 file changed, 910 insertions(+) create mode 100644 docs/specs/gatekeeper-spec.md diff --git a/docs/specs/gatekeeper-spec.md b/docs/specs/gatekeeper-spec.md new file mode 100644 index 0000000..fd3301a --- /dev/null +++ b/docs/specs/gatekeeper-spec.md @@ -0,0 +1,910 @@ +# Gatekeeper: Authentication & Authorization Microservice + +## Overview + +Gatekeeper is an independent, deployable authentication and authorization microservice implementing: +- **Passkey-only authentication** (WebAuthn/FIDO2) - no passwords +- **Fine-grained RBAC** with record-level permissions +- **Allows C# attributes to specify permissions or roles at code level** - distinc from .NET ABAC + +This service is framework-agnostic and can be integrated with any system via REST API. + +--- + +## Authoritative References + +### WebAuthn/FIDO2 Standards +- [W3C WebAuthn Specification](https://www.w3.org/TR/webauthn-3/) +- [FIDO Alliance Technical Specifications](https://fidoalliance.org/specs/fido-v2.0-id-20180227/fido-client-to-authenticator-protocol-v2.0-id-20180227.html) +- [WebAuthn Guide (webauthn.guide)](https://webauthn.guide/) + +### ASP.NET Core Implementation +- [ASP.NET Core Passkeys Documentation](https://learn.microsoft.com/en-us/aspnet/core/security/authentication/passkeys/?view=aspnetcore-10.0) +- [fido2-net-lib GitHub](https://github.com/passwordless-lib/fido2-net-lib) - Recommended library for .NET 9 +- [Syncfusion FIDO2 Tutorial](https://www.syncfusion.com/blogs/post/passkey-in-asp-dotnet-core-with-fido2) +- [damienbod/AspNetCoreIdentityFido2Mfa](https://github.com/damienbod/AspNetCoreIdentityFido2Mfa) - .NET 9 reference implementation + +### React Implementation +- [SimpleWebAuthn Documentation](https://simplewebauthn.dev/docs/packages/browser/) +- [SimpleWebAuthn Server Package](https://simplewebauthn.dev/docs/packages/server) +- [Complete React + WebAuthn Guide](https://medium.com/@siddhantahire98/building-a-modern-authentication-system-with-webauthn-passkeys-a-complete-guide-65cac3511049) + +### Access Control Design +- [NocoBase RBAC Design Guide](https://www.nocobase.com/en/blog/how-to-design-rbac-role-based-access-control-system) +- [Oso RBAC Layer Guide](https://www.osohq.com/learn/rbac-role-based-access-control) +- [SQLFlash Fine-Grained RBAC](https://sqlflash.ai/article/20250617-2/) +- [Hoop.dev Fine-Grained Access Control](https://hoop.dev/blog/fine-grained-access-control-and-rbac-building-secure-and-scalable-permission-systems/) +- [Permify Fine-Grained Access](https://permify.co/post/fine-grained-access-control-where-rbac-falls-short/) + +--- + +## Architecture + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ Client Application │ +│ (React Dashboard, etc.) │ +│ │ +│ ┌─────────────────┐ ┌─────────────────┐ │ +│ │ @simplewebauthn │ │ API Client │ │ +│ │ /browser │ │ (fetch/axios) │ │ +│ └────────┬────────┘ └────────┬────────┘ │ +└───────────┼──────────────────────┼──────────────────────────────┘ + │ │ + ▼ ▼ +┌─────────────────────────────────────────────────────────────────┐ +│ Gatekeeper API (:5002) │ +│ │ +│ ┌─────────────────────────────────────────────────────────┐ │ +│ │ Authentication Layer │ │ +│ │ POST /auth/register/begin - Start passkey creation │ │ +│ │ POST /auth/register/complete - Finish registration │ │ +│ │ POST /auth/login/begin - Start authentication │ │ +│ │ POST /auth/login/complete - Finish authentication │ │ +│ │ POST /auth/logout - Invalidate session │ │ +│ │ GET /auth/session - Get current session │ │ +│ └─────────────────────────────────────────────────────────┘ │ +│ │ +│ ┌─────────────────────────────────────────────────────────┐ │ +│ │ Authorization Layer │ │ +│ │ GET /authz/check - Check permission │ │ +│ │ GET /authz/permissions - List user permissions │ │ +│ │ POST /authz/evaluate - Bulk permission check │ │ +│ └─────────────────────────────────────────────────────────┘ │ +│ │ +│ ┌─────────────────────────────────────────────────────────┐ │ +│ │ Admin API (protected) │ │ +│ │ /admin/users - User management │ │ +│ │ /admin/roles - Role management │ │ +│ │ /admin/permissions - Permission management │ │ +│ │ /admin/policies - ABAC policy management │ │ +│ └─────────────────────────────────────────────────────────┘ │ +│ │ +│ ┌─────────────────────────────────────────────────────────┐ │ +│ │ fido2-net-lib (Fido2.AspNet) │ │ +│ │ Attestation & Assertion verification │ │ +│ └─────────────────────────────────────────────────────────┘ │ +└────────────────────────────┬────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────┐ +│ Database │ +│ │ +│ Users ──┬── Credentials (passkeys) │ +│ ├── UserRoles ── Roles ── RolePermissions │ +│ └── UserPermissions (direct grants) │ +│ │ │ +│ ▼ │ +│ Permissions ── ResourceType + Action + Scope │ +│ │ +│ Policies (ABAC) ── Conditions + Attributes │ +└─────────────────────────────────────────────────────────────────┘ +``` + +--- + +## Database Schema + +```mermaid +erDiagram + %% ═══════════════════════════════════════════════════════════════ + %% CORE AUTHENTICATION + %% ═══════════════════════════════════════════════════════════════ + + gk_user { + text id PK "UUID" + text display_name "NOT NULL" + text email UK "Unique index" + text created_at "NOT NULL, ISO8601" + text last_login_at "ISO8601" + boolean is_active "NOT NULL, default 1" + json metadata "Extensibility" + } + + gk_credential { + text id PK "Base64URL credential ID" + text user_id FK "NOT NULL" + blob public_key "NOT NULL, COSE format" + int sign_count "NOT NULL, default 0" + text aaguid "Authenticator AAGUID" + text credential_type "NOT NULL, 'public-key'" + json transports "['internal','usb','ble','nfc']" + text attestation_format + text created_at "NOT NULL" + text last_used_at + text device_name "User-friendly name" + boolean is_backup_eligible "BE flag" + boolean is_backed_up "BS flag" + } + + gk_session { + text id PK "JWT JTI" + text user_id FK "NOT NULL" + text credential_id FK + text created_at "NOT NULL" + text expires_at "NOT NULL" + text last_activity_at "NOT NULL" + text ip_address + text user_agent + boolean is_revoked "NOT NULL, default 0" + } + + gk_challenge { + text id PK "UUID" + text user_id "NULL for login" + blob challenge "NOT NULL, crypto random" + text type "NOT NULL, registration|authentication" + text created_at "NOT NULL" + text expires_at "NOT NULL, 5 min" + } + + %% ═══════════════════════════════════════════════════════════════ + %% RBAC + %% ═══════════════════════════════════════════════════════════════ + + gk_role { + text id PK + text name UK "NOT NULL, unique" + text description + boolean is_system "NOT NULL, default 0" + text created_at "NOT NULL" + text parent_role_id FK "Role hierarchy" + } + + gk_user_role { + text user_id PK,FK "Composite PK" + text role_id PK,FK "Composite PK" + text granted_at "NOT NULL" + text granted_by FK + text expires_at "Temporal grants" + } + + gk_permission { + text id PK + text code UK "NOT NULL, e.g. patient:read" + text resource_type "NOT NULL" + text action "NOT NULL, read|write|delete" + text description + text created_at "NOT NULL" + } + + gk_role_permission { + text role_id PK,FK "Composite PK" + text permission_id PK,FK "Composite PK" + text granted_at "NOT NULL" + } + + gk_user_permission { + text user_id FK "NOT NULL" + text permission_id FK "NOT NULL" + text scope_type "all|record|query" + text scope_value "Record ID or LQL query" + text granted_at "NOT NULL" + text granted_by FK + text expires_at + text reason "Audit trail" + } + + %% ═══════════════════════════════════════════════════════════════ + %% FINE-GRAINED ACCESS CONTROL + %% ═══════════════════════════════════════════════════════════════ + + gk_resource_grant { + text id PK + text user_id FK "NOT NULL" + text resource_type "NOT NULL, e.g. patient" + text resource_id "NOT NULL, e.g. patient-uuid" + text permission_id FK "NOT NULL" + text granted_at "NOT NULL" + text granted_by FK + text expires_at + } + + gk_policy { + text id PK + text name UK "NOT NULL" + text description + text resource_type "NOT NULL" + text action "NOT NULL" + json condition "NOT NULL, JSON expression" + text effect "NOT NULL, allow|deny" + int priority "NOT NULL, default 0" + boolean is_active "NOT NULL, default 1" + text created_at "NOT NULL" + } + + %% ═══════════════════════════════════════════════════════════════ + %% RELATIONSHIPS + %% ═══════════════════════════════════════════════════════════════ + + gk_user ||--o{ gk_credential : "has passkeys" + gk_user ||--o{ gk_session : "has sessions" + gk_credential ||--o{ gk_session : "authenticates" + + gk_user ||--o{ gk_user_role : "assigned to" + gk_role ||--o{ gk_user_role : "has members" + gk_user ||--o{ gk_user_role : "grants (granted_by)" + + gk_role ||--o| gk_role : "inherits from (parent)" + + gk_role ||--o{ gk_role_permission : "has" + gk_permission ||--o{ gk_role_permission : "granted to" + + gk_user ||--o{ gk_user_permission : "has direct" + gk_permission ||--o{ gk_user_permission : "granted directly" + gk_user ||--o{ gk_user_permission : "grants (granted_by)" + + gk_user ||--o{ gk_resource_grant : "has access to" + gk_permission ||--o{ gk_resource_grant : "defines access" + gk_user ||--o{ gk_resource_grant : "grants (granted_by)" +``` + +**Policy Condition Examples** (stored as JSON): +```json +{ "user.department": "finance", "resource.status": "draft" } +{ "time.hour": { "$gte": 9, "$lte": 17 } } +{ "user.id": { "$eq": "resource.owner_id" } } +``` + +--- + +## API Specification + +### Authentication Endpoints + +#### POST /auth/register/begin +Start passkey registration for a new or existing user. + +**Request:** +```json +{ + "email": "user@example.com", + "displayName": "John Doe" +} +``` + +**Response:** +```json +{ + "challengeId": "uuid", + "options": { + "challenge": "base64url-encoded-challenge", + "rp": { + "name": "Gatekeeper", + "id": "localhost" + }, + "user": { + "id": "base64url-user-id", + "name": "user@example.com", + "displayName": "John Doe" + }, + "pubKeyCredParams": [ + { "type": "public-key", "alg": -7 }, + { "type": "public-key", "alg": -257 } + ], + "timeout": 60000, + "attestation": "none", + "authenticatorSelection": { + "authenticatorAttachment": "platform", + "residentKey": "required", + "userVerification": "required" + } + } +} +``` + +#### POST /auth/register/complete +Complete passkey registration with authenticator response. + +**Request:** +```json +{ + "challengeId": "uuid", + "response": { + "id": "credential-id", + "rawId": "base64url", + "type": "public-key", + "response": { + "clientDataJSON": "base64url", + "attestationObject": "base64url" + } + }, + "deviceName": "MacBook Pro Touch ID" +} +``` + +**Response:** +```json +{ + "userId": "user-uuid", + "credentialId": "credential-id", + "session": { + "token": "session-token", + "expiresAt": "2025-12-22T00:00:00Z" + } +} +``` + +#### POST /auth/login/begin +Start passkey authentication. + +**Request:** +```json +{ + "email": "user@example.com" // Optional - for discoverable credentials +} +``` + +**Response:** +```json +{ + "challengeId": "uuid", + "options": { + "challenge": "base64url-encoded-challenge", + "timeout": 60000, + "rpId": "localhost", + "allowCredentials": [], // Empty for discoverable credentials + "userVerification": "required" + } +} +``` + +#### POST /auth/login/complete +Complete passkey authentication. + +**Request:** +```json +{ + "challengeId": "uuid", + "response": { + "id": "credential-id", + "rawId": "base64url", + "type": "public-key", + "response": { + "clientDataJSON": "base64url", + "authenticatorData": "base64url", + "signature": "base64url", + "userHandle": "base64url" + } + } +} +``` + +**Response:** +```json +{ + "userId": "user-uuid", + "displayName": "John Doe", + "session": { + "token": "session-token", + "expiresAt": "2025-12-22T00:00:00Z" + } +} +``` + +#### GET /auth/session +Get current session info. + +**Headers:** `Authorization: Bearer <session-token>` + +**Response:** +```json +{ + "userId": "user-uuid", + "displayName": "John Doe", + "email": "user@example.com", + "roles": ["admin", "clinician"], + "expiresAt": "2025-12-22T00:00:00Z" +} +``` + +#### POST /auth/logout +Invalidate current session. + +**Headers:** `Authorization: Bearer <session-token>` + +**Response:** `204 No Content` + +--- + +### Authorization Endpoints + +#### GET /authz/check +Check if current user has a specific permission. + +**Headers:** `Authorization: Bearer <session-token>` + +**Query Parameters:** +- `permission` - Permission code (e.g., `patient:read`) +- `resourceType` - Optional resource type +- `resourceId` - Optional specific resource ID + +**Response:** +```json +{ + "allowed": true, + "reason": "role:admin grants patient:read", + "evaluatedPolicies": ["default-admin-policy"] +} +``` + +#### POST /authz/evaluate +Bulk permission evaluation. + +**Request:** +```json +{ + "checks": [ + { "permission": "patient:read", "resourceId": "patient-123" }, + { "permission": "patient:write", "resourceId": "patient-123" }, + { "permission": "order:delete", "resourceId": "order-456" } + ] +} +``` + +**Response:** +```json +{ + "results": [ + { "permission": "patient:read", "resourceId": "patient-123", "allowed": true }, + { "permission": "patient:write", "resourceId": "patient-123", "allowed": true }, + { "permission": "order:delete", "resourceId": "order-456", "allowed": false } + ] +} +``` + +#### GET /authz/permissions +List all effective permissions for current user. + +**Response:** +```json +{ + "permissions": [ + { + "code": "patient:read", + "source": "role:clinician", + "scope": "all" + }, + { + "code": "patient:write", + "source": "direct-grant", + "scope": "record", + "scopeValue": "patient-123" + } + ] +} +``` + +--- + +### Admin Endpoints + +All admin endpoints require the `admin:*` permission. + +#### Users +- `GET /admin/users` - List users +- `GET /admin/users/{id}` - Get user details +- `POST /admin/users` - Create user (generates registration link) +- `PUT /admin/users/{id}` - Update user +- `DELETE /admin/users/{id}` - Deactivate user +- `GET /admin/users/{id}/credentials` - List user's passkeys +- `DELETE /admin/users/{id}/credentials/{credentialId}` - Revoke passkey + +#### Roles +- `GET /admin/roles` - List roles +- `GET /admin/roles/{id}` - Get role with permissions +- `POST /admin/roles` - Create role +- `PUT /admin/roles/{id}` - Update role +- `DELETE /admin/roles/{id}` - Delete role (if not system role) +- `POST /admin/roles/{id}/permissions` - Add permission to role +- `DELETE /admin/roles/{id}/permissions/{permissionId}` - Remove permission + +#### Permissions +- `GET /admin/permissions` - List permissions +- `POST /admin/permissions` - Create permission +- `DELETE /admin/permissions/{id}` - Delete permission + +#### User Grants +- `POST /admin/users/{id}/roles` - Assign role to user +- `DELETE /admin/users/{id}/roles/{roleId}` - Remove role +- `POST /admin/users/{id}/permissions` - Direct permission grant +- `DELETE /admin/users/{id}/permissions/{permissionId}` - Revoke grant +- `POST /admin/users/{id}/resources` - Grant resource-level access +- `DELETE /admin/users/{id}/resources/{grantId}` - Revoke resource access + +--- + +## Project Structure + +``` +Samples/ +└── Gatekeeper/ + ├── spec.md # This file + ├── Gatekeeper.Api/ + │ ├── Gatekeeper.Api.csproj + │ ├── Program.cs # Minimal API setup + │ ├── GlobalUsings.cs + │ ├── Endpoints/ + │ │ ├── AuthEndpoints.cs # /auth/* routes + │ │ ├── AuthzEndpoints.cs # /authz/* routes + │ │ └── AdminEndpoints.cs # /admin/* routes + │ ├── Services/ + │ │ ├── PasskeyService.cs # fido2-net-lib wrapper + │ │ ├── SessionService.cs # Session management + │ │ ├── AuthorizationService.cs # Permission evaluation + │ │ └── PolicyEvaluator.cs # ABAC policy engine + │ ├── Middleware/ + │ │ └── AuthMiddleware.cs # Session validation + │ ├── Sql/ + │ │ ├── GetUserByEmail.sql + │ │ ├── GetUserCredentials.sql + │ │ ├── InsertCredential.sql + │ │ ├── GetUserPermissions.sql + │ │ ├── CheckResourceGrant.sql + │ │ └── ... (DataProvider SQL files) + │ └── gatekeeper.db + │ + ├── Gatekeeper.Api.Tests/ + │ ├── Gatekeeper.Api.Tests.csproj + │ ├── AuthenticationTests.cs + │ ├── AuthorizationTests.cs + │ └── PermissionTests.cs + │ + └── Gatekeeper.Migration/ + ├── Gatekeeper.Migration.csproj + └── Schema.cs # Migration SchemaBuilder +``` + +--- + +## Implementation Guide + +### Dependencies (NuGet) + +```xml +<!-- Gatekeeper.Api.csproj --> +<PackageReference Include="Fido2" Version="4.*" /> +<PackageReference Include="Fido2.AspNet" Version="4.*" /> +<PackageReference Include="Microsoft.Data.Sqlite" Version="9.*" /> +``` + +### FIDO2 Configuration + +```csharp +// Program.cs +builder.Services.AddFido2(options => +{ + options.ServerDomain = builder.Configuration["Fido2:ServerDomain"] ?? "localhost"; + options.ServerName = "Gatekeeper"; + options.Origins = new HashSet<string> + { + builder.Configuration["Fido2:Origin"] ?? "http://localhost:5173" + }; + options.TimestampDriftTolerance = 300000; // 5 minutes +}); +``` + +### React Integration + +```typescript +// Using @simplewebauthn/browser +import { + startRegistration, + startAuthentication +} from '@simplewebauthn/browser'; + +// Registration +async function registerPasskey() { + const beginResp = await fetch('/auth/register/begin', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ email, displayName }) + }); + const { challengeId, options } = await beginResp.json(); + + // Trigger browser passkey creation + const credential = await startRegistration(options); + + const completeResp = await fetch('/auth/register/complete', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ challengeId, response: credential }) + }); + + return completeResp.json(); +} + +// Authentication +async function loginWithPasskey() { + const beginResp = await fetch('/auth/login/begin', { method: 'POST' }); + const { challengeId, options } = await beginResp.json(); + + const assertion = await startAuthentication(options); + + const completeResp = await fetch('/auth/login/complete', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ challengeId, response: assertion }) + }); + + return completeResp.json(); +} +``` + +--- + +## Permission Model Examples + +### High-Level Permissions (Menu Access) +``` +menu:dashboard:access - Can see dashboard +menu:patients:access - Can see patients menu +menu:admin:access - Can see admin menu +``` + +### Resource Permissions (CRUD) +``` +patient:create - Can create patients +patient:read - Can read any patient +patient:write - Can update any patient +patient:delete - Can delete any patient + +order:create +order:read +order:write +order:delete +``` + +### Record-Level Permissions +Granted via `POST /admin/users/{id}/resources`: +```json +// User can only read order 123456 +{ + "resourceType": "order", + "resourceId": "123456", + "permissionCode": "order:read" +} + +// User can write to order 54345 +{ + "resourceType": "order", + "resourceId": "54345", + "permissionCode": "order:write" +} +``` + +### ABAC Policy Examples +```json +// Policy: Users can only edit resources they own +{ + "name": "owner-edit-policy", + "resource_type": "*", + "action": "write", + "condition": { + "user.id": { "$eq": "resource.owner_id" } + }, + "effect": "allow" +} + +// Policy: Finance users can only access finance resources during business hours +{ + "name": "finance-time-restriction", + "resource_type": "finance_report", + "action": "*", + "condition": { + "$and": [ + { "user.department": "finance" }, + { "context.hour": { "$gte": 9, "$lte": 17 } }, + { "context.day_of_week": { "$in": [1, 2, 3, 4, 5] } } + ] + }, + "effect": "allow" +} + +// Policy: Deny access to archived records except for admins +{ + "name": "archived-restriction", + "resource_type": "*", + "action": "*", + "condition": { + "$and": [ + { "resource.status": "archived" }, + { "user.roles": { "$nin": ["admin"] } } + ] + }, + "effect": "deny", + "priority": 100 +} +``` + +--- + +## Authorization Decision Flow + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ Authorization Request │ +│ User: user-123, Permission: order:write, Resource: order-456 │ +└────────────────────────────┬────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────┐ +│ Step 1: Check explicit DENY policies (highest priority first) │ +│ → If any DENY matches → DENY │ +└────────────────────────────┬────────────────────────────────────┘ + │ No DENY + ▼ +┌─────────────────────────────────────────────────────────────────┐ +│ Step 2: Check resource-level grants (gk_resource_grant) │ +│ → SELECT * FROM gk_resource_grant │ +│ WHERE user_id = ? AND resource_type = ? │ +│ AND resource_id = ? AND permission_id = ? │ +│ → If found and not expired → ALLOW │ +└────────────────────────────┬────────────────────────────────────┘ + │ Not found + ▼ +┌─────────────────────────────────────────────────────────────────┐ +│ Step 3: Check direct user permissions (gk_user_permission) │ +│ → If scope='all' → ALLOW │ +│ → If scope='record' and scope_value matches → ALLOW │ +└────────────────────────────┬────────────────────────────────────┘ + │ Not found + ▼ +┌─────────────────────────────────────────────────────────────────┐ +│ Step 4: Check role permissions (gk_role_permission via roles) │ +│ → Traverse role hierarchy │ +│ → If permission found in any role → ALLOW │ +└────────────────────────────┬────────────────────────────────────┘ + │ Not found + ▼ +┌─────────────────────────────────────────────────────────────────┐ +│ Step 5: Evaluate ABAC ALLOW policies │ +│ → If any ALLOW policy matches → ALLOW │ +└────────────────────────────┬────────────────────────────────────┘ + │ No match + ▼ +┌─────────────────────────────────────────────────────────────────┐ +│ Default: DENY │ +└─────────────────────────────────────────────────────────────────┘ +``` + +--- + +## Security Considerations + +1. **No Password Storage** - Only public keys stored; private keys never leave user devices +2. **Challenge Expiry** - All challenges expire after 5 minutes +3. **Session Rotation** - Sessions can be invalidated server-side +4. **Sign Count Verification** - Detect cloned authenticators +5. **User Verification Required** - Biometric/PIN required for all operations +6. **Audit Logging** - All authentication and authorization events logged + +--- + +## Integration with Other Services + +Other microservices integrate via middleware: + +```csharp +// In Clinical.Api or Scheduling.Api +app.Use(async (context, next) => +{ + var token = context.Request.Headers["Authorization"] + .ToString() + .Replace("Bearer ", ""); + + if (string.IsNullOrEmpty(token)) + { + context.Response.StatusCode = 401; + return; + } + + // Validate with Gatekeeper + using var client = new HttpClient(); + var response = await client.GetAsync( + $"http://localhost:5002/auth/session", + new HttpRequestMessage { Headers = { Authorization = new("Bearer", token) } } + ); + + if (!response.IsSuccessStatusCode) + { + context.Response.StatusCode = 401; + return; + } + + var session = await response.Content.ReadFromJsonAsync<SessionInfo>(); + context.Items["User"] = session; + + await next(); +}); +``` + +Or via shared library: +```csharp +// Gatekeeper.Client library +services.AddGatekeeperAuth(options => +{ + options.GatekeeperUrl = "http://localhost:5002"; +}); + +// Then in endpoints: +app.MapGet("/fhir/Patient", async (HttpContext ctx) => +{ + var authz = ctx.RequestServices.GetRequiredService<IGatekeeperClient>(); + if (!await authz.CheckAsync("patient:read")) + return Results.Forbid(); + + // ... handle request +}); +``` + +--- + +## Default Roles & Permissions + +Seeded via `Gatekeeper.Migration` on first run: + +| Role | Description | System? | +|------|-------------|---------| +| `admin` | Full system access | Yes | +| `user` | Basic authenticated user | Yes | + +| Permission Code | Resource | Action | Description | +|-----------------|----------|--------|-------------| +| `admin:*` | admin | * | Full admin access | +| `user:profile` | user | read | View own profile | +| `user:credentials` | user | manage | Manage own passkeys | + +| Role | Permissions | +|------|-------------| +| `admin` | `admin:*` | +| `user` | `user:profile`, `user:credentials` | + +--- + +## Sync Support + +Gatekeeper integrates with the existing Sync infrastructure for multi-node deployments. Sync triggers are enabled on permission tables via the `Sync.SQLite` schema extensions (uses existing `Sync.Http` infrastructure). + +--- + +## Open Questions + +1. **Token Format**: JWT vs opaque session tokens? + - Current spec uses opaque tokens for server-side revocation + - JWT could be added for stateless verification in edge cases + +2. **Cross-Origin Passkeys**: Support for passkeys across subdomains? + - Requires careful RP ID configuration + +3. **Recovery Flow**: What happens if user loses all devices? + - Admin-initiated account recovery? + - Backup codes? (against passkey-only philosophy) + +--- + +## Version History + +| Version | Date | Changes | +|---------|------|---------| +| 1.0.0 | 2025-12-21 | Initial specification | From 00100845e3691e391db206d4103811e34b1f55c1 Mon Sep 17 00:00:00 2001 From: Christian Findlay <16697547+MelbourneDeveloper@users.noreply.github.com> Date: Wed, 8 Apr 2026 06:36:01 +1000 Subject: [PATCH 08/59] Fixes --- .../Generated/CheckPermission.g.cs | 107 ------- .../Generated/CheckResourceGrant.g.cs | 151 --------- .../Generated/CountSystemRoles.g.cs | 70 ----- .../Generated/GetActivePolicies.g.cs | 127 -------- .../Generated/GetAllPermissions.g.cs | 102 ------- .../Gatekeeper.Api/Generated/GetAllRoles.g.cs | 102 ------- .../Gatekeeper.Api/Generated/GetAllUsers.g.cs | 102 ------- .../Generated/GetChallengeById.g.cs | 112 ------- .../Generated/GetCredentialById.g.cs | 164 ---------- .../Generated/GetCredentialsByUserId.g.cs | 151 --------- .../Generated/GetPermissionByCode.g.cs | 107 ------- .../Generated/GetRolePermissions.g.cs | 115 ------- .../Generated/GetSessionById.g.cs | 145 --------- .../Generated/GetSessionForRevoke.g.cs | 127 -------- .../Generated/GetSessionRevoked.g.cs | 76 ----- .../Generated/GetUserByEmail.g.cs | 113 ------- .../Gatekeeper.Api/Generated/GetUserById.g.cs | 113 ------- .../Generated/GetUserCredentials.g.cs | 150 --------- .../Generated/GetUserPermissions.g.cs | 152 ---------- .../Generated/GetUserRoles.g.cs | 114 ------- .../Generated/RevokeSession.g.cs | 82 ----- .../Generated/gk_challengeOperations.g.cs | 52 ---- .../Generated/gk_credentialOperations.g.cs | 59 ---- .../Generated/gk_permissionOperations.g.cs | 52 ---- .../gk_resource_grantOperations.g.cs | 54 ---- .../Generated/gk_roleOperations.g.cs | 52 ---- .../gk_role_permissionOperations.g.cs | 49 --- .../Generated/gk_sessionOperations.g.cs | 90 ------ .../Generated/gk_userOperations.g.cs | 53 ---- .../Generated/gk_user_roleOperations.g.cs | 51 ---- ...te-generated-files-and-postgres-codegen.md | 286 ++++++++++++++++++ 31 files changed, 286 insertions(+), 2994 deletions(-) delete mode 100644 Gatekeeper/Gatekeeper.Api/Generated/CheckPermission.g.cs delete mode 100644 Gatekeeper/Gatekeeper.Api/Generated/CheckResourceGrant.g.cs delete mode 100644 Gatekeeper/Gatekeeper.Api/Generated/CountSystemRoles.g.cs delete mode 100644 Gatekeeper/Gatekeeper.Api/Generated/GetActivePolicies.g.cs delete mode 100644 Gatekeeper/Gatekeeper.Api/Generated/GetAllPermissions.g.cs delete mode 100644 Gatekeeper/Gatekeeper.Api/Generated/GetAllRoles.g.cs delete mode 100644 Gatekeeper/Gatekeeper.Api/Generated/GetAllUsers.g.cs delete mode 100644 Gatekeeper/Gatekeeper.Api/Generated/GetChallengeById.g.cs delete mode 100644 Gatekeeper/Gatekeeper.Api/Generated/GetCredentialById.g.cs delete mode 100644 Gatekeeper/Gatekeeper.Api/Generated/GetCredentialsByUserId.g.cs delete mode 100644 Gatekeeper/Gatekeeper.Api/Generated/GetPermissionByCode.g.cs delete mode 100644 Gatekeeper/Gatekeeper.Api/Generated/GetRolePermissions.g.cs delete mode 100644 Gatekeeper/Gatekeeper.Api/Generated/GetSessionById.g.cs delete mode 100644 Gatekeeper/Gatekeeper.Api/Generated/GetSessionForRevoke.g.cs delete mode 100644 Gatekeeper/Gatekeeper.Api/Generated/GetSessionRevoked.g.cs delete mode 100644 Gatekeeper/Gatekeeper.Api/Generated/GetUserByEmail.g.cs delete mode 100644 Gatekeeper/Gatekeeper.Api/Generated/GetUserById.g.cs delete mode 100644 Gatekeeper/Gatekeeper.Api/Generated/GetUserCredentials.g.cs delete mode 100644 Gatekeeper/Gatekeeper.Api/Generated/GetUserPermissions.g.cs delete mode 100644 Gatekeeper/Gatekeeper.Api/Generated/GetUserRoles.g.cs delete mode 100644 Gatekeeper/Gatekeeper.Api/Generated/RevokeSession.g.cs delete mode 100644 Gatekeeper/Gatekeeper.Api/Generated/gk_challengeOperations.g.cs delete mode 100644 Gatekeeper/Gatekeeper.Api/Generated/gk_credentialOperations.g.cs delete mode 100644 Gatekeeper/Gatekeeper.Api/Generated/gk_permissionOperations.g.cs delete mode 100644 Gatekeeper/Gatekeeper.Api/Generated/gk_resource_grantOperations.g.cs delete mode 100644 Gatekeeper/Gatekeeper.Api/Generated/gk_roleOperations.g.cs delete mode 100644 Gatekeeper/Gatekeeper.Api/Generated/gk_role_permissionOperations.g.cs delete mode 100644 Gatekeeper/Gatekeeper.Api/Generated/gk_sessionOperations.g.cs delete mode 100644 Gatekeeper/Gatekeeper.Api/Generated/gk_userOperations.g.cs delete mode 100644 Gatekeeper/Gatekeeper.Api/Generated/gk_user_roleOperations.g.cs create mode 100644 docs/plans/delete-generated-files-and-postgres-codegen.md diff --git a/Gatekeeper/Gatekeeper.Api/Generated/CheckPermission.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/CheckPermission.g.cs deleted file mode 100644 index c0c280f..0000000 --- a/Gatekeeper/Gatekeeper.Api/Generated/CheckPermission.g.cs +++ /dev/null @@ -1,107 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Threading.Tasks; -using Npgsql; -using Outcome; -using Nimblesite.Sql.Model; - -namespace Generated; - -/// <summary> -/// Extension methods for 'CheckPermission'. -/// </summary> -public static partial class CheckPermissionExtensions -{ - /// <summary> - /// Executes 'CheckPermission.sql' and maps results. - /// </summary> - /// <param name="connection">Open NpgsqlConnection connection.</param> - /// <param name="permissionCode">Query parameter.</param> - /// <param name="userId">Query parameter.</param> - /// <param name="now">Query parameter.</param> - /// <returns>Result of records or SQL error.</returns> - public static async Task<Result<ImmutableList<CheckPermission>, SqlError>> CheckPermissionAsync(this NpgsqlConnection connection, object permissionCode, object userId, object now) - { - const string sql = @"-- name: CheckPermission --- Checks if user has a specific permission code (via roles or direct grant) -SELECT 1 AS has_permission -FROM gk_permission p -WHERE p.code = @permissionCode - AND ( - -- Check role permissions - EXISTS ( - SELECT 1 FROM gk_role_permission rp - JOIN gk_user_role ur ON rp.role_id = ur.role_id - WHERE rp.permission_id = p.id - AND ur.user_id = @userId - AND (ur.expires_at IS NULL OR ur.expires_at > @now) - ) - OR - -- Check direct permissions - EXISTS ( - SELECT 1 FROM gk_user_permission up - WHERE up.permission_id = p.id - AND up.user_id = @userId - AND (up.expires_at IS NULL OR up.expires_at > @now) - ) - ) -LIMIT 1; -"; - - try - { - var results = ImmutableList.CreateBuilder<CheckPermission>(); - - using (var command = new NpgsqlCommand(sql, connection)) - { - if (permissionCode is not null and not DBNull) - command.Parameters.AddWithValue("@permissionCode", permissionCode); - else - command.Parameters.Add(new NpgsqlParameter("@permissionCode", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); - if (userId is not null and not DBNull) - command.Parameters.AddWithValue("@userId", userId); - else - command.Parameters.Add(new NpgsqlParameter("@userId", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); - if (now is not null and not DBNull) - command.Parameters.AddWithValue("@now", now); - else - command.Parameters.Add(new NpgsqlParameter("@now", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); - - using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false)) - { - while (await reader.ReadAsync().ConfigureAwait(false)) - { - var item = new CheckPermission( - reader.IsDBNull(0) ? null : reader.GetFieldValue<byte[]>(0) - ); - results.Add(item); - } - } - } - - return new Result<ImmutableList<CheckPermission>, SqlError>.Ok<ImmutableList<CheckPermission>, SqlError>(results.ToImmutable()); - } - catch (Exception ex) - { - return new Result<ImmutableList<CheckPermission>, SqlError>.Error<ImmutableList<CheckPermission>, SqlError>(new SqlError("Database error", ex)); - } - } -} - -/// <summary> -/// Result row for 'CheckPermission' query. -/// </summary> -public record CheckPermission -{ - /// <summary>Column 'has_permission'.</summary> - public byte[] has_permission { get; init; } - - /// <summary>Initializes a new instance of CheckPermission.</summary> - public CheckPermission( - byte[] has_permission - ) - { - this.has_permission = has_permission; - } -} diff --git a/Gatekeeper/Gatekeeper.Api/Generated/CheckResourceGrant.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/CheckResourceGrant.g.cs deleted file mode 100644 index 89c26ee..0000000 --- a/Gatekeeper/Gatekeeper.Api/Generated/CheckResourceGrant.g.cs +++ /dev/null @@ -1,151 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Threading.Tasks; -using Npgsql; -using Outcome; -using Nimblesite.Sql.Model; - -namespace Generated; - -/// <summary> -/// Extension methods for 'CheckResourceGrant'. -/// </summary> -public static partial class CheckResourceGrantExtensions -{ - /// <summary> - /// Executes 'CheckResourceGrant.sql' and maps results. - /// </summary> - /// <param name="connection">Open NpgsqlConnection connection.</param> - /// <param name="user_id">Query parameter.</param> - /// <param name="resource_type">Query parameter.</param> - /// <param name="permission_code">Query parameter.</param> - /// <param name="now">Query parameter.</param> - /// <param name="resource_id">Query parameter.</param> - /// <returns>Result of records or SQL error.</returns> - public static async Task<Result<ImmutableList<CheckResourceGrant>, SqlError>> CheckResourceGrantAsync(this NpgsqlConnection connection, object user_id, object resource_type, object permission_code, object now, object resource_id) - { - const string sql = @"-- name: CheckResourceGrant -SELECT rg.id, rg.user_id, rg.resource_type, rg.resource_id, rg.permission_id, - rg.granted_at, rg.granted_by, rg.expires_at, p.code as permission_code -FROM gk_resource_grant rg -JOIN gk_permission p ON rg.permission_id = p.id -WHERE rg.user_id = @user_id - AND rg.resource_type = @resource_type - AND rg.resource_id = @resource_id - AND p.code = @permission_code - AND (rg.expires_at IS NULL OR rg.expires_at > @now); -"; - - try - { - var results = ImmutableList.CreateBuilder<CheckResourceGrant>(); - - using (var command = new NpgsqlCommand(sql, connection)) - { - if (user_id is not null and not DBNull) - command.Parameters.AddWithValue("@user_id", user_id); - else - command.Parameters.Add(new NpgsqlParameter("@user_id", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); - if (resource_type is not null and not DBNull) - command.Parameters.AddWithValue("@resource_type", resource_type); - else - command.Parameters.Add(new NpgsqlParameter("@resource_type", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); - if (permission_code is not null and not DBNull) - command.Parameters.AddWithValue("@permission_code", permission_code); - else - command.Parameters.Add(new NpgsqlParameter("@permission_code", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); - if (now is not null and not DBNull) - command.Parameters.AddWithValue("@now", now); - else - command.Parameters.Add(new NpgsqlParameter("@now", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); - if (resource_id is not null and not DBNull) - command.Parameters.AddWithValue("@resource_id", resource_id); - else - command.Parameters.Add(new NpgsqlParameter("@resource_id", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); - - using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false)) - { - while (await reader.ReadAsync().ConfigureAwait(false)) - { - var item = new CheckResourceGrant( - reader.IsDBNull(0) ? null : reader.GetFieldValue<string>(0), - reader.IsDBNull(1) ? null : reader.GetFieldValue<string>(1), - reader.IsDBNull(2) ? null : reader.GetFieldValue<string>(2), - reader.IsDBNull(3) ? null : reader.GetFieldValue<string>(3), - reader.IsDBNull(4) ? null : reader.GetFieldValue<string>(4), - reader.IsDBNull(5) ? null : reader.GetFieldValue<string>(5), - reader.IsDBNull(6) ? null : reader.GetFieldValue<string>(6), - reader.IsDBNull(7) ? null : reader.GetFieldValue<string>(7), - reader.IsDBNull(8) ? null : reader.GetFieldValue<string>(8) - ); - results.Add(item); - } - } - } - - return new Result<ImmutableList<CheckResourceGrant>, SqlError>.Ok<ImmutableList<CheckResourceGrant>, SqlError>(results.ToImmutable()); - } - catch (Exception ex) - { - return new Result<ImmutableList<CheckResourceGrant>, SqlError>.Error<ImmutableList<CheckResourceGrant>, SqlError>(new SqlError("Database error", ex)); - } - } -} - -/// <summary> -/// Result row for 'CheckResourceGrant' query. -/// </summary> -public record CheckResourceGrant -{ - /// <summary>Column 'id'.</summary> - public string id { get; init; } - - /// <summary>Column 'user_id'.</summary> - public string user_id { get; init; } - - /// <summary>Column 'resource_type'.</summary> - public string resource_type { get; init; } - - /// <summary>Column 'resource_id'.</summary> - public string resource_id { get; init; } - - /// <summary>Column 'permission_id'.</summary> - public string permission_id { get; init; } - - /// <summary>Column 'granted_at'.</summary> - public string granted_at { get; init; } - - /// <summary>Column 'granted_by'.</summary> - public string granted_by { get; init; } - - /// <summary>Column 'expires_at'.</summary> - public string expires_at { get; init; } - - /// <summary>Column 'permission_code'.</summary> - public string permission_code { get; init; } - - /// <summary>Initializes a new instance of CheckResourceGrant.</summary> - public CheckResourceGrant( - string id, - string user_id, - string resource_type, - string resource_id, - string permission_id, - string granted_at, - string granted_by, - string expires_at, - string permission_code - ) - { - this.id = id; - this.user_id = user_id; - this.resource_type = resource_type; - this.resource_id = resource_id; - this.permission_id = permission_id; - this.granted_at = granted_at; - this.granted_by = granted_by; - this.expires_at = expires_at; - this.permission_code = permission_code; - } -} diff --git a/Gatekeeper/Gatekeeper.Api/Generated/CountSystemRoles.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/CountSystemRoles.g.cs deleted file mode 100644 index d708ec5..0000000 --- a/Gatekeeper/Gatekeeper.Api/Generated/CountSystemRoles.g.cs +++ /dev/null @@ -1,70 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Threading.Tasks; -using Npgsql; -using Outcome; -using Nimblesite.Sql.Model; - -namespace Generated; - -/// <summary> -/// Extension methods for 'CountSystemRoles'. -/// </summary> -public static partial class CountSystemRolesExtensions -{ - /// <summary> - /// Executes 'CountSystemRoles.sql' and maps results. - /// </summary> - /// <param name="connection">Open NpgsqlConnection connection.</param> - /// <returns>Result of records or SQL error.</returns> - public static async Task<Result<ImmutableList<CountSystemRoles>, SqlError>> CountSystemRolesAsync(this NpgsqlConnection connection) - { - const string sql = @"-- name: CountSystemRoles -SELECT COUNT(*) as cnt FROM gk_role WHERE is_system = true; -"; - - try - { - var results = ImmutableList.CreateBuilder<CountSystemRoles>(); - - using (var command = new NpgsqlCommand(sql, connection)) - { - - using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false)) - { - while (await reader.ReadAsync().ConfigureAwait(false)) - { - var item = new CountSystemRoles( - reader.IsDBNull(0) ? default(long) : reader.GetFieldValue<long>(0) - ); - results.Add(item); - } - } - } - - return new Result<ImmutableList<CountSystemRoles>, SqlError>.Ok<ImmutableList<CountSystemRoles>, SqlError>(results.ToImmutable()); - } - catch (Exception ex) - { - return new Result<ImmutableList<CountSystemRoles>, SqlError>.Error<ImmutableList<CountSystemRoles>, SqlError>(new SqlError("Database error", ex)); - } - } -} - -/// <summary> -/// Result row for 'CountSystemRoles' query. -/// </summary> -public record CountSystemRoles -{ - /// <summary>Column 'cnt'.</summary> - public long cnt { get; init; } - - /// <summary>Initializes a new instance of CountSystemRoles.</summary> - public CountSystemRoles( - long cnt - ) - { - this.cnt = cnt; - } -} diff --git a/Gatekeeper/Gatekeeper.Api/Generated/GetActivePolicies.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/GetActivePolicies.g.cs deleted file mode 100644 index a2e3c29..0000000 --- a/Gatekeeper/Gatekeeper.Api/Generated/GetActivePolicies.g.cs +++ /dev/null @@ -1,127 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Threading.Tasks; -using Npgsql; -using Outcome; -using Nimblesite.Sql.Model; - -namespace Generated; - -/// <summary> -/// Extension methods for 'GetActivePolicies'. -/// </summary> -public static partial class GetActivePoliciesExtensions -{ - /// <summary> - /// Executes 'GetActivePolicies.sql' and maps results. - /// </summary> - /// <param name="connection">Open NpgsqlConnection connection.</param> - /// <param name="resource_type">Query parameter.</param> - /// <param name="action">Query parameter.</param> - /// <returns>Result of records or SQL error.</returns> - public static async Task<Result<ImmutableList<GetActivePolicies>, SqlError>> GetActivePoliciesAsync(this NpgsqlConnection connection, object resource_type, object action) - { - const string sql = @"-- name: GetActivePolicies -SELECT id, name, description, resource_type, action, condition, effect, priority -FROM gk_policy -WHERE is_active = true - AND (resource_type = @resource_type OR resource_type = '*') - AND (action = @action OR action = '*') -ORDER BY priority DESC; -"; - - try - { - var results = ImmutableList.CreateBuilder<GetActivePolicies>(); - - using (var command = new NpgsqlCommand(sql, connection)) - { - if (resource_type is not null and not DBNull) - command.Parameters.AddWithValue("@resource_type", resource_type); - else - command.Parameters.Add(new NpgsqlParameter("@resource_type", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); - if (action is not null and not DBNull) - command.Parameters.AddWithValue("@action", action); - else - command.Parameters.Add(new NpgsqlParameter("@action", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); - - using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false)) - { - while (await reader.ReadAsync().ConfigureAwait(false)) - { - var item = new GetActivePolicies( - reader.IsDBNull(0) ? null : reader.GetFieldValue<string>(0), - reader.IsDBNull(1) ? null : reader.GetFieldValue<string>(1), - reader.IsDBNull(2) ? null : reader.GetFieldValue<string>(2), - reader.IsDBNull(3) ? null : reader.GetFieldValue<string>(3), - reader.IsDBNull(4) ? null : reader.GetFieldValue<string>(4), - reader.IsDBNull(5) ? null : reader.GetFieldValue<string>(5), - reader.IsDBNull(6) ? null : reader.GetFieldValue<string>(6), - reader.IsDBNull(7) ? default(long) : reader.GetFieldValue<long>(7) - ); - results.Add(item); - } - } - } - - return new Result<ImmutableList<GetActivePolicies>, SqlError>.Ok<ImmutableList<GetActivePolicies>, SqlError>(results.ToImmutable()); - } - catch (Exception ex) - { - return new Result<ImmutableList<GetActivePolicies>, SqlError>.Error<ImmutableList<GetActivePolicies>, SqlError>(new SqlError("Database error", ex)); - } - } -} - -/// <summary> -/// Result row for 'GetActivePolicies' query. -/// </summary> -public record GetActivePolicies -{ - /// <summary>Column 'id'.</summary> - public string id { get; init; } - - /// <summary>Column 'name'.</summary> - public string name { get; init; } - - /// <summary>Column 'description'.</summary> - public string description { get; init; } - - /// <summary>Column 'resource_type'.</summary> - public string resource_type { get; init; } - - /// <summary>Column 'action'.</summary> - public string action { get; init; } - - /// <summary>Column 'condition'.</summary> - public string condition { get; init; } - - /// <summary>Column 'effect'.</summary> - public string effect { get; init; } - - /// <summary>Column 'priority'.</summary> - public long priority { get; init; } - - /// <summary>Initializes a new instance of GetActivePolicies.</summary> - public GetActivePolicies( - string id, - string name, - string description, - string resource_type, - string action, - string condition, - string effect, - long priority - ) - { - this.id = id; - this.name = name; - this.description = description; - this.resource_type = resource_type; - this.action = action; - this.condition = condition; - this.effect = effect; - this.priority = priority; - } -} diff --git a/Gatekeeper/Gatekeeper.Api/Generated/GetAllPermissions.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/GetAllPermissions.g.cs deleted file mode 100644 index 9feeca8..0000000 --- a/Gatekeeper/Gatekeeper.Api/Generated/GetAllPermissions.g.cs +++ /dev/null @@ -1,102 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Threading.Tasks; -using Npgsql; -using Outcome; -using Nimblesite.Sql.Model; - -namespace Generated; - -/// <summary> -/// Extension methods for 'GetAllPermissions'. -/// </summary> -public static partial class GetAllPermissionsExtensions -{ - /// <summary> - /// Executes 'GetAllPermissions.sql' and maps results. - /// </summary> - /// <param name="connection">Open NpgsqlConnection connection.</param> - /// <returns>Result of records or SQL error.</returns> - public static async Task<Result<ImmutableList<GetAllPermissions>, SqlError>> GetAllPermissionsAsync(this NpgsqlConnection connection) - { - const string sql = @"-- name: GetAllPermissions -SELECT id, code, resource_type, action, description, created_at -FROM gk_permission -ORDER BY resource_type, action; -"; - - try - { - var results = ImmutableList.CreateBuilder<GetAllPermissions>(); - - using (var command = new NpgsqlCommand(sql, connection)) - { - - using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false)) - { - while (await reader.ReadAsync().ConfigureAwait(false)) - { - var item = new GetAllPermissions( - reader.IsDBNull(0) ? null : reader.GetFieldValue<string>(0), - reader.IsDBNull(1) ? null : reader.GetFieldValue<string>(1), - reader.IsDBNull(2) ? null : reader.GetFieldValue<string>(2), - reader.IsDBNull(3) ? null : reader.GetFieldValue<string>(3), - reader.IsDBNull(4) ? null : reader.GetFieldValue<string>(4), - reader.IsDBNull(5) ? null : reader.GetFieldValue<string>(5) - ); - results.Add(item); - } - } - } - - return new Result<ImmutableList<GetAllPermissions>, SqlError>.Ok<ImmutableList<GetAllPermissions>, SqlError>(results.ToImmutable()); - } - catch (Exception ex) - { - return new Result<ImmutableList<GetAllPermissions>, SqlError>.Error<ImmutableList<GetAllPermissions>, SqlError>(new SqlError("Database error", ex)); - } - } -} - -/// <summary> -/// Result row for 'GetAllPermissions' query. -/// </summary> -public record GetAllPermissions -{ - /// <summary>Column 'id'.</summary> - public string id { get; init; } - - /// <summary>Column 'code'.</summary> - public string code { get; init; } - - /// <summary>Column 'resource_type'.</summary> - public string resource_type { get; init; } - - /// <summary>Column 'action'.</summary> - public string action { get; init; } - - /// <summary>Column 'description'.</summary> - public string description { get; init; } - - /// <summary>Column 'created_at'.</summary> - public string created_at { get; init; } - - /// <summary>Initializes a new instance of GetAllPermissions.</summary> - public GetAllPermissions( - string id, - string code, - string resource_type, - string action, - string description, - string created_at - ) - { - this.id = id; - this.code = code; - this.resource_type = resource_type; - this.action = action; - this.description = description; - this.created_at = created_at; - } -} diff --git a/Gatekeeper/Gatekeeper.Api/Generated/GetAllRoles.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/GetAllRoles.g.cs deleted file mode 100644 index e2c11fc..0000000 --- a/Gatekeeper/Gatekeeper.Api/Generated/GetAllRoles.g.cs +++ /dev/null @@ -1,102 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Threading.Tasks; -using Npgsql; -using Outcome; -using Nimblesite.Sql.Model; - -namespace Generated; - -/// <summary> -/// Extension methods for 'GetAllRoles'. -/// </summary> -public static partial class GetAllRolesExtensions -{ - /// <summary> - /// Executes 'GetAllRoles.sql' and maps results. - /// </summary> - /// <param name="connection">Open NpgsqlConnection connection.</param> - /// <returns>Result of records or SQL error.</returns> - public static async Task<Result<ImmutableList<GetAllRoles>, SqlError>> GetAllRolesAsync(this NpgsqlConnection connection) - { - const string sql = @"-- name: GetAllRoles -SELECT id, name, description, is_system, created_at, parent_role_id -FROM gk_role -ORDER BY name; -"; - - try - { - var results = ImmutableList.CreateBuilder<GetAllRoles>(); - - using (var command = new NpgsqlCommand(sql, connection)) - { - - using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false)) - { - while (await reader.ReadAsync().ConfigureAwait(false)) - { - var item = new GetAllRoles( - reader.IsDBNull(0) ? null : reader.GetFieldValue<string>(0), - reader.IsDBNull(1) ? null : reader.GetFieldValue<string>(1), - reader.IsDBNull(2) ? null : reader.GetFieldValue<string>(2), - reader.IsDBNull(3) ? null : reader.GetFieldValue<bool?>(3), - reader.IsDBNull(4) ? null : reader.GetFieldValue<string>(4), - reader.IsDBNull(5) ? null : reader.GetFieldValue<string>(5) - ); - results.Add(item); - } - } - } - - return new Result<ImmutableList<GetAllRoles>, SqlError>.Ok<ImmutableList<GetAllRoles>, SqlError>(results.ToImmutable()); - } - catch (Exception ex) - { - return new Result<ImmutableList<GetAllRoles>, SqlError>.Error<ImmutableList<GetAllRoles>, SqlError>(new SqlError("Database error", ex)); - } - } -} - -/// <summary> -/// Result row for 'GetAllRoles' query. -/// </summary> -public record GetAllRoles -{ - /// <summary>Column 'id'.</summary> - public string id { get; init; } - - /// <summary>Column 'name'.</summary> - public string name { get; init; } - - /// <summary>Column 'description'.</summary> - public string description { get; init; } - - /// <summary>Column 'is_system'.</summary> - public bool? is_system { get; init; } - - /// <summary>Column 'created_at'.</summary> - public string created_at { get; init; } - - /// <summary>Column 'parent_role_id'.</summary> - public string parent_role_id { get; init; } - - /// <summary>Initializes a new instance of GetAllRoles.</summary> - public GetAllRoles( - string id, - string name, - string description, - bool? is_system, - string created_at, - string parent_role_id - ) - { - this.id = id; - this.name = name; - this.description = description; - this.is_system = is_system; - this.created_at = created_at; - this.parent_role_id = parent_role_id; - } -} diff --git a/Gatekeeper/Gatekeeper.Api/Generated/GetAllUsers.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/GetAllUsers.g.cs deleted file mode 100644 index 7c80d5e..0000000 --- a/Gatekeeper/Gatekeeper.Api/Generated/GetAllUsers.g.cs +++ /dev/null @@ -1,102 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Threading.Tasks; -using Npgsql; -using Outcome; -using Nimblesite.Sql.Model; - -namespace Generated; - -/// <summary> -/// Extension methods for 'GetAllUsers'. -/// </summary> -public static partial class GetAllUsersExtensions -{ - /// <summary> - /// Executes 'GetAllUsers.sql' and maps results. - /// </summary> - /// <param name="connection">Open NpgsqlConnection connection.</param> - /// <returns>Result of records or SQL error.</returns> - public static async Task<Result<ImmutableList<GetAllUsers>, SqlError>> GetAllUsersAsync(this NpgsqlConnection connection) - { - const string sql = @"-- name: GetAllUsers -SELECT id, display_name, email, created_at, last_login_at, is_active -FROM gk_user -ORDER BY display_name; -"; - - try - { - var results = ImmutableList.CreateBuilder<GetAllUsers>(); - - using (var command = new NpgsqlCommand(sql, connection)) - { - - using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false)) - { - while (await reader.ReadAsync().ConfigureAwait(false)) - { - var item = new GetAllUsers( - reader.IsDBNull(0) ? null : reader.GetFieldValue<string>(0), - reader.IsDBNull(1) ? null : reader.GetFieldValue<string>(1), - reader.IsDBNull(2) ? null : reader.GetFieldValue<string>(2), - reader.IsDBNull(3) ? null : reader.GetFieldValue<string>(3), - reader.IsDBNull(4) ? null : reader.GetFieldValue<string>(4), - reader.IsDBNull(5) ? null : reader.GetFieldValue<bool?>(5) - ); - results.Add(item); - } - } - } - - return new Result<ImmutableList<GetAllUsers>, SqlError>.Ok<ImmutableList<GetAllUsers>, SqlError>(results.ToImmutable()); - } - catch (Exception ex) - { - return new Result<ImmutableList<GetAllUsers>, SqlError>.Error<ImmutableList<GetAllUsers>, SqlError>(new SqlError("Database error", ex)); - } - } -} - -/// <summary> -/// Result row for 'GetAllUsers' query. -/// </summary> -public record GetAllUsers -{ - /// <summary>Column 'id'.</summary> - public string id { get; init; } - - /// <summary>Column 'display_name'.</summary> - public string display_name { get; init; } - - /// <summary>Column 'email'.</summary> - public string email { get; init; } - - /// <summary>Column 'created_at'.</summary> - public string created_at { get; init; } - - /// <summary>Column 'last_login_at'.</summary> - public string last_login_at { get; init; } - - /// <summary>Column 'is_active'.</summary> - public bool? is_active { get; init; } - - /// <summary>Initializes a new instance of GetAllUsers.</summary> - public GetAllUsers( - string id, - string display_name, - string email, - string created_at, - string last_login_at, - bool? is_active - ) - { - this.id = id; - this.display_name = display_name; - this.email = email; - this.created_at = created_at; - this.last_login_at = last_login_at; - this.is_active = is_active; - } -} diff --git a/Gatekeeper/Gatekeeper.Api/Generated/GetChallengeById.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/GetChallengeById.g.cs deleted file mode 100644 index 2bb9f81..0000000 --- a/Gatekeeper/Gatekeeper.Api/Generated/GetChallengeById.g.cs +++ /dev/null @@ -1,112 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Threading.Tasks; -using Npgsql; -using Outcome; -using Nimblesite.Sql.Model; - -namespace Generated; - -/// <summary> -/// Extension methods for 'GetChallengeById'. -/// </summary> -public static partial class GetChallengeByIdExtensions -{ - /// <summary> - /// Executes 'GetChallengeById.sql' and maps results. - /// </summary> - /// <param name="connection">Open NpgsqlConnection connection.</param> - /// <param name="id">Query parameter.</param> - /// <param name="now">Query parameter.</param> - /// <returns>Result of records or SQL error.</returns> - public static async Task<Result<ImmutableList<GetChallengeById>, SqlError>> GetChallengeByIdAsync(this NpgsqlConnection connection, object id, object now) - { - const string sql = @"-- name: GetChallengeById -SELECT id, user_id, challenge, type, created_at, expires_at -FROM gk_challenge -WHERE id = @id AND expires_at > @now; -"; - - try - { - var results = ImmutableList.CreateBuilder<GetChallengeById>(); - - using (var command = new NpgsqlCommand(sql, connection)) - { - if (id is not null and not DBNull) - command.Parameters.AddWithValue("@id", id); - else - command.Parameters.Add(new NpgsqlParameter("@id", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); - if (now is not null and not DBNull) - command.Parameters.AddWithValue("@now", now); - else - command.Parameters.Add(new NpgsqlParameter("@now", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); - - using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false)) - { - while (await reader.ReadAsync().ConfigureAwait(false)) - { - var item = new GetChallengeById( - reader.IsDBNull(0) ? null : reader.GetFieldValue<string>(0), - reader.IsDBNull(1) ? null : reader.GetFieldValue<string>(1), - reader.IsDBNull(2) ? null : reader.GetFieldValue<byte[]>(2), - reader.IsDBNull(3) ? null : reader.GetFieldValue<string>(3), - reader.IsDBNull(4) ? null : reader.GetFieldValue<string>(4), - reader.IsDBNull(5) ? null : reader.GetFieldValue<string>(5) - ); - results.Add(item); - } - } - } - - return new Result<ImmutableList<GetChallengeById>, SqlError>.Ok<ImmutableList<GetChallengeById>, SqlError>(results.ToImmutable()); - } - catch (Exception ex) - { - return new Result<ImmutableList<GetChallengeById>, SqlError>.Error<ImmutableList<GetChallengeById>, SqlError>(new SqlError("Database error", ex)); - } - } -} - -/// <summary> -/// Result row for 'GetChallengeById' query. -/// </summary> -public record GetChallengeById -{ - /// <summary>Column 'id'.</summary> - public string id { get; init; } - - /// <summary>Column 'user_id'.</summary> - public string user_id { get; init; } - - /// <summary>Column 'challenge'.</summary> - public byte[] challenge { get; init; } - - /// <summary>Column 'type'.</summary> - public string type { get; init; } - - /// <summary>Column 'created_at'.</summary> - public string created_at { get; init; } - - /// <summary>Column 'expires_at'.</summary> - public string expires_at { get; init; } - - /// <summary>Initializes a new instance of GetChallengeById.</summary> - public GetChallengeById( - string id, - string user_id, - byte[] challenge, - string type, - string created_at, - string expires_at - ) - { - this.id = id; - this.user_id = user_id; - this.challenge = challenge; - this.type = type; - this.created_at = created_at; - this.expires_at = expires_at; - } -} diff --git a/Gatekeeper/Gatekeeper.Api/Generated/GetCredentialById.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/GetCredentialById.g.cs deleted file mode 100644 index a06805a..0000000 --- a/Gatekeeper/Gatekeeper.Api/Generated/GetCredentialById.g.cs +++ /dev/null @@ -1,164 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Threading.Tasks; -using Npgsql; -using Outcome; -using Nimblesite.Sql.Model; - -namespace Generated; - -/// <summary> -/// Extension methods for 'GetCredentialById'. -/// </summary> -public static partial class GetCredentialByIdExtensions -{ - /// <summary> - /// Executes 'GetCredentialById.sql' and maps results. - /// </summary> - /// <param name="connection">Open NpgsqlConnection connection.</param> - /// <param name="id">Query parameter.</param> - /// <returns>Result of records or SQL error.</returns> - public static async Task<Result<ImmutableList<GetCredentialById>, SqlError>> GetCredentialByIdAsync(this NpgsqlConnection connection, object id) - { - const string sql = @"-- name: GetCredentialById -SELECT c.id, c.user_id, c.public_key, c.sign_count, c.aaguid, c.credential_type, c.transports, - c.attestation_format, c.created_at, c.last_used_at, c.device_name, c.is_backup_eligible, c.is_backed_up, - u.display_name, u.email -FROM gk_credential c -JOIN gk_user u ON c.user_id = u.id -WHERE c.id = @id AND u.is_active = true; -"; - - try - { - var results = ImmutableList.CreateBuilder<GetCredentialById>(); - - using (var command = new NpgsqlCommand(sql, connection)) - { - if (id is not null and not DBNull) - command.Parameters.AddWithValue("@id", id); - else - command.Parameters.Add(new NpgsqlParameter("@id", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); - - using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false)) - { - while (await reader.ReadAsync().ConfigureAwait(false)) - { - var item = new GetCredentialById( - reader.IsDBNull(0) ? null : reader.GetFieldValue<string>(0), - reader.IsDBNull(1) ? null : reader.GetFieldValue<string>(1), - reader.IsDBNull(2) ? null : reader.GetFieldValue<byte[]>(2), - reader.IsDBNull(3) ? default(long) : reader.GetFieldValue<long>(3), - reader.IsDBNull(4) ? null : reader.GetFieldValue<string>(4), - reader.IsDBNull(5) ? null : reader.GetFieldValue<string>(5), - reader.IsDBNull(6) ? null : reader.GetFieldValue<string>(6), - reader.IsDBNull(7) ? null : reader.GetFieldValue<string>(7), - reader.IsDBNull(8) ? null : reader.GetFieldValue<string>(8), - reader.IsDBNull(9) ? null : reader.GetFieldValue<string>(9), - reader.IsDBNull(10) ? null : reader.GetFieldValue<string>(10), - reader.IsDBNull(11) ? null : reader.GetFieldValue<bool?>(11), - reader.IsDBNull(12) ? null : reader.GetFieldValue<bool?>(12), - reader.IsDBNull(13) ? null : reader.GetFieldValue<string>(13), - reader.IsDBNull(14) ? null : reader.GetFieldValue<string>(14) - ); - results.Add(item); - } - } - } - - return new Result<ImmutableList<GetCredentialById>, SqlError>.Ok<ImmutableList<GetCredentialById>, SqlError>(results.ToImmutable()); - } - catch (Exception ex) - { - return new Result<ImmutableList<GetCredentialById>, SqlError>.Error<ImmutableList<GetCredentialById>, SqlError>(new SqlError("Database error", ex)); - } - } -} - -/// <summary> -/// Result row for 'GetCredentialById' query. -/// </summary> -public record GetCredentialById -{ - /// <summary>Column 'id'.</summary> - public string id { get; init; } - - /// <summary>Column 'user_id'.</summary> - public string user_id { get; init; } - - /// <summary>Column 'public_key'.</summary> - public byte[] public_key { get; init; } - - /// <summary>Column 'sign_count'.</summary> - public long sign_count { get; init; } - - /// <summary>Column 'aaguid'.</summary> - public string aaguid { get; init; } - - /// <summary>Column 'credential_type'.</summary> - public string credential_type { get; init; } - - /// <summary>Column 'transports'.</summary> - public string transports { get; init; } - - /// <summary>Column 'attestation_format'.</summary> - public string attestation_format { get; init; } - - /// <summary>Column 'created_at'.</summary> - public string created_at { get; init; } - - /// <summary>Column 'last_used_at'.</summary> - public string last_used_at { get; init; } - - /// <summary>Column 'device_name'.</summary> - public string device_name { get; init; } - - /// <summary>Column 'is_backup_eligible'.</summary> - public bool? is_backup_eligible { get; init; } - - /// <summary>Column 'is_backed_up'.</summary> - public bool? is_backed_up { get; init; } - - /// <summary>Column 'display_name'.</summary> - public string display_name { get; init; } - - /// <summary>Column 'email'.</summary> - public string email { get; init; } - - /// <summary>Initializes a new instance of GetCredentialById.</summary> - public GetCredentialById( - string id, - string user_id, - byte[] public_key, - long sign_count, - string aaguid, - string credential_type, - string transports, - string attestation_format, - string created_at, - string last_used_at, - string device_name, - bool? is_backup_eligible, - bool? is_backed_up, - string display_name, - string email - ) - { - this.id = id; - this.user_id = user_id; - this.public_key = public_key; - this.sign_count = sign_count; - this.aaguid = aaguid; - this.credential_type = credential_type; - this.transports = transports; - this.attestation_format = attestation_format; - this.created_at = created_at; - this.last_used_at = last_used_at; - this.device_name = device_name; - this.is_backup_eligible = is_backup_eligible; - this.is_backed_up = is_backed_up; - this.display_name = display_name; - this.email = email; - } -} diff --git a/Gatekeeper/Gatekeeper.Api/Generated/GetCredentialsByUserId.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/GetCredentialsByUserId.g.cs deleted file mode 100644 index 84d5574..0000000 --- a/Gatekeeper/Gatekeeper.Api/Generated/GetCredentialsByUserId.g.cs +++ /dev/null @@ -1,151 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Threading.Tasks; -using Npgsql; -using Outcome; -using Nimblesite.Sql.Model; - -namespace Generated; - -/// <summary> -/// Extension methods for 'GetCredentialsByUserId'. -/// </summary> -public static partial class GetCredentialsByUserIdExtensions -{ - /// <summary> - /// Executes 'GetCredentialsByUserId.sql' and maps results. - /// </summary> - /// <param name="connection">Open NpgsqlConnection connection.</param> - /// <param name="userId">Query parameter.</param> - /// <returns>Result of records or SQL error.</returns> - public static async Task<Result<ImmutableList<GetCredentialsByUserId>, SqlError>> GetCredentialsByUserIdAsync(this NpgsqlConnection connection, object userId) - { - const string sql = @"-- name: GetCredentialsByUserId -SELECT id, user_id, public_key, sign_count, aaguid, credential_type, transports, - attestation_format, created_at, last_used_at, device_name, - is_backup_eligible, is_backed_up -FROM gk_credential -WHERE user_id = @userId; -"; - - try - { - var results = ImmutableList.CreateBuilder<GetCredentialsByUserId>(); - - using (var command = new NpgsqlCommand(sql, connection)) - { - if (userId is not null and not DBNull) - command.Parameters.AddWithValue("@userId", userId); - else - command.Parameters.Add(new NpgsqlParameter("@userId", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); - - using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false)) - { - while (await reader.ReadAsync().ConfigureAwait(false)) - { - var item = new GetCredentialsByUserId( - reader.IsDBNull(0) ? null : reader.GetFieldValue<string>(0), - reader.IsDBNull(1) ? null : reader.GetFieldValue<string>(1), - reader.IsDBNull(2) ? null : reader.GetFieldValue<byte[]>(2), - reader.IsDBNull(3) ? default(long) : reader.GetFieldValue<long>(3), - reader.IsDBNull(4) ? null : reader.GetFieldValue<string>(4), - reader.IsDBNull(5) ? null : reader.GetFieldValue<string>(5), - reader.IsDBNull(6) ? null : reader.GetFieldValue<string>(6), - reader.IsDBNull(7) ? null : reader.GetFieldValue<string>(7), - reader.IsDBNull(8) ? null : reader.GetFieldValue<string>(8), - reader.IsDBNull(9) ? null : reader.GetFieldValue<string>(9), - reader.IsDBNull(10) ? null : reader.GetFieldValue<string>(10), - reader.IsDBNull(11) ? null : reader.GetFieldValue<bool?>(11), - reader.IsDBNull(12) ? null : reader.GetFieldValue<bool?>(12) - ); - results.Add(item); - } - } - } - - return new Result<ImmutableList<GetCredentialsByUserId>, SqlError>.Ok<ImmutableList<GetCredentialsByUserId>, SqlError>(results.ToImmutable()); - } - catch (Exception ex) - { - return new Result<ImmutableList<GetCredentialsByUserId>, SqlError>.Error<ImmutableList<GetCredentialsByUserId>, SqlError>(new SqlError("Database error", ex)); - } - } -} - -/// <summary> -/// Result row for 'GetCredentialsByUserId' query. -/// </summary> -public record GetCredentialsByUserId -{ - /// <summary>Column 'id'.</summary> - public string id { get; init; } - - /// <summary>Column 'user_id'.</summary> - public string user_id { get; init; } - - /// <summary>Column 'public_key'.</summary> - public byte[] public_key { get; init; } - - /// <summary>Column 'sign_count'.</summary> - public long sign_count { get; init; } - - /// <summary>Column 'aaguid'.</summary> - public string aaguid { get; init; } - - /// <summary>Column 'credential_type'.</summary> - public string credential_type { get; init; } - - /// <summary>Column 'transports'.</summary> - public string transports { get; init; } - - /// <summary>Column 'attestation_format'.</summary> - public string attestation_format { get; init; } - - /// <summary>Column 'created_at'.</summary> - public string created_at { get; init; } - - /// <summary>Column 'last_used_at'.</summary> - public string last_used_at { get; init; } - - /// <summary>Column 'device_name'.</summary> - public string device_name { get; init; } - - /// <summary>Column 'is_backup_eligible'.</summary> - public bool? is_backup_eligible { get; init; } - - /// <summary>Column 'is_backed_up'.</summary> - public bool? is_backed_up { get; init; } - - /// <summary>Initializes a new instance of GetCredentialsByUserId.</summary> - public GetCredentialsByUserId( - string id, - string user_id, - byte[] public_key, - long sign_count, - string aaguid, - string credential_type, - string transports, - string attestation_format, - string created_at, - string last_used_at, - string device_name, - bool? is_backup_eligible, - bool? is_backed_up - ) - { - this.id = id; - this.user_id = user_id; - this.public_key = public_key; - this.sign_count = sign_count; - this.aaguid = aaguid; - this.credential_type = credential_type; - this.transports = transports; - this.attestation_format = attestation_format; - this.created_at = created_at; - this.last_used_at = last_used_at; - this.device_name = device_name; - this.is_backup_eligible = is_backup_eligible; - this.is_backed_up = is_backed_up; - } -} diff --git a/Gatekeeper/Gatekeeper.Api/Generated/GetPermissionByCode.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/GetPermissionByCode.g.cs deleted file mode 100644 index 0d82639..0000000 --- a/Gatekeeper/Gatekeeper.Api/Generated/GetPermissionByCode.g.cs +++ /dev/null @@ -1,107 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Threading.Tasks; -using Npgsql; -using Outcome; -using Nimblesite.Sql.Model; - -namespace Generated; - -/// <summary> -/// Extension methods for 'GetPermissionByCode'. -/// </summary> -public static partial class GetPermissionByCodeExtensions -{ - /// <summary> - /// Executes 'GetPermissionByCode.sql' and maps results. - /// </summary> - /// <param name="connection">Open NpgsqlConnection connection.</param> - /// <param name="code">Query parameter.</param> - /// <returns>Result of records or SQL error.</returns> - public static async Task<Result<ImmutableList<GetPermissionByCode>, SqlError>> GetPermissionByCodeAsync(this NpgsqlConnection connection, object code) - { - const string sql = @"-- name: GetPermissionByCode -SELECT id, code, resource_type, action, description, created_at -FROM gk_permission -WHERE code = @code; -"; - - try - { - var results = ImmutableList.CreateBuilder<GetPermissionByCode>(); - - using (var command = new NpgsqlCommand(sql, connection)) - { - if (code is not null and not DBNull) - command.Parameters.AddWithValue("@code", code); - else - command.Parameters.Add(new NpgsqlParameter("@code", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); - - using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false)) - { - while (await reader.ReadAsync().ConfigureAwait(false)) - { - var item = new GetPermissionByCode( - reader.IsDBNull(0) ? null : reader.GetFieldValue<string>(0), - reader.IsDBNull(1) ? null : reader.GetFieldValue<string>(1), - reader.IsDBNull(2) ? null : reader.GetFieldValue<string>(2), - reader.IsDBNull(3) ? null : reader.GetFieldValue<string>(3), - reader.IsDBNull(4) ? null : reader.GetFieldValue<string>(4), - reader.IsDBNull(5) ? null : reader.GetFieldValue<string>(5) - ); - results.Add(item); - } - } - } - - return new Result<ImmutableList<GetPermissionByCode>, SqlError>.Ok<ImmutableList<GetPermissionByCode>, SqlError>(results.ToImmutable()); - } - catch (Exception ex) - { - return new Result<ImmutableList<GetPermissionByCode>, SqlError>.Error<ImmutableList<GetPermissionByCode>, SqlError>(new SqlError("Database error", ex)); - } - } -} - -/// <summary> -/// Result row for 'GetPermissionByCode' query. -/// </summary> -public record GetPermissionByCode -{ - /// <summary>Column 'id'.</summary> - public string id { get; init; } - - /// <summary>Column 'code'.</summary> - public string code { get; init; } - - /// <summary>Column 'resource_type'.</summary> - public string resource_type { get; init; } - - /// <summary>Column 'action'.</summary> - public string action { get; init; } - - /// <summary>Column 'description'.</summary> - public string description { get; init; } - - /// <summary>Column 'created_at'.</summary> - public string created_at { get; init; } - - /// <summary>Initializes a new instance of GetPermissionByCode.</summary> - public GetPermissionByCode( - string id, - string code, - string resource_type, - string action, - string description, - string created_at - ) - { - this.id = id; - this.code = code; - this.resource_type = resource_type; - this.action = action; - this.description = description; - this.created_at = created_at; - } -} diff --git a/Gatekeeper/Gatekeeper.Api/Generated/GetRolePermissions.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/GetRolePermissions.g.cs deleted file mode 100644 index b61ca70..0000000 --- a/Gatekeeper/Gatekeeper.Api/Generated/GetRolePermissions.g.cs +++ /dev/null @@ -1,115 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Threading.Tasks; -using Npgsql; -using Outcome; -using Nimblesite.Sql.Model; - -namespace Generated; - -/// <summary> -/// Extension methods for 'GetRolePermissions'. -/// </summary> -public static partial class GetRolePermissionsExtensions -{ - /// <summary> - /// Executes 'GetRolePermissions.sql' and maps results. - /// </summary> - /// <param name="connection">Open NpgsqlConnection connection.</param> - /// <param name="roleId">Query parameter.</param> - /// <returns>Result of records or SQL error.</returns> - public static async Task<Result<ImmutableList<GetRolePermissions>, SqlError>> GetRolePermissionsAsync(this NpgsqlConnection connection, object roleId) - { - const string sql = @"-- name: GetRolePermissions -SELECT p.id, p.code, p.resource_type, p.action, p.description, p.created_at, - rp.granted_at -FROM gk_permission p -JOIN gk_role_permission rp ON p.id = rp.permission_id -WHERE rp.role_id = @roleId; -"; - - try - { - var results = ImmutableList.CreateBuilder<GetRolePermissions>(); - - using (var command = new NpgsqlCommand(sql, connection)) - { - if (roleId is not null and not DBNull) - command.Parameters.AddWithValue("@roleId", roleId); - else - command.Parameters.Add(new NpgsqlParameter("@roleId", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); - - using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false)) - { - while (await reader.ReadAsync().ConfigureAwait(false)) - { - var item = new GetRolePermissions( - reader.IsDBNull(0) ? null : reader.GetFieldValue<string>(0), - reader.IsDBNull(1) ? null : reader.GetFieldValue<string>(1), - reader.IsDBNull(2) ? null : reader.GetFieldValue<string>(2), - reader.IsDBNull(3) ? null : reader.GetFieldValue<string>(3), - reader.IsDBNull(4) ? null : reader.GetFieldValue<string>(4), - reader.IsDBNull(5) ? null : reader.GetFieldValue<string>(5), - reader.IsDBNull(6) ? null : reader.GetFieldValue<string>(6) - ); - results.Add(item); - } - } - } - - return new Result<ImmutableList<GetRolePermissions>, SqlError>.Ok<ImmutableList<GetRolePermissions>, SqlError>(results.ToImmutable()); - } - catch (Exception ex) - { - return new Result<ImmutableList<GetRolePermissions>, SqlError>.Error<ImmutableList<GetRolePermissions>, SqlError>(new SqlError("Database error", ex)); - } - } -} - -/// <summary> -/// Result row for 'GetRolePermissions' query. -/// </summary> -public record GetRolePermissions -{ - /// <summary>Column 'id'.</summary> - public string id { get; init; } - - /// <summary>Column 'code'.</summary> - public string code { get; init; } - - /// <summary>Column 'resource_type'.</summary> - public string resource_type { get; init; } - - /// <summary>Column 'action'.</summary> - public string action { get; init; } - - /// <summary>Column 'description'.</summary> - public string description { get; init; } - - /// <summary>Column 'created_at'.</summary> - public string created_at { get; init; } - - /// <summary>Column 'granted_at'.</summary> - public string granted_at { get; init; } - - /// <summary>Initializes a new instance of GetRolePermissions.</summary> - public GetRolePermissions( - string id, - string code, - string resource_type, - string action, - string description, - string created_at, - string granted_at - ) - { - this.id = id; - this.code = code; - this.resource_type = resource_type; - this.action = action; - this.description = description; - this.created_at = created_at; - this.granted_at = granted_at; - } -} diff --git a/Gatekeeper/Gatekeeper.Api/Generated/GetSessionById.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/GetSessionById.g.cs deleted file mode 100644 index 2327941..0000000 --- a/Gatekeeper/Gatekeeper.Api/Generated/GetSessionById.g.cs +++ /dev/null @@ -1,145 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Threading.Tasks; -using Npgsql; -using Outcome; -using Nimblesite.Sql.Model; - -namespace Generated; - -/// <summary> -/// Extension methods for 'GetSessionById'. -/// </summary> -public static partial class GetSessionByIdExtensions -{ - /// <summary> - /// Executes 'GetSessionById.sql' and maps results. - /// </summary> - /// <param name="connection">Open NpgsqlConnection connection.</param> - /// <param name="id">Query parameter.</param> - /// <param name="now">Query parameter.</param> - /// <returns>Result of records or SQL error.</returns> - public static async Task<Result<ImmutableList<GetSessionById>, SqlError>> GetSessionByIdAsync(this NpgsqlConnection connection, object id, object now) - { - const string sql = @"-- name: GetSessionById -SELECT s.id, s.user_id, s.credential_id, s.created_at, s.expires_at, s.last_activity_at, - s.ip_address, s.user_agent, s.is_revoked, - u.display_name, u.email -FROM gk_session s -JOIN gk_user u ON s.user_id = u.id -WHERE s.id = @id AND s.is_revoked = false AND s.expires_at > @now AND u.is_active = true; -"; - - try - { - var results = ImmutableList.CreateBuilder<GetSessionById>(); - - using (var command = new NpgsqlCommand(sql, connection)) - { - if (id is not null and not DBNull) - command.Parameters.AddWithValue("@id", id); - else - command.Parameters.Add(new NpgsqlParameter("@id", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); - if (now is not null and not DBNull) - command.Parameters.AddWithValue("@now", now); - else - command.Parameters.Add(new NpgsqlParameter("@now", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); - - using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false)) - { - while (await reader.ReadAsync().ConfigureAwait(false)) - { - var item = new GetSessionById( - reader.IsDBNull(0) ? null : reader.GetFieldValue<string>(0), - reader.IsDBNull(1) ? null : reader.GetFieldValue<string>(1), - reader.IsDBNull(2) ? null : reader.GetFieldValue<string>(2), - reader.IsDBNull(3) ? null : reader.GetFieldValue<string>(3), - reader.IsDBNull(4) ? null : reader.GetFieldValue<string>(4), - reader.IsDBNull(5) ? null : reader.GetFieldValue<string>(5), - reader.IsDBNull(6) ? null : reader.GetFieldValue<string>(6), - reader.IsDBNull(7) ? null : reader.GetFieldValue<string>(7), - reader.IsDBNull(8) ? null : reader.GetFieldValue<bool?>(8), - reader.IsDBNull(9) ? null : reader.GetFieldValue<string>(9), - reader.IsDBNull(10) ? null : reader.GetFieldValue<string>(10) - ); - results.Add(item); - } - } - } - - return new Result<ImmutableList<GetSessionById>, SqlError>.Ok<ImmutableList<GetSessionById>, SqlError>(results.ToImmutable()); - } - catch (Exception ex) - { - return new Result<ImmutableList<GetSessionById>, SqlError>.Error<ImmutableList<GetSessionById>, SqlError>(new SqlError("Database error", ex)); - } - } -} - -/// <summary> -/// Result row for 'GetSessionById' query. -/// </summary> -public record GetSessionById -{ - /// <summary>Column 'id'.</summary> - public string id { get; init; } - - /// <summary>Column 'user_id'.</summary> - public string user_id { get; init; } - - /// <summary>Column 'credential_id'.</summary> - public string credential_id { get; init; } - - /// <summary>Column 'created_at'.</summary> - public string created_at { get; init; } - - /// <summary>Column 'expires_at'.</summary> - public string expires_at { get; init; } - - /// <summary>Column 'last_activity_at'.</summary> - public string last_activity_at { get; init; } - - /// <summary>Column 'ip_address'.</summary> - public string ip_address { get; init; } - - /// <summary>Column 'user_agent'.</summary> - public string user_agent { get; init; } - - /// <summary>Column 'is_revoked'.</summary> - public bool? is_revoked { get; init; } - - /// <summary>Column 'display_name'.</summary> - public string display_name { get; init; } - - /// <summary>Column 'email'.</summary> - public string email { get; init; } - - /// <summary>Initializes a new instance of GetSessionById.</summary> - public GetSessionById( - string id, - string user_id, - string credential_id, - string created_at, - string expires_at, - string last_activity_at, - string ip_address, - string user_agent, - bool? is_revoked, - string display_name, - string email - ) - { - this.id = id; - this.user_id = user_id; - this.credential_id = credential_id; - this.created_at = created_at; - this.expires_at = expires_at; - this.last_activity_at = last_activity_at; - this.ip_address = ip_address; - this.user_agent = user_agent; - this.is_revoked = is_revoked; - this.display_name = display_name; - this.email = email; - } -} diff --git a/Gatekeeper/Gatekeeper.Api/Generated/GetSessionForRevoke.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/GetSessionForRevoke.g.cs deleted file mode 100644 index 4613a72..0000000 --- a/Gatekeeper/Gatekeeper.Api/Generated/GetSessionForRevoke.g.cs +++ /dev/null @@ -1,127 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Threading.Tasks; -using Npgsql; -using Outcome; -using Nimblesite.Sql.Model; - -namespace Generated; - -/// <summary> -/// Extension methods for 'GetSessionForRevoke'. -/// </summary> -public static partial class GetSessionForRevokeExtensions -{ - /// <summary> - /// Executes 'GetSessionForRevoke.sql' and maps results. - /// </summary> - /// <param name="connection">Open NpgsqlConnection connection.</param> - /// <param name="jti">Query parameter.</param> - /// <returns>Result of records or SQL error.</returns> - public static async Task<Result<ImmutableList<GetSessionForRevoke>, SqlError>> GetSessionForRevokeAsync(this NpgsqlConnection connection, object jti) - { - const string sql = @"-- Gets a session for revocation (no filters) --- @jti: The session ID (JWT ID) to get -SELECT id, user_id, credential_id, created_at, expires_at, last_activity_at, - ip_address, user_agent, is_revoked -FROM gk_session -WHERE id = @jti; -"; - - try - { - var results = ImmutableList.CreateBuilder<GetSessionForRevoke>(); - - using (var command = new NpgsqlCommand(sql, connection)) - { - if (jti is not null and not DBNull) - command.Parameters.AddWithValue("@jti", jti); - else - command.Parameters.Add(new NpgsqlParameter("@jti", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); - - using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false)) - { - while (await reader.ReadAsync().ConfigureAwait(false)) - { - var item = new GetSessionForRevoke( - reader.IsDBNull(0) ? null : reader.GetFieldValue<string>(0), - reader.IsDBNull(1) ? null : reader.GetFieldValue<string>(1), - reader.IsDBNull(2) ? null : reader.GetFieldValue<string>(2), - reader.IsDBNull(3) ? null : reader.GetFieldValue<string>(3), - reader.IsDBNull(4) ? null : reader.GetFieldValue<string>(4), - reader.IsDBNull(5) ? null : reader.GetFieldValue<string>(5), - reader.IsDBNull(6) ? null : reader.GetFieldValue<string>(6), - reader.IsDBNull(7) ? null : reader.GetFieldValue<string>(7), - reader.IsDBNull(8) ? null : reader.GetFieldValue<bool?>(8) - ); - results.Add(item); - } - } - } - - return new Result<ImmutableList<GetSessionForRevoke>, SqlError>.Ok<ImmutableList<GetSessionForRevoke>, SqlError>(results.ToImmutable()); - } - catch (Exception ex) - { - return new Result<ImmutableList<GetSessionForRevoke>, SqlError>.Error<ImmutableList<GetSessionForRevoke>, SqlError>(new SqlError("Database error", ex)); - } - } -} - -/// <summary> -/// Result row for 'GetSessionForRevoke' query. -/// </summary> -public record GetSessionForRevoke -{ - /// <summary>Column 'id'.</summary> - public string id { get; init; } - - /// <summary>Column 'user_id'.</summary> - public string user_id { get; init; } - - /// <summary>Column 'credential_id'.</summary> - public string credential_id { get; init; } - - /// <summary>Column 'created_at'.</summary> - public string created_at { get; init; } - - /// <summary>Column 'expires_at'.</summary> - public string expires_at { get; init; } - - /// <summary>Column 'last_activity_at'.</summary> - public string last_activity_at { get; init; } - - /// <summary>Column 'ip_address'.</summary> - public string ip_address { get; init; } - - /// <summary>Column 'user_agent'.</summary> - public string user_agent { get; init; } - - /// <summary>Column 'is_revoked'.</summary> - public bool? is_revoked { get; init; } - - /// <summary>Initializes a new instance of GetSessionForRevoke.</summary> - public GetSessionForRevoke( - string id, - string user_id, - string credential_id, - string created_at, - string expires_at, - string last_activity_at, - string ip_address, - string user_agent, - bool? is_revoked - ) - { - this.id = id; - this.user_id = user_id; - this.credential_id = credential_id; - this.created_at = created_at; - this.expires_at = expires_at; - this.last_activity_at = last_activity_at; - this.ip_address = ip_address; - this.user_agent = user_agent; - this.is_revoked = is_revoked; - } -} diff --git a/Gatekeeper/Gatekeeper.Api/Generated/GetSessionRevoked.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/GetSessionRevoked.g.cs deleted file mode 100644 index 8f83931..0000000 --- a/Gatekeeper/Gatekeeper.Api/Generated/GetSessionRevoked.g.cs +++ /dev/null @@ -1,76 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Threading.Tasks; -using Npgsql; -using Outcome; -using Nimblesite.Sql.Model; - -namespace Generated; - -/// <summary> -/// Extension methods for 'GetSessionRevoked'. -/// </summary> -public static partial class GetSessionRevokedExtensions -{ - /// <summary> - /// Executes 'GetSessionRevoked.sql' and maps results. - /// </summary> - /// <param name="connection">Open NpgsqlConnection connection.</param> - /// <param name="jti">Query parameter.</param> - /// <returns>Result of records or SQL error.</returns> - public static async Task<Result<ImmutableList<GetSessionRevoked>, SqlError>> GetSessionRevokedAsync(this NpgsqlConnection connection, object jti) - { - const string sql = @"-- Gets the revocation status of a session --- @jti: The session ID (JWT ID) to check -SELECT is_revoked FROM gk_session WHERE id = @jti; -"; - - try - { - var results = ImmutableList.CreateBuilder<GetSessionRevoked>(); - - using (var command = new NpgsqlCommand(sql, connection)) - { - if (jti is not null and not DBNull) - command.Parameters.AddWithValue("@jti", jti); - else - command.Parameters.Add(new NpgsqlParameter("@jti", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); - - using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false)) - { - while (await reader.ReadAsync().ConfigureAwait(false)) - { - var item = new GetSessionRevoked( - reader.IsDBNull(0) ? null : reader.GetFieldValue<bool?>(0) - ); - results.Add(item); - } - } - } - - return new Result<ImmutableList<GetSessionRevoked>, SqlError>.Ok<ImmutableList<GetSessionRevoked>, SqlError>(results.ToImmutable()); - } - catch (Exception ex) - { - return new Result<ImmutableList<GetSessionRevoked>, SqlError>.Error<ImmutableList<GetSessionRevoked>, SqlError>(new SqlError("Database error", ex)); - } - } -} - -/// <summary> -/// Result row for 'GetSessionRevoked' query. -/// </summary> -public record GetSessionRevoked -{ - /// <summary>Column 'is_revoked'.</summary> - public bool? is_revoked { get; init; } - - /// <summary>Initializes a new instance of GetSessionRevoked.</summary> - public GetSessionRevoked( - bool? is_revoked - ) - { - this.is_revoked = is_revoked; - } -} diff --git a/Gatekeeper/Gatekeeper.Api/Generated/GetUserByEmail.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/GetUserByEmail.g.cs deleted file mode 100644 index cef636c..0000000 --- a/Gatekeeper/Gatekeeper.Api/Generated/GetUserByEmail.g.cs +++ /dev/null @@ -1,113 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Threading.Tasks; -using Npgsql; -using Outcome; -using Nimblesite.Sql.Model; - -namespace Generated; - -/// <summary> -/// Extension methods for 'GetUserByEmail'. -/// </summary> -public static partial class GetUserByEmailExtensions -{ - /// <summary> - /// Executes 'GetUserByEmail.sql' and maps results. - /// </summary> - /// <param name="connection">Open NpgsqlConnection connection.</param> - /// <param name="email">Query parameter.</param> - /// <returns>Result of records or SQL error.</returns> - public static async Task<Result<ImmutableList<GetUserByEmail>, SqlError>> GetUserByEmailAsync(this NpgsqlConnection connection, object email) - { - const string sql = @"-- name: GetUserByEmail -SELECT id, display_name, email, created_at, last_login_at, is_active, metadata -FROM gk_user -WHERE email = @email AND is_active = true; -"; - - try - { - var results = ImmutableList.CreateBuilder<GetUserByEmail>(); - - using (var command = new NpgsqlCommand(sql, connection)) - { - if (email is not null and not DBNull) - command.Parameters.AddWithValue("@email", email); - else - command.Parameters.Add(new NpgsqlParameter("@email", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); - - using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false)) - { - while (await reader.ReadAsync().ConfigureAwait(false)) - { - var item = new GetUserByEmail( - reader.IsDBNull(0) ? null : reader.GetFieldValue<string>(0), - reader.IsDBNull(1) ? null : reader.GetFieldValue<string>(1), - reader.IsDBNull(2) ? null : reader.GetFieldValue<string>(2), - reader.IsDBNull(3) ? null : reader.GetFieldValue<string>(3), - reader.IsDBNull(4) ? null : reader.GetFieldValue<string>(4), - reader.IsDBNull(5) ? null : reader.GetFieldValue<bool?>(5), - reader.IsDBNull(6) ? null : reader.GetFieldValue<string>(6) - ); - results.Add(item); - } - } - } - - return new Result<ImmutableList<GetUserByEmail>, SqlError>.Ok<ImmutableList<GetUserByEmail>, SqlError>(results.ToImmutable()); - } - catch (Exception ex) - { - return new Result<ImmutableList<GetUserByEmail>, SqlError>.Error<ImmutableList<GetUserByEmail>, SqlError>(new SqlError("Database error", ex)); - } - } -} - -/// <summary> -/// Result row for 'GetUserByEmail' query. -/// </summary> -public record GetUserByEmail -{ - /// <summary>Column 'id'.</summary> - public string id { get; init; } - - /// <summary>Column 'display_name'.</summary> - public string display_name { get; init; } - - /// <summary>Column 'email'.</summary> - public string email { get; init; } - - /// <summary>Column 'created_at'.</summary> - public string created_at { get; init; } - - /// <summary>Column 'last_login_at'.</summary> - public string last_login_at { get; init; } - - /// <summary>Column 'is_active'.</summary> - public bool? is_active { get; init; } - - /// <summary>Column 'metadata'.</summary> - public string metadata { get; init; } - - /// <summary>Initializes a new instance of GetUserByEmail.</summary> - public GetUserByEmail( - string id, - string display_name, - string email, - string created_at, - string last_login_at, - bool? is_active, - string metadata - ) - { - this.id = id; - this.display_name = display_name; - this.email = email; - this.created_at = created_at; - this.last_login_at = last_login_at; - this.is_active = is_active; - this.metadata = metadata; - } -} diff --git a/Gatekeeper/Gatekeeper.Api/Generated/GetUserById.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/GetUserById.g.cs deleted file mode 100644 index 94f0278..0000000 --- a/Gatekeeper/Gatekeeper.Api/Generated/GetUserById.g.cs +++ /dev/null @@ -1,113 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Threading.Tasks; -using Npgsql; -using Outcome; -using Nimblesite.Sql.Model; - -namespace Generated; - -/// <summary> -/// Extension methods for 'GetUserById'. -/// </summary> -public static partial class GetUserByIdExtensions -{ - /// <summary> - /// Executes 'GetUserById.sql' and maps results. - /// </summary> - /// <param name="connection">Open NpgsqlConnection connection.</param> - /// <param name="id">Query parameter.</param> - /// <returns>Result of records or SQL error.</returns> - public static async Task<Result<ImmutableList<GetUserById>, SqlError>> GetUserByIdAsync(this NpgsqlConnection connection, object id) - { - const string sql = @"-- name: GetUserById -SELECT id, display_name, email, created_at, last_login_at, is_active, metadata -FROM gk_user -WHERE id = @id; -"; - - try - { - var results = ImmutableList.CreateBuilder<GetUserById>(); - - using (var command = new NpgsqlCommand(sql, connection)) - { - if (id is not null and not DBNull) - command.Parameters.AddWithValue("@id", id); - else - command.Parameters.Add(new NpgsqlParameter("@id", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); - - using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false)) - { - while (await reader.ReadAsync().ConfigureAwait(false)) - { - var item = new GetUserById( - reader.IsDBNull(0) ? null : reader.GetFieldValue<string>(0), - reader.IsDBNull(1) ? null : reader.GetFieldValue<string>(1), - reader.IsDBNull(2) ? null : reader.GetFieldValue<string>(2), - reader.IsDBNull(3) ? null : reader.GetFieldValue<string>(3), - reader.IsDBNull(4) ? null : reader.GetFieldValue<string>(4), - reader.IsDBNull(5) ? null : reader.GetFieldValue<bool?>(5), - reader.IsDBNull(6) ? null : reader.GetFieldValue<string>(6) - ); - results.Add(item); - } - } - } - - return new Result<ImmutableList<GetUserById>, SqlError>.Ok<ImmutableList<GetUserById>, SqlError>(results.ToImmutable()); - } - catch (Exception ex) - { - return new Result<ImmutableList<GetUserById>, SqlError>.Error<ImmutableList<GetUserById>, SqlError>(new SqlError("Database error", ex)); - } - } -} - -/// <summary> -/// Result row for 'GetUserById' query. -/// </summary> -public record GetUserById -{ - /// <summary>Column 'id'.</summary> - public string id { get; init; } - - /// <summary>Column 'display_name'.</summary> - public string display_name { get; init; } - - /// <summary>Column 'email'.</summary> - public string email { get; init; } - - /// <summary>Column 'created_at'.</summary> - public string created_at { get; init; } - - /// <summary>Column 'last_login_at'.</summary> - public string last_login_at { get; init; } - - /// <summary>Column 'is_active'.</summary> - public bool? is_active { get; init; } - - /// <summary>Column 'metadata'.</summary> - public string metadata { get; init; } - - /// <summary>Initializes a new instance of GetUserById.</summary> - public GetUserById( - string id, - string display_name, - string email, - string created_at, - string last_login_at, - bool? is_active, - string metadata - ) - { - this.id = id; - this.display_name = display_name; - this.email = email; - this.created_at = created_at; - this.last_login_at = last_login_at; - this.is_active = is_active; - this.metadata = metadata; - } -} diff --git a/Gatekeeper/Gatekeeper.Api/Generated/GetUserCredentials.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/GetUserCredentials.g.cs deleted file mode 100644 index 725a67c..0000000 --- a/Gatekeeper/Gatekeeper.Api/Generated/GetUserCredentials.g.cs +++ /dev/null @@ -1,150 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Threading.Tasks; -using Npgsql; -using Outcome; -using Nimblesite.Sql.Model; - -namespace Generated; - -/// <summary> -/// Extension methods for 'GetUserCredentials'. -/// </summary> -public static partial class GetUserCredentialsExtensions -{ - /// <summary> - /// Executes 'GetUserCredentials.sql' and maps results. - /// </summary> - /// <param name="connection">Open NpgsqlConnection connection.</param> - /// <param name="user_id">Query parameter.</param> - /// <returns>Result of records or SQL error.</returns> - public static async Task<Result<ImmutableList<GetUserCredentials>, SqlError>> GetUserCredentialsAsync(this NpgsqlConnection connection, object user_id) - { - const string sql = @"-- name: GetUserCredentials -SELECT id, user_id, public_key, sign_count, aaguid, credential_type, transports, - attestation_format, created_at, last_used_at, device_name, is_backup_eligible, is_backed_up -FROM gk_credential -WHERE user_id = @user_id; -"; - - try - { - var results = ImmutableList.CreateBuilder<GetUserCredentials>(); - - using (var command = new NpgsqlCommand(sql, connection)) - { - if (user_id is not null and not DBNull) - command.Parameters.AddWithValue("@user_id", user_id); - else - command.Parameters.Add(new NpgsqlParameter("@user_id", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); - - using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false)) - { - while (await reader.ReadAsync().ConfigureAwait(false)) - { - var item = new GetUserCredentials( - reader.IsDBNull(0) ? null : reader.GetFieldValue<string>(0), - reader.IsDBNull(1) ? null : reader.GetFieldValue<string>(1), - reader.IsDBNull(2) ? null : reader.GetFieldValue<byte[]>(2), - reader.IsDBNull(3) ? default(long) : reader.GetFieldValue<long>(3), - reader.IsDBNull(4) ? null : reader.GetFieldValue<string>(4), - reader.IsDBNull(5) ? null : reader.GetFieldValue<string>(5), - reader.IsDBNull(6) ? null : reader.GetFieldValue<string>(6), - reader.IsDBNull(7) ? null : reader.GetFieldValue<string>(7), - reader.IsDBNull(8) ? null : reader.GetFieldValue<string>(8), - reader.IsDBNull(9) ? null : reader.GetFieldValue<string>(9), - reader.IsDBNull(10) ? null : reader.GetFieldValue<string>(10), - reader.IsDBNull(11) ? null : reader.GetFieldValue<bool?>(11), - reader.IsDBNull(12) ? null : reader.GetFieldValue<bool?>(12) - ); - results.Add(item); - } - } - } - - return new Result<ImmutableList<GetUserCredentials>, SqlError>.Ok<ImmutableList<GetUserCredentials>, SqlError>(results.ToImmutable()); - } - catch (Exception ex) - { - return new Result<ImmutableList<GetUserCredentials>, SqlError>.Error<ImmutableList<GetUserCredentials>, SqlError>(new SqlError("Database error", ex)); - } - } -} - -/// <summary> -/// Result row for 'GetUserCredentials' query. -/// </summary> -public record GetUserCredentials -{ - /// <summary>Column 'id'.</summary> - public string id { get; init; } - - /// <summary>Column 'user_id'.</summary> - public string user_id { get; init; } - - /// <summary>Column 'public_key'.</summary> - public byte[] public_key { get; init; } - - /// <summary>Column 'sign_count'.</summary> - public long sign_count { get; init; } - - /// <summary>Column 'aaguid'.</summary> - public string aaguid { get; init; } - - /// <summary>Column 'credential_type'.</summary> - public string credential_type { get; init; } - - /// <summary>Column 'transports'.</summary> - public string transports { get; init; } - - /// <summary>Column 'attestation_format'.</summary> - public string attestation_format { get; init; } - - /// <summary>Column 'created_at'.</summary> - public string created_at { get; init; } - - /// <summary>Column 'last_used_at'.</summary> - public string last_used_at { get; init; } - - /// <summary>Column 'device_name'.</summary> - public string device_name { get; init; } - - /// <summary>Column 'is_backup_eligible'.</summary> - public bool? is_backup_eligible { get; init; } - - /// <summary>Column 'is_backed_up'.</summary> - public bool? is_backed_up { get; init; } - - /// <summary>Initializes a new instance of GetUserCredentials.</summary> - public GetUserCredentials( - string id, - string user_id, - byte[] public_key, - long sign_count, - string aaguid, - string credential_type, - string transports, - string attestation_format, - string created_at, - string last_used_at, - string device_name, - bool? is_backup_eligible, - bool? is_backed_up - ) - { - this.id = id; - this.user_id = user_id; - this.public_key = public_key; - this.sign_count = sign_count; - this.aaguid = aaguid; - this.credential_type = credential_type; - this.transports = transports; - this.attestation_format = attestation_format; - this.created_at = created_at; - this.last_used_at = last_used_at; - this.device_name = device_name; - this.is_backup_eligible = is_backup_eligible; - this.is_backed_up = is_backed_up; - } -} diff --git a/Gatekeeper/Gatekeeper.Api/Generated/GetUserPermissions.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/GetUserPermissions.g.cs deleted file mode 100644 index 2b881ab..0000000 --- a/Gatekeeper/Gatekeeper.Api/Generated/GetUserPermissions.g.cs +++ /dev/null @@ -1,152 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Threading.Tasks; -using Npgsql; -using Outcome; -using Nimblesite.Sql.Model; - -namespace Generated; - -/// <summary> -/// Extension methods for 'GetUserPermissions'. -/// </summary> -public static partial class GetUserPermissionsExtensions -{ - /// <summary> - /// Executes 'GetUserPermissions.sql' and maps results. - /// </summary> - /// <param name="connection">Open NpgsqlConnection connection.</param> - /// <param name="user_id">Query parameter.</param> - /// <param name="now">Query parameter.</param> - /// <returns>Result of records or SQL error.</returns> - public static async Task<Result<ImmutableList<GetUserPermissions>, SqlError>> GetUserPermissionsAsync(this NpgsqlConnection connection, object user_id, object now) - { - const string sql = @"-- name: GetUserPermissions --- Returns all permissions for a user: from roles + direct grants --- Note: source_type column uses role name prefix to indicate source (role-based vs direct) -SELECT DISTINCT p.id, p.code, p.resource_type, p.action, p.description, - r.name as source_name, - ur.role_id as source_type, - NULL as scope_type, - NULL as scope_value -FROM gk_user_role ur -JOIN gk_role r ON ur.role_id = r.id -JOIN gk_role_permission rp ON r.id = rp.role_id -JOIN gk_permission p ON rp.permission_id = p.id -WHERE ur.user_id = @user_id - AND (ur.expires_at IS NULL OR ur.expires_at > @now) - -UNION ALL - -SELECT p.id, p.code, p.resource_type, p.action, p.description, - p.code as source_name, - up.permission_id as source_type, - COALESCE(up.scope_type, p.resource_type) as scope_type, - COALESCE(up.scope_value, p.action) as scope_value -FROM gk_user_permission up -JOIN gk_permission p ON up.permission_id = p.id -WHERE up.user_id = @user_id - AND (up.expires_at IS NULL OR up.expires_at > @now); -"; - - try - { - var results = ImmutableList.CreateBuilder<GetUserPermissions>(); - - using (var command = new NpgsqlCommand(sql, connection)) - { - if (user_id is not null and not DBNull) - command.Parameters.AddWithValue("@user_id", user_id); - else - command.Parameters.Add(new NpgsqlParameter("@user_id", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); - if (now is not null and not DBNull) - command.Parameters.AddWithValue("@now", now); - else - command.Parameters.Add(new NpgsqlParameter("@now", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); - - using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false)) - { - while (await reader.ReadAsync().ConfigureAwait(false)) - { - var item = new GetUserPermissions( - reader.IsDBNull(0) ? null : reader.GetFieldValue<string>(0), - reader.IsDBNull(1) ? null : reader.GetFieldValue<string>(1), - reader.IsDBNull(2) ? null : reader.GetFieldValue<string>(2), - reader.IsDBNull(3) ? null : reader.GetFieldValue<string>(3), - reader.IsDBNull(4) ? null : reader.GetFieldValue<string>(4), - reader.IsDBNull(5) ? null : reader.GetFieldValue<string>(5), - reader.IsDBNull(6) ? null : reader.GetFieldValue<string>(6), - reader.IsDBNull(7) ? null : reader.GetFieldValue<byte[]>(7), - reader.IsDBNull(8) ? null : reader.GetFieldValue<byte[]>(8) - ); - results.Add(item); - } - } - } - - return new Result<ImmutableList<GetUserPermissions>, SqlError>.Ok<ImmutableList<GetUserPermissions>, SqlError>(results.ToImmutable()); - } - catch (Exception ex) - { - return new Result<ImmutableList<GetUserPermissions>, SqlError>.Error<ImmutableList<GetUserPermissions>, SqlError>(new SqlError("Database error", ex)); - } - } -} - -/// <summary> -/// Result row for 'GetUserPermissions' query. -/// </summary> -public record GetUserPermissions -{ - /// <summary>Column 'id'.</summary> - public string id { get; init; } - - /// <summary>Column 'code'.</summary> - public string code { get; init; } - - /// <summary>Column 'resource_type'.</summary> - public string resource_type { get; init; } - - /// <summary>Column 'action'.</summary> - public string action { get; init; } - - /// <summary>Column 'description'.</summary> - public string description { get; init; } - - /// <summary>Column 'source_name'.</summary> - public string source_name { get; init; } - - /// <summary>Column 'source_type'.</summary> - public string source_type { get; init; } - - /// <summary>Column 'scope_type'.</summary> - public byte[] scope_type { get; init; } - - /// <summary>Column 'scope_value'.</summary> - public byte[] scope_value { get; init; } - - /// <summary>Initializes a new instance of GetUserPermissions.</summary> - public GetUserPermissions( - string id, - string code, - string resource_type, - string action, - string description, - string source_name, - string source_type, - byte[] scope_type, - byte[] scope_value - ) - { - this.id = id; - this.code = code; - this.resource_type = resource_type; - this.action = action; - this.description = description; - this.source_name = source_name; - this.source_type = source_type; - this.scope_type = scope_type; - this.scope_value = scope_value; - } -} diff --git a/Gatekeeper/Gatekeeper.Api/Generated/GetUserRoles.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/GetUserRoles.g.cs deleted file mode 100644 index c024210..0000000 --- a/Gatekeeper/Gatekeeper.Api/Generated/GetUserRoles.g.cs +++ /dev/null @@ -1,114 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Threading.Tasks; -using Npgsql; -using Outcome; -using Nimblesite.Sql.Model; - -namespace Generated; - -/// <summary> -/// Extension methods for 'GetUserRoles'. -/// </summary> -public static partial class GetUserRolesExtensions -{ - /// <summary> - /// Executes 'GetUserRoles.sql' and maps results. - /// </summary> - /// <param name="connection">Open NpgsqlConnection connection.</param> - /// <param name="user_id">Query parameter.</param> - /// <param name="now">Query parameter.</param> - /// <returns>Result of records or SQL error.</returns> - public static async Task<Result<ImmutableList<GetUserRoles>, SqlError>> GetUserRolesAsync(this NpgsqlConnection connection, object user_id, object now) - { - const string sql = @"-- name: GetUserRoles -SELECT r.id, r.name, r.description, r.is_system, ur.granted_at, ur.expires_at -FROM gk_user_role ur -JOIN gk_role r ON ur.role_id = r.id -WHERE ur.user_id = @user_id - AND (ur.expires_at IS NULL OR ur.expires_at > @now); -"; - - try - { - var results = ImmutableList.CreateBuilder<GetUserRoles>(); - - using (var command = new NpgsqlCommand(sql, connection)) - { - if (user_id is not null and not DBNull) - command.Parameters.AddWithValue("@user_id", user_id); - else - command.Parameters.Add(new NpgsqlParameter("@user_id", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); - if (now is not null and not DBNull) - command.Parameters.AddWithValue("@now", now); - else - command.Parameters.Add(new NpgsqlParameter("@now", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); - - using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false)) - { - while (await reader.ReadAsync().ConfigureAwait(false)) - { - var item = new GetUserRoles( - reader.IsDBNull(0) ? null : reader.GetFieldValue<string>(0), - reader.IsDBNull(1) ? null : reader.GetFieldValue<string>(1), - reader.IsDBNull(2) ? null : reader.GetFieldValue<string>(2), - reader.IsDBNull(3) ? null : reader.GetFieldValue<bool?>(3), - reader.IsDBNull(4) ? null : reader.GetFieldValue<string>(4), - reader.IsDBNull(5) ? null : reader.GetFieldValue<string>(5) - ); - results.Add(item); - } - } - } - - return new Result<ImmutableList<GetUserRoles>, SqlError>.Ok<ImmutableList<GetUserRoles>, SqlError>(results.ToImmutable()); - } - catch (Exception ex) - { - return new Result<ImmutableList<GetUserRoles>, SqlError>.Error<ImmutableList<GetUserRoles>, SqlError>(new SqlError("Database error", ex)); - } - } -} - -/// <summary> -/// Result row for 'GetUserRoles' query. -/// </summary> -public record GetUserRoles -{ - /// <summary>Column 'id'.</summary> - public string id { get; init; } - - /// <summary>Column 'name'.</summary> - public string name { get; init; } - - /// <summary>Column 'description'.</summary> - public string description { get; init; } - - /// <summary>Column 'is_system'.</summary> - public bool? is_system { get; init; } - - /// <summary>Column 'granted_at'.</summary> - public string granted_at { get; init; } - - /// <summary>Column 'expires_at'.</summary> - public string expires_at { get; init; } - - /// <summary>Initializes a new instance of GetUserRoles.</summary> - public GetUserRoles( - string id, - string name, - string description, - bool? is_system, - string granted_at, - string expires_at - ) - { - this.id = id; - this.name = name; - this.description = description; - this.is_system = is_system; - this.granted_at = granted_at; - this.expires_at = expires_at; - } -} diff --git a/Gatekeeper/Gatekeeper.Api/Generated/RevokeSession.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/RevokeSession.g.cs deleted file mode 100644 index 052b1cf..0000000 --- a/Gatekeeper/Gatekeeper.Api/Generated/RevokeSession.g.cs +++ /dev/null @@ -1,82 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Threading.Tasks; -using Npgsql; -using Outcome; -using Nimblesite.Sql.Model; - -namespace Generated; - -/// <summary> -/// Extension methods for 'RevokeSession'. -/// </summary> -public static partial class RevokeSessionExtensions -{ - /// <summary> - /// Executes 'RevokeSession.sql' and maps results. - /// </summary> - /// <param name="connection">Open NpgsqlConnection connection.</param> - /// <param name="jti">Query parameter.</param> - /// <returns>Result of records or SQL error.</returns> - public static async Task<Result<ImmutableList<RevokeSession>, SqlError>> RevokeSessionAsync(this NpgsqlConnection connection, object jti) - { - const string sql = @"-- Revokes a session by setting is_revoked = true --- @jti: The session ID (JWT ID) to revoke -UPDATE gk_session SET is_revoked = true WHERE id = @jti RETURNING id, is_revoked; -"; - - try - { - var results = ImmutableList.CreateBuilder<RevokeSession>(); - - using (var command = new NpgsqlCommand(sql, connection)) - { - if (jti is not null and not DBNull) - command.Parameters.AddWithValue("@jti", jti); - else - command.Parameters.Add(new NpgsqlParameter("@jti", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); - - using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false)) - { - while (await reader.ReadAsync().ConfigureAwait(false)) - { - var item = new RevokeSession( - reader.IsDBNull(0) ? null : reader.GetFieldValue<string>(0), - reader.IsDBNull(1) ? null : reader.GetFieldValue<bool?>(1) - ); - results.Add(item); - } - } - } - - return new Result<ImmutableList<RevokeSession>, SqlError>.Ok<ImmutableList<RevokeSession>, SqlError>(results.ToImmutable()); - } - catch (Exception ex) - { - return new Result<ImmutableList<RevokeSession>, SqlError>.Error<ImmutableList<RevokeSession>, SqlError>(new SqlError("Database error", ex)); - } - } -} - -/// <summary> -/// Result row for 'RevokeSession' query. -/// </summary> -public record RevokeSession -{ - /// <summary>Column 'id'.</summary> - public string id { get; init; } - - /// <summary>Column 'is_revoked'.</summary> - public bool? is_revoked { get; init; } - - /// <summary>Initializes a new instance of RevokeSession.</summary> - public RevokeSession( - string id, - bool? is_revoked - ) - { - this.id = id; - this.is_revoked = is_revoked; - } -} diff --git a/Gatekeeper/Gatekeeper.Api/Generated/gk_challengeOperations.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/gk_challengeOperations.g.cs deleted file mode 100644 index d846599..0000000 --- a/Gatekeeper/Gatekeeper.Api/Generated/gk_challengeOperations.g.cs +++ /dev/null @@ -1,52 +0,0 @@ -#nullable enable -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Data; -using System.Globalization; -using System.Threading.Tasks; -using Npgsql; -using Outcome; -using Nimblesite.Sql.Model; - -namespace Generated -{ - /// <summary> - /// Extension methods for table operations on gk_challenge - /// </summary> - public static partial class gk_challengeExtensions - { - - /// <summary> - /// Inserts a new row into the gk_challenge table. - /// </summary> - public static async Task<Result<int, SqlError>> Insertgk_challengeAsync(this IDbTransaction transaction, string? id, string? user_id, byte[] challenge, string? type, string? created_at, string? expires_at) - { - const string sql = "INSERT INTO gk_challenge (id, user_id, challenge, type, created_at, expires_at) VALUES (@id, @user_id, @challenge, @type, @created_at, @expires_at)"; - - if (transaction.Connection is null) - return new Result<int, SqlError>.Error<int, SqlError>(new SqlError("Transaction has no connection")); - - try - { - using (var command = new NpgsqlCommand(sql, (NpgsqlConnection)transaction.Connection!, (NpgsqlTransaction)transaction)) - { - command.Parameters.AddWithValue("@id", id ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@user_id", user_id ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@challenge", challenge ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@type", type ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@created_at", created_at ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@expires_at", expires_at ?? (object)DBNull.Value); - - var rowsAffected = await command.ExecuteNonQueryAsync().ConfigureAwait(false); - return new Result<int, SqlError>.Ok<int, SqlError>(rowsAffected); - } - } - catch (Exception ex) - { - return new Result<int, SqlError>.Error<int, SqlError>(new SqlError("Insert failed", ex)); - } - } - - } -} diff --git a/Gatekeeper/Gatekeeper.Api/Generated/gk_credentialOperations.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/gk_credentialOperations.g.cs deleted file mode 100644 index fb37582..0000000 --- a/Gatekeeper/Gatekeeper.Api/Generated/gk_credentialOperations.g.cs +++ /dev/null @@ -1,59 +0,0 @@ -#nullable enable -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Data; -using System.Globalization; -using System.Threading.Tasks; -using Npgsql; -using Outcome; -using Nimblesite.Sql.Model; - -namespace Generated -{ - /// <summary> - /// Extension methods for table operations on gk_credential - /// </summary> - public static partial class gk_credentialExtensions - { - - /// <summary> - /// Inserts a new row into the gk_credential table. - /// </summary> - public static async Task<Result<int, SqlError>> Insertgk_credentialAsync(this IDbTransaction transaction, string? id, string? user_id, byte[] public_key, long? sign_count, string? aaguid, string? credential_type, string? transports, string? attestation_format, string? created_at, string? last_used_at, string? device_name, bool? is_backup_eligible, bool? is_backed_up) - { - const string sql = "INSERT INTO gk_credential (id, user_id, public_key, sign_count, aaguid, credential_type, transports, attestation_format, created_at, last_used_at, device_name, is_backup_eligible, is_backed_up) VALUES (@id, @user_id, @public_key, @sign_count, @aaguid, @credential_type, @transports, @attestation_format, @created_at, @last_used_at, @device_name, @is_backup_eligible, @is_backed_up)"; - - if (transaction.Connection is null) - return new Result<int, SqlError>.Error<int, SqlError>(new SqlError("Transaction has no connection")); - - try - { - using (var command = new NpgsqlCommand(sql, (NpgsqlConnection)transaction.Connection!, (NpgsqlTransaction)transaction)) - { - command.Parameters.AddWithValue("@id", id ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@user_id", user_id ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@public_key", public_key ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@sign_count", sign_count ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@aaguid", aaguid ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@credential_type", credential_type ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@transports", transports ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@attestation_format", attestation_format ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@created_at", created_at ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@last_used_at", last_used_at ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@device_name", device_name ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@is_backup_eligible", is_backup_eligible ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@is_backed_up", is_backed_up ?? (object)DBNull.Value); - - var rowsAffected = await command.ExecuteNonQueryAsync().ConfigureAwait(false); - return new Result<int, SqlError>.Ok<int, SqlError>(rowsAffected); - } - } - catch (Exception ex) - { - return new Result<int, SqlError>.Error<int, SqlError>(new SqlError("Insert failed", ex)); - } - } - - } -} diff --git a/Gatekeeper/Gatekeeper.Api/Generated/gk_permissionOperations.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/gk_permissionOperations.g.cs deleted file mode 100644 index 5e21816..0000000 --- a/Gatekeeper/Gatekeeper.Api/Generated/gk_permissionOperations.g.cs +++ /dev/null @@ -1,52 +0,0 @@ -#nullable enable -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Data; -using System.Globalization; -using System.Threading.Tasks; -using Npgsql; -using Outcome; -using Nimblesite.Sql.Model; - -namespace Generated -{ - /// <summary> - /// Extension methods for table operations on gk_permission - /// </summary> - public static partial class gk_permissionExtensions - { - - /// <summary> - /// Inserts a new row into the gk_permission table. - /// </summary> - public static async Task<Result<int, SqlError>> Insertgk_permissionAsync(this IDbTransaction transaction, string? id, string? code, string? resource_type, string? action, string? description, string? created_at) - { - const string sql = "INSERT INTO gk_permission (id, code, resource_type, action, description, created_at) VALUES (@id, @code, @resource_type, @action, @description, @created_at)"; - - if (transaction.Connection is null) - return new Result<int, SqlError>.Error<int, SqlError>(new SqlError("Transaction has no connection")); - - try - { - using (var command = new NpgsqlCommand(sql, (NpgsqlConnection)transaction.Connection!, (NpgsqlTransaction)transaction)) - { - command.Parameters.AddWithValue("@id", id ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@code", code ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@resource_type", resource_type ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@action", action ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@description", description ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@created_at", created_at ?? (object)DBNull.Value); - - var rowsAffected = await command.ExecuteNonQueryAsync().ConfigureAwait(false); - return new Result<int, SqlError>.Ok<int, SqlError>(rowsAffected); - } - } - catch (Exception ex) - { - return new Result<int, SqlError>.Error<int, SqlError>(new SqlError("Insert failed", ex)); - } - } - - } -} diff --git a/Gatekeeper/Gatekeeper.Api/Generated/gk_resource_grantOperations.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/gk_resource_grantOperations.g.cs deleted file mode 100644 index 6d13572..0000000 --- a/Gatekeeper/Gatekeeper.Api/Generated/gk_resource_grantOperations.g.cs +++ /dev/null @@ -1,54 +0,0 @@ -#nullable enable -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Data; -using System.Globalization; -using System.Threading.Tasks; -using Npgsql; -using Outcome; -using Nimblesite.Sql.Model; - -namespace Generated -{ - /// <summary> - /// Extension methods for table operations on gk_resource_grant - /// </summary> - public static partial class gk_resource_grantExtensions - { - - /// <summary> - /// Inserts a new row into the gk_resource_grant table. - /// </summary> - public static async Task<Result<int, SqlError>> Insertgk_resource_grantAsync(this IDbTransaction transaction, string? id, string? user_id, string? resource_type, string? resource_id, string? permission_id, string? granted_at, string? granted_by, string? expires_at) - { - const string sql = "INSERT INTO gk_resource_grant (id, user_id, resource_type, resource_id, permission_id, granted_at, granted_by, expires_at) VALUES (@id, @user_id, @resource_type, @resource_id, @permission_id, @granted_at, @granted_by, @expires_at)"; - - if (transaction.Connection is null) - return new Result<int, SqlError>.Error<int, SqlError>(new SqlError("Transaction has no connection")); - - try - { - using (var command = new NpgsqlCommand(sql, (NpgsqlConnection)transaction.Connection!, (NpgsqlTransaction)transaction)) - { - command.Parameters.AddWithValue("@id", id ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@user_id", user_id ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@resource_type", resource_type ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@resource_id", resource_id ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@permission_id", permission_id ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@granted_at", granted_at ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@granted_by", granted_by ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@expires_at", expires_at ?? (object)DBNull.Value); - - var rowsAffected = await command.ExecuteNonQueryAsync().ConfigureAwait(false); - return new Result<int, SqlError>.Ok<int, SqlError>(rowsAffected); - } - } - catch (Exception ex) - { - return new Result<int, SqlError>.Error<int, SqlError>(new SqlError("Insert failed", ex)); - } - } - - } -} diff --git a/Gatekeeper/Gatekeeper.Api/Generated/gk_roleOperations.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/gk_roleOperations.g.cs deleted file mode 100644 index cdd5d4d..0000000 --- a/Gatekeeper/Gatekeeper.Api/Generated/gk_roleOperations.g.cs +++ /dev/null @@ -1,52 +0,0 @@ -#nullable enable -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Data; -using System.Globalization; -using System.Threading.Tasks; -using Npgsql; -using Outcome; -using Nimblesite.Sql.Model; - -namespace Generated -{ - /// <summary> - /// Extension methods for table operations on gk_role - /// </summary> - public static partial class gk_roleExtensions - { - - /// <summary> - /// Inserts a new row into the gk_role table. - /// </summary> - public static async Task<Result<int, SqlError>> Insertgk_roleAsync(this IDbTransaction transaction, string? id, string? name, string? description, bool? is_system, string? created_at, string? parent_role_id) - { - const string sql = "INSERT INTO gk_role (id, name, description, is_system, created_at, parent_role_id) VALUES (@id, @name, @description, @is_system, @created_at, @parent_role_id)"; - - if (transaction.Connection is null) - return new Result<int, SqlError>.Error<int, SqlError>(new SqlError("Transaction has no connection")); - - try - { - using (var command = new NpgsqlCommand(sql, (NpgsqlConnection)transaction.Connection!, (NpgsqlTransaction)transaction)) - { - command.Parameters.AddWithValue("@id", id ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@name", name ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@description", description ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@is_system", is_system ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@created_at", created_at ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@parent_role_id", parent_role_id ?? (object)DBNull.Value); - - var rowsAffected = await command.ExecuteNonQueryAsync().ConfigureAwait(false); - return new Result<int, SqlError>.Ok<int, SqlError>(rowsAffected); - } - } - catch (Exception ex) - { - return new Result<int, SqlError>.Error<int, SqlError>(new SqlError("Insert failed", ex)); - } - } - - } -} diff --git a/Gatekeeper/Gatekeeper.Api/Generated/gk_role_permissionOperations.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/gk_role_permissionOperations.g.cs deleted file mode 100644 index 32067ed..0000000 --- a/Gatekeeper/Gatekeeper.Api/Generated/gk_role_permissionOperations.g.cs +++ /dev/null @@ -1,49 +0,0 @@ -#nullable enable -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Data; -using System.Globalization; -using System.Threading.Tasks; -using Npgsql; -using Outcome; -using Nimblesite.Sql.Model; - -namespace Generated -{ - /// <summary> - /// Extension methods for table operations on gk_role_permission - /// </summary> - public static partial class gk_role_permissionExtensions - { - - /// <summary> - /// Inserts a new row into the gk_role_permission table. - /// </summary> - public static async Task<Result<int, SqlError>> Insertgk_role_permissionAsync(this IDbTransaction transaction, string? role_id, string? permission_id, string? granted_at) - { - const string sql = "INSERT INTO gk_role_permission (role_id, permission_id, granted_at) VALUES (@role_id, @permission_id, @granted_at)"; - - if (transaction.Connection is null) - return new Result<int, SqlError>.Error<int, SqlError>(new SqlError("Transaction has no connection")); - - try - { - using (var command = new NpgsqlCommand(sql, (NpgsqlConnection)transaction.Connection!, (NpgsqlTransaction)transaction)) - { - command.Parameters.AddWithValue("@role_id", role_id ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@permission_id", permission_id ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@granted_at", granted_at ?? (object)DBNull.Value); - - var rowsAffected = await command.ExecuteNonQueryAsync().ConfigureAwait(false); - return new Result<int, SqlError>.Ok<int, SqlError>(rowsAffected); - } - } - catch (Exception ex) - { - return new Result<int, SqlError>.Error<int, SqlError>(new SqlError("Insert failed", ex)); - } - } - - } -} diff --git a/Gatekeeper/Gatekeeper.Api/Generated/gk_sessionOperations.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/gk_sessionOperations.g.cs deleted file mode 100644 index 035254c..0000000 --- a/Gatekeeper/Gatekeeper.Api/Generated/gk_sessionOperations.g.cs +++ /dev/null @@ -1,90 +0,0 @@ -#nullable enable -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Data; -using System.Globalization; -using System.Threading.Tasks; -using Npgsql; -using Outcome; -using Nimblesite.Sql.Model; - -namespace Generated -{ - /// <summary> - /// Extension methods for table operations on gk_session - /// </summary> - public static partial class gk_sessionExtensions - { - - /// <summary> - /// Inserts a new row into the gk_session table. - /// </summary> - public static async Task<Result<int, SqlError>> Insertgk_sessionAsync(this IDbTransaction transaction, string? id, string? user_id, string? credential_id, string? created_at, string? expires_at, string? last_activity_at, string? ip_address, string? user_agent, bool? is_revoked) - { - const string sql = "INSERT INTO gk_session (id, user_id, credential_id, created_at, expires_at, last_activity_at, ip_address, user_agent, is_revoked) VALUES (@id, @user_id, @credential_id, @created_at, @expires_at, @last_activity_at, @ip_address, @user_agent, @is_revoked)"; - - if (transaction.Connection is null) - return new Result<int, SqlError>.Error<int, SqlError>(new SqlError("Transaction has no connection")); - - try - { - using (var command = new NpgsqlCommand(sql, (NpgsqlConnection)transaction.Connection!, (NpgsqlTransaction)transaction)) - { - command.Parameters.AddWithValue("@id", id ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@user_id", user_id ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@credential_id", credential_id ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@created_at", created_at ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@expires_at", expires_at ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@last_activity_at", last_activity_at ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@ip_address", ip_address ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@user_agent", user_agent ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@is_revoked", is_revoked ?? (object)DBNull.Value); - - var rowsAffected = await command.ExecuteNonQueryAsync().ConfigureAwait(false); - return new Result<int, SqlError>.Ok<int, SqlError>(rowsAffected); - } - } - catch (Exception ex) - { - return new Result<int, SqlError>.Error<int, SqlError>(new SqlError("Insert failed", ex)); - } - } - - - /// <summary> - /// Updates a row in the gk_session table. - /// </summary> - public static async Task<Result<int, SqlError>> Updategk_sessionAsync(this IDbTransaction transaction, string id, string user_id, string credential_id, string created_at, string expires_at, string last_activity_at, string ip_address, string user_agent, bool? is_revoked) - { - const string sql = "UPDATE gk_session SET user_id = @user_id, credential_id = @credential_id, created_at = @created_at, expires_at = @expires_at, last_activity_at = @last_activity_at, ip_address = @ip_address, user_agent = @user_agent, is_revoked = @is_revoked WHERE id = @id"; - - if (transaction.Connection is null) - return new Result<int, SqlError>.Error<int, SqlError>(new SqlError("Transaction has no connection")); - - try - { - using (var command = new NpgsqlCommand(sql, (NpgsqlConnection)transaction.Connection!, (NpgsqlTransaction)transaction)) - { - command.Parameters.AddWithValue("@id", id ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@user_id", user_id ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@credential_id", credential_id ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@created_at", created_at ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@expires_at", expires_at ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@last_activity_at", last_activity_at ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@ip_address", ip_address ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@user_agent", user_agent ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@is_revoked", is_revoked ?? (object)DBNull.Value); - - var rowsAffected = await command.ExecuteNonQueryAsync().ConfigureAwait(false); - return new Result<int, SqlError>.Ok<int, SqlError>(rowsAffected); - } - } - catch (Exception ex) - { - return new Result<int, SqlError>.Error<int, SqlError>(new SqlError("Update failed", ex)); - } - } - - } -} diff --git a/Gatekeeper/Gatekeeper.Api/Generated/gk_userOperations.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/gk_userOperations.g.cs deleted file mode 100644 index e3980c4..0000000 --- a/Gatekeeper/Gatekeeper.Api/Generated/gk_userOperations.g.cs +++ /dev/null @@ -1,53 +0,0 @@ -#nullable enable -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Data; -using System.Globalization; -using System.Threading.Tasks; -using Npgsql; -using Outcome; -using Nimblesite.Sql.Model; - -namespace Generated -{ - /// <summary> - /// Extension methods for table operations on gk_user - /// </summary> - public static partial class gk_userExtensions - { - - /// <summary> - /// Inserts a new row into the gk_user table. - /// </summary> - public static async Task<Result<int, SqlError>> Insertgk_userAsync(this IDbTransaction transaction, string? id, string? display_name, string? email, string? created_at, string? last_login_at, bool? is_active, string? metadata) - { - const string sql = "INSERT INTO gk_user (id, display_name, email, created_at, last_login_at, is_active, metadata) VALUES (@id, @display_name, @email, @created_at, @last_login_at, @is_active, @metadata)"; - - if (transaction.Connection is null) - return new Result<int, SqlError>.Error<int, SqlError>(new SqlError("Transaction has no connection")); - - try - { - using (var command = new NpgsqlCommand(sql, (NpgsqlConnection)transaction.Connection!, (NpgsqlTransaction)transaction)) - { - command.Parameters.AddWithValue("@id", id ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@display_name", display_name ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@email", email ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@created_at", created_at ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@last_login_at", last_login_at ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@is_active", is_active ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@metadata", metadata ?? (object)DBNull.Value); - - var rowsAffected = await command.ExecuteNonQueryAsync().ConfigureAwait(false); - return new Result<int, SqlError>.Ok<int, SqlError>(rowsAffected); - } - } - catch (Exception ex) - { - return new Result<int, SqlError>.Error<int, SqlError>(new SqlError("Insert failed", ex)); - } - } - - } -} diff --git a/Gatekeeper/Gatekeeper.Api/Generated/gk_user_roleOperations.g.cs b/Gatekeeper/Gatekeeper.Api/Generated/gk_user_roleOperations.g.cs deleted file mode 100644 index 044e4a4..0000000 --- a/Gatekeeper/Gatekeeper.Api/Generated/gk_user_roleOperations.g.cs +++ /dev/null @@ -1,51 +0,0 @@ -#nullable enable -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Data; -using System.Globalization; -using System.Threading.Tasks; -using Npgsql; -using Outcome; -using Nimblesite.Sql.Model; - -namespace Generated -{ - /// <summary> - /// Extension methods for table operations on gk_user_role - /// </summary> - public static partial class gk_user_roleExtensions - { - - /// <summary> - /// Inserts a new row into the gk_user_role table. - /// </summary> - public static async Task<Result<int, SqlError>> Insertgk_user_roleAsync(this IDbTransaction transaction, string? user_id, string? role_id, string? granted_at, string? granted_by, string? expires_at) - { - const string sql = "INSERT INTO gk_user_role (user_id, role_id, granted_at, granted_by, expires_at) VALUES (@user_id, @role_id, @granted_at, @granted_by, @expires_at)"; - - if (transaction.Connection is null) - return new Result<int, SqlError>.Error<int, SqlError>(new SqlError("Transaction has no connection")); - - try - { - using (var command = new NpgsqlCommand(sql, (NpgsqlConnection)transaction.Connection!, (NpgsqlTransaction)transaction)) - { - command.Parameters.AddWithValue("@user_id", user_id ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@role_id", role_id ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@granted_at", granted_at ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@granted_by", granted_by ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@expires_at", expires_at ?? (object)DBNull.Value); - - var rowsAffected = await command.ExecuteNonQueryAsync().ConfigureAwait(false); - return new Result<int, SqlError>.Ok<int, SqlError>(rowsAffected); - } - } - catch (Exception ex) - { - return new Result<int, SqlError>.Error<int, SqlError>(new SqlError("Insert failed", ex)); - } - } - - } -} diff --git a/docs/plans/delete-generated-files-and-postgres-codegen.md b/docs/plans/delete-generated-files-and-postgres-codegen.md new file mode 100644 index 0000000..8b306ea --- /dev/null +++ b/docs/plans/delete-generated-files-and-postgres-codegen.md @@ -0,0 +1,286 @@ +# Plan: Delete Committed Generated Code & Switch to Postgres-Based Generation + +DataProvider reference code here: +/Users/christianfindlay/Documents/Code/ai_cms + +## Context + +Generated `.g.cs` files are currently committed to git in three of four API projects (Clinical, Scheduling, Gatekeeper). The fourth (ICD10) already excludes them via a per-folder `.gitignore`. This causes constant noise: + +- The current uncommitted modification to `Gatekeeper/Gatekeeper.Api/Generated/CheckResourceGrant.g.cs` shows only the **order of parameters** changed between two runs of the generator. Output is non-deterministic across machines/runs. +- Worse, the current generator (`dataprovider-sqlite`) reads schema from a local SQLite mirror created from YAML by `migration-cli --provider sqlite`. SQLite has no real type system, so every generated column comes back as `string`. Look at `CheckResourceGrant.g.cs` lines 102–126: `id`, `granted_at`, `expires_at`, `permission_id` are all `string` when they should be `Guid` / `DateTimeOffset`. This is a latent runtime bug in addition to the file-churn problem. +- The MSBuild target uses `IgnoreExitCode="true"` on the codegen step, so silent generation failures get masked and someone could be tempted to hand-edit the resulting stale files. + +The goal: **all four projects must regenerate their data-access code from a live Postgres database on every build**, the generated files must never be committed, and there must never be any need to manually edit generated code. Build/test/CI must spin up the Postgres container before invoking the generators. + +--- + +## Recommended Approach (Summary) + +1. Switch all four projects from `dataprovider-sqlite` to `dataprovider-postgres` for accurate type introspection. +2. Move the migration step from inside each `.csproj` to a single `make db-migrate` target that applies YAML schemas to the live Postgres via `migration-cli --provider postgres`. +3. Add `make db-up` / `make db-down` targets that start/stop the Postgres container via `docker compose`. Make `db-up` a hard prerequisite of `make build`, `make test`, `make ci`. The MSBuild codegen target stays inside each `.csproj` so IDE rebuilds also regenerate, but it now expects Postgres to be reachable and **fails loudly** if it isn't (no more `IgnoreExitCode`). +4. Update the GitHub Actions workflow to use the same `make db-up && make db-migrate` flow instead of the inline `services:` Postgres block, so local and CI run the identical pipeline. +5. Delete tracked `Generated/` files from git, add a single root `**/Generated/` ignore rule, and consolidate the per-folder ICD10 ignores. + +--- + +## Critical Files + +| Path | Change | +| --- | --- | +| `.gitignore` (root) | Add `**/Generated/`, `*.generated.sql`, `*.db` | +| `ICD10/.gitignore` | Remove now-redundant lines (`Generated/`, `*.generated.sql`, `*.db`) | +| `.config/dotnet-tools.json` | Add `nimblesite.dataprovider.postgres.cli` (replaces sqlite version for codegen) | +| `Makefile` | Add `db-up`, `db-down`, `db-reset`, `db-migrate` targets; make `build`/`test`/`ci` depend on them | +| `docker/docker-compose.db.yml` (NEW) | Stripped-down compose with only the `db` service for use during build | +| `Clinical/Clinical.Api/Clinical.Api.csproj` | Switch Exec to `dataprovider-postgres`, remove `migration-cli` Target, remove `IgnoreExitCode` | +| `Scheduling/Scheduling.Api/Scheduling.Api.csproj` | Same | +| `Gatekeeper/Gatekeeper.Api/Gatekeeper.Api.csproj` | Same | +| `ICD10/ICD10.Api/ICD10.Api.csproj` | Same | +| `Clinical/Clinical.Api/DataProvider.json` | Update `connectionString` to Postgres; change `tables[].schema` from `main` to `public` | +| `Scheduling/Scheduling.Api/DataProvider.json` | Same | +| `Gatekeeper/Gatekeeper.Api/DataProvider.json` | Same | +| `ICD10/ICD10.Api/DataProvider.json` | Same | +| `.github/workflows/ci.yml` | Remove `services.postgres` block; add `make db-up` step before lint/test/build | + +--- + +## Step-by-Step Plan + +### Step 1 — Add `dataprovider-postgres` to dotnet tools + +Edit `.config/dotnet-tools.json` and add an entry alongside the existing tools: + +```json +"nimblesite.dataprovider.postgres.cli": { + "version": "0.2.0-beta", + "commands": ["dataprovider-postgres"], + "rollForward": false +} +``` + +Keep `nimblesite.dataprovider.sqlite.cli` for now (ICD10 may still use it temporarily — see Step 8). + +### Step 2 — Create a build-only docker compose file + +Create `docker/docker-compose.db.yml` containing only the `db` service from the existing `docker/docker-compose.yml` (lines 2–16). This is the file `make db-up` will invoke. Reuses the existing init scripts in `docker/init-db/` which create the four databases (`gatekeeper`, `clinical`, `scheduling`, `icd10`) and roles. + +### Step 3 — Add Makefile targets + +Insert into [Makefile](Makefile) after the existing `setup` target: + +```make +# ============================================================================= +# DATABASE LIFECYCLE (required for code generation + tests) +# ============================================================================= + +DB_COMPOSE := docker compose -f docker/docker-compose.db.yml +DB_PASSWORD ?= changeme + +## db-up: Start Postgres container and wait until healthy +db-up: + @echo "==> Starting Postgres..." + @$(DB_COMPOSE) up -d + @echo "==> Waiting for Postgres to become healthy..." + @for i in $$(seq 1 30); do \ + if $(DB_COMPOSE) exec -T db pg_isready -U postgres >/dev/null 2>&1; then \ + echo "Postgres ready."; exit 0; \ + fi; sleep 1; \ + done; \ + echo "FAIL: Postgres never became healthy"; $(DB_COMPOSE) logs db; exit 1 + +## db-down: Stop Postgres container (preserves volume) +db-down: + @echo "==> Stopping Postgres..." + @$(DB_COMPOSE) down + +## db-reset: Drop volume and restart Postgres clean +db-reset: + @echo "==> Resetting Postgres (DROP volumes)..." + @$(DB_COMPOSE) down -v + @$(MAKE) db-up + @$(MAKE) db-migrate + +## db-migrate: Apply YAML schemas to live Postgres for all four databases +db-migrate: db-up + @echo "==> Applying schemas..." + dotnet migration-cli --schema Gatekeeper/Gatekeeper.Api/gatekeeper-schema.yaml \ + --output "Host=localhost;Database=gatekeeper;Username=gatekeeper;Password=$(DB_PASSWORD)" \ + --provider postgres + dotnet migration-cli --schema Clinical/Clinical.Api/clinical-schema.yaml \ + --output "Host=localhost;Database=clinical;Username=clinical;Password=$(DB_PASSWORD)" \ + --provider postgres + dotnet migration-cli --schema Scheduling/Scheduling.Api/scheduling-schema.yaml \ + --output "Host=localhost;Database=scheduling;Username=scheduling;Password=$(DB_PASSWORD)" \ + --provider postgres + dotnet migration-cli --schema ICD10/ICD10.Api/icd10-schema.yaml \ + --output "Host=localhost;Database=icd10;Username=icd10;Password=$(DB_PASSWORD)" \ + --provider postgres +``` + +Then change the existing primary targets so they depend on a live, migrated database: + +```make +build: db-migrate + @echo "==> Building..." + dotnet build HealthcareSamples.sln --configuration Release + +test: db-migrate + @echo "==> Testing..." + dotnet test ... + +lint: fmt-check db-migrate + @echo "==> Linting..." + dotnet build HealthcareSamples.sln --configuration Release +``` + +`db-migrate` itself depends on `db-up`, so the chain `make ci → lint → db-migrate → db-up` guarantees the container is started before any `dotnet` invocation. Add `db-up`, `db-down`, `db-reset`, `db-migrate` to the `.PHONY` list and to the `help` target. + +### Step 4 — Update each `DataProvider.json` for Postgres + +For all four files (`Clinical/Clinical.Api/DataProvider.json`, `Scheduling/Scheduling.Api/DataProvider.json`, `Gatekeeper/Gatekeeper.Api/DataProvider.json`, `ICD10/ICD10.Api/DataProvider.json`): + +1. Replace the `connectionString` field. Example for Gatekeeper: + ```json + "connectionString": "Host=localhost;Database=gatekeeper;Username=gatekeeper;Password=changeme" + ``` + This is a **dev/codegen-only** connection string. Runtime uses `appsettings.json` / env vars and is unaffected. The plaintext `changeme` here is acceptable because the same default already lives in `docker/docker-compose.yml` line 24 and `.github/workflows/ci.yml` line 24. + +2. Change every `"schema": "main"` to `"schema": "public"`. SQLite's default schema is `main`; Postgres's is `public`. + +### Step 5 — Update each API `.csproj` + +For each of the four API csproj files, apply these changes (example shown for `Gatekeeper.Api.csproj`; the same pattern applies to the others — just delete the `CreateDatabaseSchema` Target since migrations now run via `make db-migrate`): + +**Delete** the `CreateDatabaseSchema` Target entirely (lines 33–40 in Gatekeeper, equivalent lines in the others). Migrations are now a Makefile concern. + +**Replace** the body of `TranspileLqlAndGenerateDataProvider`: + +```xml +<Target + Name="TranspileLqlAndGenerateDataProvider" + BeforeTargets="BeforeCompile;CoreCompile" + Inputs="$(MSBuildProjectDirectory)/DataProvider.json;@(AdditionalFiles);@(LqlFiles)" + Outputs="$(MSBuildProjectDirectory)/Generated/.timestamp" +> + <RemoveDir Directories="$(MSBuildProjectDirectory)/Generated" /> + <MakeDir Directories="$(MSBuildProjectDirectory)/Generated" /> + <ItemGroup> + <LqlFiles Include="$(MSBuildProjectDirectory)/**/*.lql" /> + </ItemGroup> + <Exec + Command="dotnet lqlcli-sqlite --input "%(LqlFiles.Identity)" --output "%(LqlFiles.RootDir)%(LqlFiles.Directory)%(LqlFiles.Filename).generated.sql"" + Condition="'$(EnableLqlTranspile)' == 'true' and @(LqlFiles) != ''" + WorkingDirectory="$(MSBuildProjectDirectory)" /> + <Exec + Command="dotnet dataprovider-postgres --project-dir "$(MSBuildProjectDirectory)" --config "$(MSBuildProjectDirectory)/DataProvider.json" --out "$(MSBuildProjectDirectory)/Generated"" + WorkingDirectory="$(MSBuildProjectDirectory)" + StandardOutputImportance="High" + StandardErrorImportance="High" /> + <Touch Files="$(MSBuildProjectDirectory)/Generated/.timestamp" AlwaysCreate="true" /> + <ItemGroup> + <Compile Include="$(MSBuildProjectDirectory)/Generated/**/*.g.cs" /> + </ItemGroup> +</Target> +``` + +Notable diffs from the current target: + +- `dataprovider-sqlite` → `dataprovider-postgres` +- `--connection-type NpgsqlConnection` flag removed (the postgres tool always emits Npgsql code) +- **`IgnoreExitCode="true"` removed** from the codegen step. If Postgres is unreachable, generation fails, and so does the build. This is the enforcement mechanism for "code must always be generated, never hand-edited". +- `ContinueOnError="WarnAndContinue"` removed from the LQL transpile step for the same reason. + +The `<Compile Remove="Generated/**" />` ItemGroup at the top of each csproj stays unchanged. + +### Step 6 — Delete tracked Generated files and update gitignore + +```bash +git rm -r --cached Clinical/Clinical.Api/Generated +git rm -r --cached Scheduling/Scheduling.Api/Generated +git rm -r --cached Gatekeeper/Gatekeeper.Api/Generated +``` + +ICD10 has zero tracked `Generated/` files (verified via `git ls-files`); skip it. + +Edit [.gitignore](.gitignore) and add to the C#/.NET section after line 70 (`obj/`): + +```gitignore +# Generated code (regenerated at build time by TranspileLqlAndGenerateDataProvider) +**/Generated/ +# LQL transpile output +*.generated.sql +# SQLite databases (legacy from previous codegen approach; safe to keep ignored) +*.db +``` + +Edit [ICD10/.gitignore](ICD10/.gitignore) and **delete** lines 1–4 (`# Generated files`, `*.generated.sql`, `*.db`, `Generated/`) — they are now redundant. Leave the Python and IDE sections alone. + +### Step 7 — Update the GitHub Actions workflow + +In [.github/workflows/ci.yml](.github/workflows/ci.yml): + +1. **Delete** the `services.postgres` block (lines 19–31). CI will now use the same `docker compose` flow as local dev via `make db-up`. +2. **Insert** a new step right after `dotnet tool restore` (between current line 59 and line 61): + ```yaml + - name: Start database + run: make db-up + - name: Apply schemas + run: make db-migrate + ``` +3. The existing `Lint` / `Test` / `Build` steps already invoke `make`, and those targets now depend on `db-migrate` (which depends on `db-up`), so even if the explicit steps above were removed the chain would still work. We add them explicitly for clarity in the CI log and to fail fast at a recognizable step name. +4. The embedding-service step at lines 42–56 stays as-is — it's unrelated. +5. Move the `Build` step (currently at line 88, the LAST step) to be the FIRST `make` invocation, BEFORE `Lint`, `Test`, `Coverage check`. Right now `make build` runs after `make test`, which is backwards: tests can't run if the build is broken, so build must come first. Order should be: db-up → db-migrate → build → lint → test → coverage-check → upload. + +### Step 8 — Decide ICD10's fate + +ICD10's codegen currently uses the SQLite path *and* references `EnableLqlTranspile=true` for `.lql` files. After this plan, ICD10 must also use `dataprovider-postgres`. Apply the same `.csproj` and `DataProvider.json` changes as the other three. This means the ICD10 SQLite-mirror approach goes away entirely. Verify that no test or runtime code depends on the on-disk `icd10.db` SQLite file (`<Content Include="icd10.db" Condition="Exists('icd10.db')">` in the csproj — that line should also be deleted, since the runtime is Postgres). Once ICD10 is migrated, `nimblesite.dataprovider.sqlite.cli` and `nimblesite.lql.cli.sqlite` can be reviewed for removal from `.config/dotnet-tools.json` (out of scope for this plan if anything still depends on them). + +--- + +## Verification + +1. **Local fresh-clone smoke test:** + ```bash + make clean + make db-reset # drops volume, starts Postgres clean, applies all schemas + make ci # lint + test + build, all from a clean slate + git status # MUST be clean — no Generated/ files showing up + ``` + Expected: every project regenerates its `Generated/*.g.cs` files from the live Postgres schema, all tests pass, working tree is clean. + +2. **Type-correctness spot check:** Open `Gatekeeper/Gatekeeper.Api/Generated/CheckResourceGrant.g.cs` after a successful build. The columns `id`, `permission_id`, `granted_at`, `expires_at` should now be `Guid` and `DateTimeOffset`, NOT `string`. This is the proof that Postgres-based introspection is wired up correctly. + +3. **Failure mode check:** + ```bash + make db-down + dotnet build Gatekeeper/Gatekeeper.Api/Gatekeeper.Api.csproj + ``` + Expected: build FAILS with a clear error from `dataprovider-postgres` saying it cannot connect. This verifies that `IgnoreExitCode` removal works — generation failures are now loud. + +4. **Re-build idempotency:** + ```bash + make build + make build + git status + ``` + Expected: clean working tree after both builds. (Note: even if the Nimblesite generator's output ordering is non-deterministic upstream, this no longer matters because the files are gitignored. See Concern (a).) + +5. **CI verification:** Push the branch and confirm the GitHub Actions run goes through the steps in this order: `Start database` → `Apply schemas` → `Build` → `Lint` → `Test` → `Coverage check`. All green. + +--- + +## Concerns / Follow-ups (out of scope but worth tracking) + +**(a) Non-deterministic generator output.** The `CheckResourceGrant.g.cs` parameter-order drift you observed comes from dictionary iteration order in `dataprovider-sqlite`. After this plan it stops mattering for git but should still be filed against `/Users/christianfindlay/Documents/Code/gigs/DataProvider` so future debugging diffs across machines stay quiet. Fix: sort keys with `StringComparer.Ordinal` before emitting parameter lists. + +**(b) Connection string secrecy.** `DataProvider.json` will contain `Password=changeme` in plaintext. Acceptable because (i) it's a dev-only password matching `docker-compose.yml` and CI defaults, (ii) the file is committed in source already, (iii) production runtime uses `appsettings.json` / env vars and is unaffected. If a real password ever appears here, it's a process failure regardless of file format. Optional follow-up: support `${DB_PASSWORD}` env var substitution in `DataProvider.json` upstream. + +**(c) MSBuild target re-runs every build.** The current target's `<RemoveDir>` deletes `.timestamp` immediately, so the `Inputs`/`Outputs` incremental check always sees outputs as missing and re-runs. This is wasteful but pre-existing; not changed by this plan. Follow-up: drop `RemoveDir`/`MakeDir` and let `dataprovider-postgres` overwrite in place, so MSBuild's incremental check actually works. + +**(d) `make lint` runs `csharpier check`.** Once generated files are produced fresh on every build, csharpier may flag them. Either (i) the generator must emit csharpier-clean output, or (ii) add `Generated/` to `.csharpierignore`. Recommend (ii) — generated code should never be linted. + +**(e) ICD10 SQLite leftovers.** Once Step 8 lands, the `*.db` files (`icd10.db`, `clinical.db`, `scheduling.db`, `gatekeeper.db`) and `*.generated.sql` files left over from prior builds become orphans. `make clean` should be extended to remove them, or they should be deleted from any working trees as a one-time cleanup. + +**(f) `dataprovider-postgres` argument set.** Confirmed via DataProvider source at `/Users/christianfindlay/Documents/Code/gigs/DataProvider/DataProvider/DataProvider.Postgres.Cli`: it accepts `--project-dir`, `--config`, `--out` and reads the connection string from `DataProvider.json`. No `--connection-string` flag exists, which is why we put the connection string in the JSON. From 0e72d78a23e009bf9a925a5804349e68fdfcc8a1 Mon Sep 17 00:00:00 2001 From: Christian Findlay <16697547+MelbourneDeveloper@users.noreply.github.com> Date: Wed, 8 Apr 2026 08:04:56 +1000 Subject: [PATCH 09/59] Delete generated files --- .config/dotnet-tools.json | 16 +- .github/workflows/ci.yml | 22 +- .gitignore | 14 + Clinical/Clinical.Api/Clinical.Api.csproj | 23 +- Clinical/Clinical.Api/DataProvider.json | 136 ++++----- Clinical/Clinical.Api/Generated/.timestamp | 0 .../Generated/GetConditionsByPatient.g.cs | 163 ---------- .../Generated/GetEncountersByPatient.g.cs | 139 --------- .../Generated/GetMedicationsByPatient.g.cs | 157 ---------- .../Generated/GetPatientById.g.cs | 157 ---------- .../Clinical.Api/Generated/GetPatients.g.cs | 172 ----------- .../Generated/SearchPatients.g.cs | 157 ---------- .../Generated/fhir_ConditionOperations.g.cs | 62 ---- .../Generated/fhir_EncounterOperations.g.cs | 58 ---- .../fhir_MedicationRequestOperations.g.cs | 61 ---- .../Generated/fhir_PatientOperations.g.cs | 102 ------- Clinical/Clinical.Api/GlobalUsings.cs | 8 +- Clinical/Clinical.Api/Program.cs | 44 ++- .../GetConditionsByPatient.generated.sql | 1 - .../GetEncountersByPatient.generated.sql | 1 - .../GetMedicationsByPatient.generated.sql | 1 - .../Queries/GetPatientById.generated.sql | 1 - .../Queries/GetPatients.generated.sql | 1 - .../Queries/SearchPatients.generated.sql | 1 - Directory.Build.props | 2 +- .../AuthorizationTests.cs | 2 +- .../Gatekeeper.Api/AuthorizationService.cs | 14 +- Gatekeeper/Gatekeeper.Api/DataProvider.json | 20 +- .../Gatekeeper.Api/Gatekeeper.Api.csproj | 20 +- .../Gatekeeper.Api/Generated/.timestamp | 0 Gatekeeper/Gatekeeper.Api/Program.cs | 33 ++- .../Gatekeeper.Api/Sql/CheckPermission.sql | 2 +- .../Gatekeeper.Api/Sql/CheckResourceGrant.sql | 2 +- .../Gatekeeper.Api/Sql/CountSystemRoles.sql | 2 +- .../Gatekeeper.Api/Sql/GetActivePolicies.sql | 2 +- .../Gatekeeper.Api/Sql/GetAllPermissions.sql | 2 +- Gatekeeper/Gatekeeper.Api/Sql/GetAllRoles.sql | 2 +- Gatekeeper/Gatekeeper.Api/Sql/GetAllUsers.sql | 2 +- .../Gatekeeper.Api/Sql/GetChallengeById.sql | 2 +- .../Gatekeeper.Api/Sql/GetCredentialById.sql | 2 +- .../Sql/GetCredentialsByUserId.sql | 2 +- .../Sql/GetPermissionByCode.sql | 2 +- .../Gatekeeper.Api/Sql/GetRolePermissions.sql | 2 +- .../Gatekeeper.Api/Sql/GetSessionById.sql | 2 +- .../Sql/GetSessionForRevoke.sql | 2 +- .../Gatekeeper.Api/Sql/GetSessionRevoked.sql | 2 +- .../Gatekeeper.Api/Sql/GetUserByEmail.sql | 2 +- Gatekeeper/Gatekeeper.Api/Sql/GetUserById.sql | 2 +- .../Gatekeeper.Api/Sql/GetUserCredentials.sql | 2 +- .../Gatekeeper.Api/Sql/GetUserPermissions.sql | 2 +- .../Gatekeeper.Api/Sql/GetUserRoles.sql | 2 +- .../Gatekeeper.Api/Sql/RevokeSession.sql | 2 +- ICD10/.gitignore | 5 - ICD10/ICD10.Api/DataProvider.json | 279 +++++++++--------- ICD10/ICD10.Api/ICD10.Api.csproj | 27 +- ICD10/ICD10.Api/Program.cs | 6 +- ICD10/ICD10.Api/Queries/SearchAchiCodes.sql | 6 +- ICD10/ICD10.Api/Queries/SearchIcd10Codes.sql | 20 +- Makefile | 63 +++- Scheduling/Scheduling.Api/DataProvider.json | 146 ++++----- .../Scheduling.Api/Generated/.timestamp | 0 .../Generated/CheckSchedulingConflicts.g.cs | 101 ------- .../Generated/GetAllPractitioners.g.cs | 116 -------- .../Generated/GetAppointmentById.g.cs | 151 ---------- .../Generated/GetAppointmentsByPatient.g.cs | 151 ---------- .../GetAppointmentsByPractitioner.g.cs | 151 ---------- .../Generated/GetAppointmentsByStatus.g.cs | 131 -------- .../Generated/GetAvailableSlots.g.cs | 107 ------- .../Generated/GetPractitionerById.g.cs | 121 -------- .../Generated/GetProviderAvailability.g.cs | 103 ------- .../Generated/GetProviderDailySchedule.g.cs | 161 ---------- .../Generated/GetUpcomingAppointments.g.cs | 146 --------- .../SearchPractitionersBySpecialty.g.cs | 121 -------- .../Generated/fhir_AppointmentOperations.g.cs | 60 ---- .../fhir_PractitionerOperations.g.cs | 55 ---- Scheduling/Scheduling.Api/GlobalUsings.cs | 8 +- Scheduling/Scheduling.Api/Program.cs | 2 +- .../CheckSchedulingConflicts.generated.sql | 1 - .../Queries/GetAllPractitioners.generated.sql | 1 - .../Queries/GetAppointmentById.generated.sql | 1 - .../GetAppointmentsByPatient.generated.sql | 1 - ...etAppointmentsByPractitioner.generated.sql | 1 - .../GetAppointmentsByStatus.generated.sql | 1 - .../Queries/GetAvailableSlots.generated.sql | 1 - .../Queries/GetPractitionerById.generated.sql | 1 - .../GetProviderAvailability.generated.sql | 1 - .../GetProviderDailySchedule.generated.sql | 1 - .../GetUpcomingAppointments.generated.sql | 1 - ...archPractitionersBySpecialty.generated.sql | 1 - .../Scheduling.Api/Scheduling.Api.csproj | 23 +- docker/docker-compose.db.yml | 20 ++ ...te-generated-files-and-postgres-codegen.md | 12 + 92 files changed, 542 insertions(+), 3392 deletions(-) delete mode 100644 Clinical/Clinical.Api/Generated/.timestamp delete mode 100644 Clinical/Clinical.Api/Generated/GetConditionsByPatient.g.cs delete mode 100644 Clinical/Clinical.Api/Generated/GetEncountersByPatient.g.cs delete mode 100644 Clinical/Clinical.Api/Generated/GetMedicationsByPatient.g.cs delete mode 100644 Clinical/Clinical.Api/Generated/GetPatientById.g.cs delete mode 100644 Clinical/Clinical.Api/Generated/GetPatients.g.cs delete mode 100644 Clinical/Clinical.Api/Generated/SearchPatients.g.cs delete mode 100644 Clinical/Clinical.Api/Generated/fhir_ConditionOperations.g.cs delete mode 100644 Clinical/Clinical.Api/Generated/fhir_EncounterOperations.g.cs delete mode 100644 Clinical/Clinical.Api/Generated/fhir_MedicationRequestOperations.g.cs delete mode 100644 Clinical/Clinical.Api/Generated/fhir_PatientOperations.g.cs delete mode 100644 Clinical/Clinical.Api/Queries/GetConditionsByPatient.generated.sql delete mode 100644 Clinical/Clinical.Api/Queries/GetEncountersByPatient.generated.sql delete mode 100644 Clinical/Clinical.Api/Queries/GetMedicationsByPatient.generated.sql delete mode 100644 Clinical/Clinical.Api/Queries/GetPatientById.generated.sql delete mode 100644 Clinical/Clinical.Api/Queries/GetPatients.generated.sql delete mode 100644 Clinical/Clinical.Api/Queries/SearchPatients.generated.sql delete mode 100644 Gatekeeper/Gatekeeper.Api/Generated/.timestamp delete mode 100644 Scheduling/Scheduling.Api/Generated/.timestamp delete mode 100644 Scheduling/Scheduling.Api/Generated/CheckSchedulingConflicts.g.cs delete mode 100644 Scheduling/Scheduling.Api/Generated/GetAllPractitioners.g.cs delete mode 100644 Scheduling/Scheduling.Api/Generated/GetAppointmentById.g.cs delete mode 100644 Scheduling/Scheduling.Api/Generated/GetAppointmentsByPatient.g.cs delete mode 100644 Scheduling/Scheduling.Api/Generated/GetAppointmentsByPractitioner.g.cs delete mode 100644 Scheduling/Scheduling.Api/Generated/GetAppointmentsByStatus.g.cs delete mode 100644 Scheduling/Scheduling.Api/Generated/GetAvailableSlots.g.cs delete mode 100644 Scheduling/Scheduling.Api/Generated/GetPractitionerById.g.cs delete mode 100644 Scheduling/Scheduling.Api/Generated/GetProviderAvailability.g.cs delete mode 100644 Scheduling/Scheduling.Api/Generated/GetProviderDailySchedule.g.cs delete mode 100644 Scheduling/Scheduling.Api/Generated/GetUpcomingAppointments.g.cs delete mode 100644 Scheduling/Scheduling.Api/Generated/SearchPractitionersBySpecialty.g.cs delete mode 100644 Scheduling/Scheduling.Api/Generated/fhir_AppointmentOperations.g.cs delete mode 100644 Scheduling/Scheduling.Api/Generated/fhir_PractitionerOperations.g.cs delete mode 100644 Scheduling/Scheduling.Api/Queries/CheckSchedulingConflicts.generated.sql delete mode 100644 Scheduling/Scheduling.Api/Queries/GetAllPractitioners.generated.sql delete mode 100644 Scheduling/Scheduling.Api/Queries/GetAppointmentById.generated.sql delete mode 100644 Scheduling/Scheduling.Api/Queries/GetAppointmentsByPatient.generated.sql delete mode 100644 Scheduling/Scheduling.Api/Queries/GetAppointmentsByPractitioner.generated.sql delete mode 100644 Scheduling/Scheduling.Api/Queries/GetAppointmentsByStatus.generated.sql delete mode 100644 Scheduling/Scheduling.Api/Queries/GetAvailableSlots.generated.sql delete mode 100644 Scheduling/Scheduling.Api/Queries/GetPractitionerById.generated.sql delete mode 100644 Scheduling/Scheduling.Api/Queries/GetProviderAvailability.generated.sql delete mode 100644 Scheduling/Scheduling.Api/Queries/GetProviderDailySchedule.generated.sql delete mode 100644 Scheduling/Scheduling.Api/Queries/GetUpcomingAppointments.generated.sql delete mode 100644 Scheduling/Scheduling.Api/Queries/SearchPractitionersBySpecialty.generated.sql create mode 100644 docker/docker-compose.db.yml diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index f5967de..bbdf98c 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -10,7 +10,7 @@ "rollForward": false }, "nimblesite.dataprovider.migration.cli": { - "version": "0.2.0-beta", + "version": "0.2.2-beta", "commands": [ "migration-cli" ], @@ -23,6 +23,13 @@ ], "rollForward": false }, + "nimblesite.lql.cli.postgres": { + "version": "0.1.8-beta", + "commands": [ + "lql-postgres" + ], + "rollForward": false + }, "nimblesite.dataprovider.sqlite.cli": { "version": "0.2.0-beta", "commands": [ @@ -30,6 +37,13 @@ ], "rollForward": false }, + "nimblesite.dataprovider.postgres.cli": { + "version": "0.2.7-beta", + "commands": [ + "dataprovider-postgres" + ], + "rollForward": false + }, "h5-compiler": { "version": "26.3.64893", "commands": [ diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 30c4bb6..e5a3bac 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,22 +16,10 @@ jobs: name: CI runs-on: ubuntu-latest timeout-minutes: 30 - services: - postgres: - image: pgvector/pgvector:pg16 - env: - POSTGRES_USER: postgres - POSTGRES_PASSWORD: changeme - ports: - - 5432:5432 - options: >- - --health-cmd "pg_isready -U postgres" - --health-interval 5s - --health-timeout 3s - --health-retries 10 env: + DB_PASSWORD: changeme TEST_POSTGRES_CONNECTION: Host=localhost;Database=postgres;Username=postgres;Password=changeme - ICD10_TEST_CONNECTION_STRING: Host=localhost;Database=postgres;Username=postgres;Password=changeme + ICD10_TEST_CONNECTION_STRING: Host=localhost;Database=icd10;Username=postgres;Password=changeme steps: - uses: actions/checkout@v4 @@ -39,6 +27,9 @@ jobs: with: dotnet-version: '10.0.x' + - name: Start Postgres (pgvector) via docker compose + run: make db-up + - name: Start embedding service run: | cd ICD10/embedding-service @@ -58,6 +49,9 @@ jobs: - run: dotnet restore - run: dotnet tool restore + - name: Migrate Postgres schemas + run: make db-migrate + - name: Install Playwright browsers run: | dotnet build Dashboard/Dashboard.Integration.Tests/Dashboard.Integration.Tests.csproj --configuration Release diff --git a/.gitignore b/.gitignore index cf4417e..1a4e4c2 100644 --- a/.gitignore +++ b/.gitignore @@ -71,6 +71,16 @@ obj/ out/ publish/ artifacts/ + +# DataProvider codegen output (regenerated each build by `dataprovider-postgres`) +**/Generated/ +**/Generated/**/*.g.cs +**/Generated/.timestamp +**/*.generated.sql +# Local SQLite databases (no longer used; project is on Postgres) +*.db +*.db-shm +*.db-wal *.user *.userosscache *.suo @@ -85,3 +95,7 @@ project.lock.json !**/packages/repositories.config *.TargetFrameworkMonikers *.dotCover + + +*.nupkg +*.generated.sql \ No newline at end of file diff --git a/Clinical/Clinical.Api/Clinical.Api.csproj b/Clinical/Clinical.Api/Clinical.Api.csproj index 36a37cf..d033082 100644 --- a/Clinical/Clinical.Api/Clinical.Api.csproj +++ b/Clinical/Clinical.Api/Clinical.Api.csproj @@ -1,7 +1,7 @@ <Project Sdk="Microsoft.NET.Sdk.Web"> <PropertyGroup> <OutputType>Exe</OutputType> - <NoWarn>CA1515;CA2100;RS1035;CA1508;CA2234</NoWarn> + <NoWarn>$(NoWarn);CA1515;CA2100;RS1035;CA1508;CA2234;CS1591</NoWarn> <EnableLqlTranspile>true</EnableLqlTranspile> </PropertyGroup> @@ -33,19 +33,10 @@ </Content> </ItemGroup> - <!-- Create database from YAML using Migration.Cli (installed as dotnet tool) --> - <Target Name="CreateDatabaseSchema" BeforeTargets="TranspileLqlAndGenerateDataProvider"> - <Exec - Command="dotnet migration-cli --schema "$(MSBuildProjectDirectory)/clinical-schema.yaml" --output "$(MSBuildProjectDirectory)/clinical.db" --provider sqlite" - WorkingDirectory="$(MSBuildProjectDirectory)" - StandardOutputImportance="High" - StandardErrorImportance="High" - /> - </Target> - - <!-- Pre-compile: transpile LQL to SQL, then generate C# from SQL using CLI tools --> + <!-- Pre-compile: transpile LQL to SQL, then generate C# via dataprovider-postgres CLI. + Requires a live Postgres with the clinical schema migrated (see `make db-migrate`). --> <Target - Name="TranspileLqlAndGenerateDataProvider" + Name="GenerateDataProvider" BeforeTargets="BeforeCompile;CoreCompile" Inputs="$(MSBuildProjectDirectory)/DataProvider.json;@(AdditionalFiles);@(LqlFiles)" Outputs="$(MSBuildProjectDirectory)/Generated/.timestamp" @@ -57,19 +48,17 @@ </ItemGroup> <Message Importance="High" Text="Transpiling LQL files (@(LqlFiles))" /> <Exec - Command="dotnet lqlcli-sqlite --input "%(LqlFiles.Identity)" --output "%(LqlFiles.RootDir)%(LqlFiles.Directory)%(LqlFiles.Filename).generated.sql"" + Command="dotnet lql-postgres --input "%(LqlFiles.Identity)" --output "%(LqlFiles.RootDir)%(LqlFiles.Directory)%(LqlFiles.Filename).generated.sql"" Condition="'$(EnableLqlTranspile)' == 'true' and @(LqlFiles) != ''" WorkingDirectory="$(MSBuildProjectDirectory)" StandardOutputImportance="High" StandardErrorImportance="High" - ContinueOnError="WarnAndContinue" /> <Exec - Command="dotnet dataprovider-sqlite --project-dir "$(MSBuildProjectDirectory)" --config "$(MSBuildProjectDirectory)/DataProvider.json" --out "$(MSBuildProjectDirectory)/Generated" --connection-type NpgsqlConnection" + Command="dotnet dataprovider-postgres --project-dir "$(MSBuildProjectDirectory)" --config "$(MSBuildProjectDirectory)/DataProvider.json" --out "$(MSBuildProjectDirectory)/Generated"" WorkingDirectory="$(MSBuildProjectDirectory)" StandardOutputImportance="High" StandardErrorImportance="High" - IgnoreExitCode="true" /> <Touch Files="$(MSBuildProjectDirectory)/Generated/.timestamp" AlwaysCreate="true" /> <ItemGroup> diff --git a/Clinical/Clinical.Api/DataProvider.json b/Clinical/Clinical.Api/DataProvider.json index 3c6fe7d..d746bdf 100644 --- a/Clinical/Clinical.Api/DataProvider.json +++ b/Clinical/Clinical.Api/DataProvider.json @@ -1,67 +1,71 @@ { - "queries": [ - { - "name": "GetPatients", - "sqlFile": "Queries/GetPatients.generated.sql" - }, - { - "name": "GetPatientById", - "sqlFile": "Queries/GetPatientById.generated.sql" - }, - { - "name": "SearchPatients", - "sqlFile": "Queries/SearchPatients.generated.sql" - }, - { - "name": "GetEncountersByPatient", - "sqlFile": "Queries/GetEncountersByPatient.generated.sql" - }, - { - "name": "GetConditionsByPatient", - "sqlFile": "Queries/GetConditionsByPatient.generated.sql" - }, - { - "name": "GetMedicationsByPatient", - "sqlFile": "Queries/GetMedicationsByPatient.generated.sql" - } - ], - "tables": [ - { - "schema": "main", - "name": "fhir_Patient", - "generateInsert": true, - "generateUpdate": true, - "generateDelete": true, - "excludeColumns": ["Id"], - "primaryKeyColumns": ["Id"] - }, - { - "schema": "main", - "name": "fhir_Encounter", - "generateInsert": true, - "generateUpdate": false, - "generateDelete": false, - "excludeColumns": ["Id"], - "primaryKeyColumns": ["Id"] - }, - { - "schema": "main", - "name": "fhir_Condition", - "generateInsert": true, - "generateUpdate": false, - "generateDelete": false, - "excludeColumns": ["Id"], - "primaryKeyColumns": ["Id"] - }, - { - "schema": "main", - "name": "fhir_MedicationRequest", - "generateInsert": true, - "generateUpdate": false, - "generateDelete": false, - "excludeColumns": ["Id"], - "primaryKeyColumns": ["Id"] - } - ], - "connectionString": "Data Source=clinical.db" -} + "queries": [ + { + "name": "GetPatients", + "sqlFile": "Queries/GetPatients.generated.sql" + }, + { + "name": "GetPatientById", + "sqlFile": "Queries/GetPatientById.generated.sql" + }, + { + "name": "SearchPatients", + "sqlFile": "Queries/SearchPatients.generated.sql" + }, + { + "name": "GetEncountersByPatient", + "sqlFile": "Queries/GetEncountersByPatient.generated.sql" + }, + { + "name": "GetConditionsByPatient", + "sqlFile": "Queries/GetConditionsByPatient.generated.sql" + }, + { + "name": "GetMedicationsByPatient", + "sqlFile": "Queries/GetMedicationsByPatient.generated.sql" + } + ], + "tables": [ + { + "schema": "public", + "name": "fhir_Patient", + "generateInsert": true, + "generateUpdate": true, + "generateDelete": true, + "primaryKeyColumns": [ + "Id" + ] + }, + { + "schema": "public", + "name": "fhir_Encounter", + "generateInsert": true, + "generateUpdate": false, + "generateDelete": false, + "primaryKeyColumns": [ + "Id" + ] + }, + { + "schema": "public", + "name": "fhir_Condition", + "generateInsert": true, + "generateUpdate": false, + "generateDelete": false, + "primaryKeyColumns": [ + "Id" + ] + }, + { + "schema": "public", + "name": "fhir_MedicationRequest", + "generateInsert": true, + "generateUpdate": false, + "generateDelete": false, + "primaryKeyColumns": [ + "Id" + ] + } + ], + "connectionString": "Host=localhost;Port=5432;Database=clinical;Username=postgres;Password=changeme" +} \ No newline at end of file diff --git a/Clinical/Clinical.Api/Generated/.timestamp b/Clinical/Clinical.Api/Generated/.timestamp deleted file mode 100644 index e69de29..0000000 diff --git a/Clinical/Clinical.Api/Generated/GetConditionsByPatient.g.cs b/Clinical/Clinical.Api/Generated/GetConditionsByPatient.g.cs deleted file mode 100644 index 05418c7..0000000 --- a/Clinical/Clinical.Api/Generated/GetConditionsByPatient.g.cs +++ /dev/null @@ -1,163 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Threading.Tasks; -using Npgsql; -using Outcome; -using Nimblesite.Sql.Model; - -namespace Generated; - -/// <summary> -/// Extension methods for 'GetConditionsByPatient'. -/// </summary> -public static partial class GetConditionsByPatientExtensions -{ - /// <summary> - /// Executes 'GetConditionsByPatient.sql' and maps results. - /// </summary> - /// <param name="connection">Open NpgsqlConnection connection.</param> - /// <param name="patientId">Query parameter.</param> - /// <returns>Result of records or SQL error.</returns> - public static async Task<Result<ImmutableList<GetConditionsByPatient>, SqlError>> GetConditionsByPatientAsync(this NpgsqlConnection connection, object patientId) - { - const string sql = @"SELECT fhir_Condition.Id, fhir_Condition.ClinicalStatus, fhir_Condition.VerificationStatus, fhir_Condition.Category, fhir_Condition.Severity, fhir_Condition.CodeSystem, fhir_Condition.CodeValue, fhir_Condition.CodeDisplay, fhir_Condition.SubjectReference, fhir_Condition.EncounterReference, fhir_Condition.OnsetDateTime, fhir_Condition.RecordedDate, fhir_Condition.RecorderReference, fhir_Condition.NoteText, fhir_Condition.LastUpdated, fhir_Condition.VersionId FROM fhir_Condition WHERE fhir_Condition.SubjectReference = @patientId ORDER BY fhir_Condition.RecordedDate DESC"; - - try - { - var results = ImmutableList.CreateBuilder<GetConditionsByPatient>(); - - using (var command = new NpgsqlCommand(sql, connection)) - { - if (patientId is not null and not DBNull) - command.Parameters.AddWithValue("@patientId", patientId); - else - command.Parameters.Add(new NpgsqlParameter("@patientId", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); - - using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false)) - { - while (await reader.ReadAsync().ConfigureAwait(false)) - { - var item = new GetConditionsByPatient( - reader.IsDBNull(0) ? null : reader.GetFieldValue<string>(0), - reader.IsDBNull(1) ? null : reader.GetFieldValue<string>(1), - reader.IsDBNull(2) ? null : reader.GetFieldValue<string>(2), - reader.IsDBNull(3) ? null : reader.GetFieldValue<string>(3), - reader.IsDBNull(4) ? null : reader.GetFieldValue<string>(4), - reader.IsDBNull(5) ? null : reader.GetFieldValue<string>(5), - reader.IsDBNull(6) ? null : reader.GetFieldValue<string>(6), - reader.IsDBNull(7) ? null : reader.GetFieldValue<string>(7), - reader.IsDBNull(8) ? null : reader.GetFieldValue<string>(8), - reader.IsDBNull(9) ? null : reader.GetFieldValue<string>(9), - reader.IsDBNull(10) ? null : reader.GetFieldValue<string>(10), - reader.IsDBNull(11) ? null : reader.GetFieldValue<string>(11), - reader.IsDBNull(12) ? null : reader.GetFieldValue<string>(12), - reader.IsDBNull(13) ? null : reader.GetFieldValue<string>(13), - reader.IsDBNull(14) ? null : reader.GetFieldValue<string>(14), - reader.IsDBNull(15) ? default(long) : reader.GetFieldValue<long>(15) - ); - results.Add(item); - } - } - } - - return new Result<ImmutableList<GetConditionsByPatient>, SqlError>.Ok<ImmutableList<GetConditionsByPatient>, SqlError>(results.ToImmutable()); - } - catch (Exception ex) - { - return new Result<ImmutableList<GetConditionsByPatient>, SqlError>.Error<ImmutableList<GetConditionsByPatient>, SqlError>(new SqlError("Database error", ex)); - } - } -} - -/// <summary> -/// Result row for 'GetConditionsByPatient' query. -/// </summary> -public record GetConditionsByPatient -{ - /// <summary>Column 'Id'.</summary> - public string Id { get; init; } - - /// <summary>Column 'ClinicalStatus'.</summary> - public string ClinicalStatus { get; init; } - - /// <summary>Column 'VerificationStatus'.</summary> - public string VerificationStatus { get; init; } - - /// <summary>Column 'Category'.</summary> - public string Category { get; init; } - - /// <summary>Column 'Severity'.</summary> - public string Severity { get; init; } - - /// <summary>Column 'CodeSystem'.</summary> - public string CodeSystem { get; init; } - - /// <summary>Column 'CodeValue'.</summary> - public string CodeValue { get; init; } - - /// <summary>Column 'CodeDisplay'.</summary> - public string CodeDisplay { get; init; } - - /// <summary>Column 'SubjectReference'.</summary> - public string SubjectReference { get; init; } - - /// <summary>Column 'EncounterReference'.</summary> - public string EncounterReference { get; init; } - - /// <summary>Column 'OnsetDateTime'.</summary> - public string OnsetDateTime { get; init; } - - /// <summary>Column 'RecordedDate'.</summary> - public string RecordedDate { get; init; } - - /// <summary>Column 'RecorderReference'.</summary> - public string RecorderReference { get; init; } - - /// <summary>Column 'NoteText'.</summary> - public string NoteText { get; init; } - - /// <summary>Column 'LastUpdated'.</summary> - public string LastUpdated { get; init; } - - /// <summary>Column 'VersionId'.</summary> - public long VersionId { get; init; } - - /// <summary>Initializes a new instance of GetConditionsByPatient.</summary> - public GetConditionsByPatient( - string Id, - string ClinicalStatus, - string VerificationStatus, - string Category, - string Severity, - string CodeSystem, - string CodeValue, - string CodeDisplay, - string SubjectReference, - string EncounterReference, - string OnsetDateTime, - string RecordedDate, - string RecorderReference, - string NoteText, - string LastUpdated, - long VersionId - ) - { - this.Id = Id; - this.ClinicalStatus = ClinicalStatus; - this.VerificationStatus = VerificationStatus; - this.Category = Category; - this.Severity = Severity; - this.CodeSystem = CodeSystem; - this.CodeValue = CodeValue; - this.CodeDisplay = CodeDisplay; - this.SubjectReference = SubjectReference; - this.EncounterReference = EncounterReference; - this.OnsetDateTime = OnsetDateTime; - this.RecordedDate = RecordedDate; - this.RecorderReference = RecorderReference; - this.NoteText = NoteText; - this.LastUpdated = LastUpdated; - this.VersionId = VersionId; - } -} diff --git a/Clinical/Clinical.Api/Generated/GetEncountersByPatient.g.cs b/Clinical/Clinical.Api/Generated/GetEncountersByPatient.g.cs deleted file mode 100644 index 56f76a9..0000000 --- a/Clinical/Clinical.Api/Generated/GetEncountersByPatient.g.cs +++ /dev/null @@ -1,139 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Threading.Tasks; -using Npgsql; -using Outcome; -using Nimblesite.Sql.Model; - -namespace Generated; - -/// <summary> -/// Extension methods for 'GetEncountersByPatient'. -/// </summary> -public static partial class GetEncountersByPatientExtensions -{ - /// <summary> - /// Executes 'GetEncountersByPatient.sql' and maps results. - /// </summary> - /// <param name="connection">Open NpgsqlConnection connection.</param> - /// <param name="patientId">Query parameter.</param> - /// <returns>Result of records or SQL error.</returns> - public static async Task<Result<ImmutableList<GetEncountersByPatient>, SqlError>> GetEncountersByPatientAsync(this NpgsqlConnection connection, object patientId) - { - const string sql = @"SELECT fhir_Encounter.Id, fhir_Encounter.Status, fhir_Encounter.Class, fhir_Encounter.PatientId, fhir_Encounter.PractitionerId, fhir_Encounter.ServiceType, fhir_Encounter.ReasonCode, fhir_Encounter.PeriodStart, fhir_Encounter.PeriodEnd, fhir_Encounter.Notes, fhir_Encounter.LastUpdated, fhir_Encounter.VersionId FROM fhir_Encounter WHERE fhir_Encounter.PatientId = @patientId ORDER BY fhir_Encounter.PeriodStart DESC"; - - try - { - var results = ImmutableList.CreateBuilder<GetEncountersByPatient>(); - - using (var command = new NpgsqlCommand(sql, connection)) - { - if (patientId is not null and not DBNull) - command.Parameters.AddWithValue("@patientId", patientId); - else - command.Parameters.Add(new NpgsqlParameter("@patientId", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); - - using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false)) - { - while (await reader.ReadAsync().ConfigureAwait(false)) - { - var item = new GetEncountersByPatient( - reader.IsDBNull(0) ? null : reader.GetFieldValue<string>(0), - reader.IsDBNull(1) ? null : reader.GetFieldValue<string>(1), - reader.IsDBNull(2) ? null : reader.GetFieldValue<string>(2), - reader.IsDBNull(3) ? null : reader.GetFieldValue<string>(3), - reader.IsDBNull(4) ? null : reader.GetFieldValue<string>(4), - reader.IsDBNull(5) ? null : reader.GetFieldValue<string>(5), - reader.IsDBNull(6) ? null : reader.GetFieldValue<string>(6), - reader.IsDBNull(7) ? null : reader.GetFieldValue<string>(7), - reader.IsDBNull(8) ? null : reader.GetFieldValue<string>(8), - reader.IsDBNull(9) ? null : reader.GetFieldValue<string>(9), - reader.IsDBNull(10) ? null : reader.GetFieldValue<string>(10), - reader.IsDBNull(11) ? default(long) : reader.GetFieldValue<long>(11) - ); - results.Add(item); - } - } - } - - return new Result<ImmutableList<GetEncountersByPatient>, SqlError>.Ok<ImmutableList<GetEncountersByPatient>, SqlError>(results.ToImmutable()); - } - catch (Exception ex) - { - return new Result<ImmutableList<GetEncountersByPatient>, SqlError>.Error<ImmutableList<GetEncountersByPatient>, SqlError>(new SqlError("Database error", ex)); - } - } -} - -/// <summary> -/// Result row for 'GetEncountersByPatient' query. -/// </summary> -public record GetEncountersByPatient -{ - /// <summary>Column 'Id'.</summary> - public string Id { get; init; } - - /// <summary>Column 'Status'.</summary> - public string Status { get; init; } - - /// <summary>Column 'Class'.</summary> - public string Class { get; init; } - - /// <summary>Column 'PatientId'.</summary> - public string PatientId { get; init; } - - /// <summary>Column 'PractitionerId'.</summary> - public string PractitionerId { get; init; } - - /// <summary>Column 'ServiceType'.</summary> - public string ServiceType { get; init; } - - /// <summary>Column 'ReasonCode'.</summary> - public string ReasonCode { get; init; } - - /// <summary>Column 'PeriodStart'.</summary> - public string PeriodStart { get; init; } - - /// <summary>Column 'PeriodEnd'.</summary> - public string PeriodEnd { get; init; } - - /// <summary>Column 'Notes'.</summary> - public string Notes { get; init; } - - /// <summary>Column 'LastUpdated'.</summary> - public string LastUpdated { get; init; } - - /// <summary>Column 'VersionId'.</summary> - public long VersionId { get; init; } - - /// <summary>Initializes a new instance of GetEncountersByPatient.</summary> - public GetEncountersByPatient( - string Id, - string Status, - string Class, - string PatientId, - string PractitionerId, - string ServiceType, - string ReasonCode, - string PeriodStart, - string PeriodEnd, - string Notes, - string LastUpdated, - long VersionId - ) - { - this.Id = Id; - this.Status = Status; - this.Class = Class; - this.PatientId = PatientId; - this.PractitionerId = PractitionerId; - this.ServiceType = ServiceType; - this.ReasonCode = ReasonCode; - this.PeriodStart = PeriodStart; - this.PeriodEnd = PeriodEnd; - this.Notes = Notes; - this.LastUpdated = LastUpdated; - this.VersionId = VersionId; - } -} diff --git a/Clinical/Clinical.Api/Generated/GetMedicationsByPatient.g.cs b/Clinical/Clinical.Api/Generated/GetMedicationsByPatient.g.cs deleted file mode 100644 index 70d5bee..0000000 --- a/Clinical/Clinical.Api/Generated/GetMedicationsByPatient.g.cs +++ /dev/null @@ -1,157 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Threading.Tasks; -using Npgsql; -using Outcome; -using Nimblesite.Sql.Model; - -namespace Generated; - -/// <summary> -/// Extension methods for 'GetMedicationsByPatient'. -/// </summary> -public static partial class GetMedicationsByPatientExtensions -{ - /// <summary> - /// Executes 'GetMedicationsByPatient.sql' and maps results. - /// </summary> - /// <param name="connection">Open NpgsqlConnection connection.</param> - /// <param name="patientId">Query parameter.</param> - /// <returns>Result of records or SQL error.</returns> - public static async Task<Result<ImmutableList<GetMedicationsByPatient>, SqlError>> GetMedicationsByPatientAsync(this NpgsqlConnection connection, object patientId) - { - const string sql = @"SELECT fhir_MedicationRequest.Id, fhir_MedicationRequest.Status, fhir_MedicationRequest.Intent, fhir_MedicationRequest.PatientId, fhir_MedicationRequest.PractitionerId, fhir_MedicationRequest.EncounterId, fhir_MedicationRequest.MedicationCode, fhir_MedicationRequest.MedicationDisplay, fhir_MedicationRequest.DosageInstruction, fhir_MedicationRequest.Quantity, fhir_MedicationRequest.Unit, fhir_MedicationRequest.Refills, fhir_MedicationRequest.AuthoredOn, fhir_MedicationRequest.LastUpdated, fhir_MedicationRequest.VersionId FROM fhir_MedicationRequest WHERE fhir_MedicationRequest.PatientId = @patientId ORDER BY fhir_MedicationRequest.AuthoredOn DESC"; - - try - { - var results = ImmutableList.CreateBuilder<GetMedicationsByPatient>(); - - using (var command = new NpgsqlCommand(sql, connection)) - { - if (patientId is not null and not DBNull) - command.Parameters.AddWithValue("@patientId", patientId); - else - command.Parameters.Add(new NpgsqlParameter("@patientId", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); - - using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false)) - { - while (await reader.ReadAsync().ConfigureAwait(false)) - { - var item = new GetMedicationsByPatient( - reader.IsDBNull(0) ? null : reader.GetFieldValue<string>(0), - reader.IsDBNull(1) ? null : reader.GetFieldValue<string>(1), - reader.IsDBNull(2) ? null : reader.GetFieldValue<string>(2), - reader.IsDBNull(3) ? null : reader.GetFieldValue<string>(3), - reader.IsDBNull(4) ? null : reader.GetFieldValue<string>(4), - reader.IsDBNull(5) ? null : reader.GetFieldValue<string>(5), - reader.IsDBNull(6) ? null : reader.GetFieldValue<string>(6), - reader.IsDBNull(7) ? null : reader.GetFieldValue<string>(7), - reader.IsDBNull(8) ? null : reader.GetFieldValue<string>(8), - reader.IsDBNull(9) ? default(double) : reader.GetFieldValue<double>(9), - reader.IsDBNull(10) ? null : reader.GetFieldValue<string>(10), - reader.IsDBNull(11) ? default(long) : reader.GetFieldValue<long>(11), - reader.IsDBNull(12) ? null : reader.GetFieldValue<string>(12), - reader.IsDBNull(13) ? null : reader.GetFieldValue<string>(13), - reader.IsDBNull(14) ? default(long) : reader.GetFieldValue<long>(14) - ); - results.Add(item); - } - } - } - - return new Result<ImmutableList<GetMedicationsByPatient>, SqlError>.Ok<ImmutableList<GetMedicationsByPatient>, SqlError>(results.ToImmutable()); - } - catch (Exception ex) - { - return new Result<ImmutableList<GetMedicationsByPatient>, SqlError>.Error<ImmutableList<GetMedicationsByPatient>, SqlError>(new SqlError("Database error", ex)); - } - } -} - -/// <summary> -/// Result row for 'GetMedicationsByPatient' query. -/// </summary> -public record GetMedicationsByPatient -{ - /// <summary>Column 'Id'.</summary> - public string Id { get; init; } - - /// <summary>Column 'Status'.</summary> - public string Status { get; init; } - - /// <summary>Column 'Intent'.</summary> - public string Intent { get; init; } - - /// <summary>Column 'PatientId'.</summary> - public string PatientId { get; init; } - - /// <summary>Column 'PractitionerId'.</summary> - public string PractitionerId { get; init; } - - /// <summary>Column 'EncounterId'.</summary> - public string EncounterId { get; init; } - - /// <summary>Column 'MedicationCode'.</summary> - public string MedicationCode { get; init; } - - /// <summary>Column 'MedicationDisplay'.</summary> - public string MedicationDisplay { get; init; } - - /// <summary>Column 'DosageInstruction'.</summary> - public string DosageInstruction { get; init; } - - /// <summary>Column 'Quantity'.</summary> - public double Quantity { get; init; } - - /// <summary>Column 'Unit'.</summary> - public string Unit { get; init; } - - /// <summary>Column 'Refills'.</summary> - public long Refills { get; init; } - - /// <summary>Column 'AuthoredOn'.</summary> - public string AuthoredOn { get; init; } - - /// <summary>Column 'LastUpdated'.</summary> - public string LastUpdated { get; init; } - - /// <summary>Column 'VersionId'.</summary> - public long VersionId { get; init; } - - /// <summary>Initializes a new instance of GetMedicationsByPatient.</summary> - public GetMedicationsByPatient( - string Id, - string Status, - string Intent, - string PatientId, - string PractitionerId, - string EncounterId, - string MedicationCode, - string MedicationDisplay, - string DosageInstruction, - double Quantity, - string Unit, - long Refills, - string AuthoredOn, - string LastUpdated, - long VersionId - ) - { - this.Id = Id; - this.Status = Status; - this.Intent = Intent; - this.PatientId = PatientId; - this.PractitionerId = PractitionerId; - this.EncounterId = EncounterId; - this.MedicationCode = MedicationCode; - this.MedicationDisplay = MedicationDisplay; - this.DosageInstruction = DosageInstruction; - this.Quantity = Quantity; - this.Unit = Unit; - this.Refills = Refills; - this.AuthoredOn = AuthoredOn; - this.LastUpdated = LastUpdated; - this.VersionId = VersionId; - } -} diff --git a/Clinical/Clinical.Api/Generated/GetPatientById.g.cs b/Clinical/Clinical.Api/Generated/GetPatientById.g.cs deleted file mode 100644 index 9c7451d..0000000 --- a/Clinical/Clinical.Api/Generated/GetPatientById.g.cs +++ /dev/null @@ -1,157 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Threading.Tasks; -using Npgsql; -using Outcome; -using Nimblesite.Sql.Model; - -namespace Generated; - -/// <summary> -/// Extension methods for 'GetPatientById'. -/// </summary> -public static partial class GetPatientByIdExtensions -{ - /// <summary> - /// Executes 'GetPatientById.sql' and maps results. - /// </summary> - /// <param name="connection">Open NpgsqlConnection connection.</param> - /// <param name="id">Query parameter.</param> - /// <returns>Result of records or SQL error.</returns> - public static async Task<Result<ImmutableList<GetPatientById>, SqlError>> GetPatientByIdAsync(this NpgsqlConnection connection, object id) - { - const string sql = @"SELECT fhir_Patient.Id, fhir_Patient.Active, fhir_Patient.GivenName, fhir_Patient.FamilyName, fhir_Patient.BirthDate, fhir_Patient.Gender, fhir_Patient.Phone, fhir_Patient.Email, fhir_Patient.AddressLine, fhir_Patient.City, fhir_Patient.State, fhir_Patient.PostalCode, fhir_Patient.Country, fhir_Patient.LastUpdated, fhir_Patient.VersionId FROM fhir_Patient WHERE fhir_Patient.Id = @id"; - - try - { - var results = ImmutableList.CreateBuilder<GetPatientById>(); - - using (var command = new NpgsqlCommand(sql, connection)) - { - if (id is not null and not DBNull) - command.Parameters.AddWithValue("@id", id); - else - command.Parameters.Add(new NpgsqlParameter("@id", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); - - using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false)) - { - while (await reader.ReadAsync().ConfigureAwait(false)) - { - var item = new GetPatientById( - reader.IsDBNull(0) ? null : reader.GetFieldValue<string>(0), - reader.IsDBNull(1) ? default(long) : reader.GetFieldValue<long>(1), - reader.IsDBNull(2) ? null : reader.GetFieldValue<string>(2), - reader.IsDBNull(3) ? null : reader.GetFieldValue<string>(3), - reader.IsDBNull(4) ? null : reader.GetFieldValue<string>(4), - reader.IsDBNull(5) ? null : reader.GetFieldValue<string>(5), - reader.IsDBNull(6) ? null : reader.GetFieldValue<string>(6), - reader.IsDBNull(7) ? null : reader.GetFieldValue<string>(7), - reader.IsDBNull(8) ? null : reader.GetFieldValue<string>(8), - reader.IsDBNull(9) ? null : reader.GetFieldValue<string>(9), - reader.IsDBNull(10) ? null : reader.GetFieldValue<string>(10), - reader.IsDBNull(11) ? null : reader.GetFieldValue<string>(11), - reader.IsDBNull(12) ? null : reader.GetFieldValue<string>(12), - reader.IsDBNull(13) ? null : reader.GetFieldValue<string>(13), - reader.IsDBNull(14) ? default(long) : reader.GetFieldValue<long>(14) - ); - results.Add(item); - } - } - } - - return new Result<ImmutableList<GetPatientById>, SqlError>.Ok<ImmutableList<GetPatientById>, SqlError>(results.ToImmutable()); - } - catch (Exception ex) - { - return new Result<ImmutableList<GetPatientById>, SqlError>.Error<ImmutableList<GetPatientById>, SqlError>(new SqlError("Database error", ex)); - } - } -} - -/// <summary> -/// Result row for 'GetPatientById' query. -/// </summary> -public record GetPatientById -{ - /// <summary>Column 'Id'.</summary> - public string Id { get; init; } - - /// <summary>Column 'Active'.</summary> - public long Active { get; init; } - - /// <summary>Column 'GivenName'.</summary> - public string GivenName { get; init; } - - /// <summary>Column 'FamilyName'.</summary> - public string FamilyName { get; init; } - - /// <summary>Column 'BirthDate'.</summary> - public string BirthDate { get; init; } - - /// <summary>Column 'Gender'.</summary> - public string Gender { get; init; } - - /// <summary>Column 'Phone'.</summary> - public string Phone { get; init; } - - /// <summary>Column 'Email'.</summary> - public string Email { get; init; } - - /// <summary>Column 'AddressLine'.</summary> - public string AddressLine { get; init; } - - /// <summary>Column 'City'.</summary> - public string City { get; init; } - - /// <summary>Column 'State'.</summary> - public string State { get; init; } - - /// <summary>Column 'PostalCode'.</summary> - public string PostalCode { get; init; } - - /// <summary>Column 'Country'.</summary> - public string Country { get; init; } - - /// <summary>Column 'LastUpdated'.</summary> - public string LastUpdated { get; init; } - - /// <summary>Column 'VersionId'.</summary> - public long VersionId { get; init; } - - /// <summary>Initializes a new instance of GetPatientById.</summary> - public GetPatientById( - string Id, - long Active, - string GivenName, - string FamilyName, - string BirthDate, - string Gender, - string Phone, - string Email, - string AddressLine, - string City, - string State, - string PostalCode, - string Country, - string LastUpdated, - long VersionId - ) - { - this.Id = Id; - this.Active = Active; - this.GivenName = GivenName; - this.FamilyName = FamilyName; - this.BirthDate = BirthDate; - this.Gender = Gender; - this.Phone = Phone; - this.Email = Email; - this.AddressLine = AddressLine; - this.City = City; - this.State = State; - this.PostalCode = PostalCode; - this.Country = Country; - this.LastUpdated = LastUpdated; - this.VersionId = VersionId; - } -} diff --git a/Clinical/Clinical.Api/Generated/GetPatients.g.cs b/Clinical/Clinical.Api/Generated/GetPatients.g.cs deleted file mode 100644 index 8a69fed..0000000 --- a/Clinical/Clinical.Api/Generated/GetPatients.g.cs +++ /dev/null @@ -1,172 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Threading.Tasks; -using Npgsql; -using Outcome; -using Nimblesite.Sql.Model; - -namespace Generated; - -/// <summary> -/// Extension methods for 'GetPatients'. -/// </summary> -public static partial class GetPatientsExtensions -{ - /// <summary> - /// Executes 'GetPatients.sql' and maps results. - /// </summary> - /// <param name="connection">Open NpgsqlConnection connection.</param> - /// <param name="active">Query parameter.</param> - /// <param name="familyName">Query parameter.</param> - /// <param name="givenName">Query parameter.</param> - /// <param name="gender">Query parameter.</param> - /// <returns>Result of records or SQL error.</returns> - public static async Task<Result<ImmutableList<GetPatients>, SqlError>> GetPatientsAsync(this NpgsqlConnection connection, object active, object familyName, object givenName, object gender) - { - const string sql = @"SELECT fhir_Patient.Id, fhir_Patient.Active, fhir_Patient.GivenName, fhir_Patient.FamilyName, fhir_Patient.BirthDate, fhir_Patient.Gender, fhir_Patient.Phone, fhir_Patient.Email, fhir_Patient.AddressLine, fhir_Patient.City, fhir_Patient.State, fhir_Patient.PostalCode, fhir_Patient.Country, fhir_Patient.LastUpdated, fhir_Patient.VersionId FROM fhir_Patient WHERE (@active IS NULL OR fhir_Patient.Active = @active) AND (@familyName IS NULL OR fhir_Patient.FamilyName LIKE '%' || @familyName || '%') AND (@givenName IS NULL OR fhir_Patient.GivenName LIKE '%' || @givenName || '%') AND (@gender IS NULL OR fhir_Patient.Gender = @gender) ORDER BY fhir_Patient.FamilyName , fhir_Patient.GivenName "; - - try - { - var results = ImmutableList.CreateBuilder<GetPatients>(); - - using (var command = new NpgsqlCommand(sql, connection)) - { - if (active is not null and not DBNull) - command.Parameters.AddWithValue("@active", active); - else - command.Parameters.Add(new NpgsqlParameter("@active", NpgsqlTypes.NpgsqlDbType.Bigint) { Value = DBNull.Value }); - if (familyName is not null and not DBNull) - command.Parameters.AddWithValue("@familyName", familyName); - else - command.Parameters.Add(new NpgsqlParameter("@familyName", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); - if (givenName is not null and not DBNull) - command.Parameters.AddWithValue("@givenName", givenName); - else - command.Parameters.Add(new NpgsqlParameter("@givenName", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); - if (gender is not null and not DBNull) - command.Parameters.AddWithValue("@gender", gender); - else - command.Parameters.Add(new NpgsqlParameter("@gender", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); - - using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false)) - { - while (await reader.ReadAsync().ConfigureAwait(false)) - { - var item = new GetPatients( - reader.IsDBNull(0) ? null : reader.GetFieldValue<string>(0), - reader.IsDBNull(1) ? default(long) : reader.GetFieldValue<long>(1), - reader.IsDBNull(2) ? null : reader.GetFieldValue<string>(2), - reader.IsDBNull(3) ? null : reader.GetFieldValue<string>(3), - reader.IsDBNull(4) ? null : reader.GetFieldValue<string>(4), - reader.IsDBNull(5) ? null : reader.GetFieldValue<string>(5), - reader.IsDBNull(6) ? null : reader.GetFieldValue<string>(6), - reader.IsDBNull(7) ? null : reader.GetFieldValue<string>(7), - reader.IsDBNull(8) ? null : reader.GetFieldValue<string>(8), - reader.IsDBNull(9) ? null : reader.GetFieldValue<string>(9), - reader.IsDBNull(10) ? null : reader.GetFieldValue<string>(10), - reader.IsDBNull(11) ? null : reader.GetFieldValue<string>(11), - reader.IsDBNull(12) ? null : reader.GetFieldValue<string>(12), - reader.IsDBNull(13) ? null : reader.GetFieldValue<string>(13), - reader.IsDBNull(14) ? default(long) : reader.GetFieldValue<long>(14) - ); - results.Add(item); - } - } - } - - return new Result<ImmutableList<GetPatients>, SqlError>.Ok<ImmutableList<GetPatients>, SqlError>(results.ToImmutable()); - } - catch (Exception ex) - { - return new Result<ImmutableList<GetPatients>, SqlError>.Error<ImmutableList<GetPatients>, SqlError>(new SqlError("Database error", ex)); - } - } -} - -/// <summary> -/// Result row for 'GetPatients' query. -/// </summary> -public record GetPatients -{ - /// <summary>Column 'Id'.</summary> - public string Id { get; init; } - - /// <summary>Column 'Active'.</summary> - public long Active { get; init; } - - /// <summary>Column 'GivenName'.</summary> - public string GivenName { get; init; } - - /// <summary>Column 'FamilyName'.</summary> - public string FamilyName { get; init; } - - /// <summary>Column 'BirthDate'.</summary> - public string BirthDate { get; init; } - - /// <summary>Column 'Gender'.</summary> - public string Gender { get; init; } - - /// <summary>Column 'Phone'.</summary> - public string Phone { get; init; } - - /// <summary>Column 'Email'.</summary> - public string Email { get; init; } - - /// <summary>Column 'AddressLine'.</summary> - public string AddressLine { get; init; } - - /// <summary>Column 'City'.</summary> - public string City { get; init; } - - /// <summary>Column 'State'.</summary> - public string State { get; init; } - - /// <summary>Column 'PostalCode'.</summary> - public string PostalCode { get; init; } - - /// <summary>Column 'Country'.</summary> - public string Country { get; init; } - - /// <summary>Column 'LastUpdated'.</summary> - public string LastUpdated { get; init; } - - /// <summary>Column 'VersionId'.</summary> - public long VersionId { get; init; } - - /// <summary>Initializes a new instance of GetPatients.</summary> - public GetPatients( - string Id, - long Active, - string GivenName, - string FamilyName, - string BirthDate, - string Gender, - string Phone, - string Email, - string AddressLine, - string City, - string State, - string PostalCode, - string Country, - string LastUpdated, - long VersionId - ) - { - this.Id = Id; - this.Active = Active; - this.GivenName = GivenName; - this.FamilyName = FamilyName; - this.BirthDate = BirthDate; - this.Gender = Gender; - this.Phone = Phone; - this.Email = Email; - this.AddressLine = AddressLine; - this.City = City; - this.State = State; - this.PostalCode = PostalCode; - this.Country = Country; - this.LastUpdated = LastUpdated; - this.VersionId = VersionId; - } -} diff --git a/Clinical/Clinical.Api/Generated/SearchPatients.g.cs b/Clinical/Clinical.Api/Generated/SearchPatients.g.cs deleted file mode 100644 index d4f7209..0000000 --- a/Clinical/Clinical.Api/Generated/SearchPatients.g.cs +++ /dev/null @@ -1,157 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Threading.Tasks; -using Npgsql; -using Outcome; -using Nimblesite.Sql.Model; - -namespace Generated; - -/// <summary> -/// Extension methods for 'SearchPatients'. -/// </summary> -public static partial class SearchPatientsExtensions -{ - /// <summary> - /// Executes 'SearchPatients.sql' and maps results. - /// </summary> - /// <param name="connection">Open NpgsqlConnection connection.</param> - /// <param name="term">Query parameter.</param> - /// <returns>Result of records or SQL error.</returns> - public static async Task<Result<ImmutableList<SearchPatients>, SqlError>> SearchPatientsAsync(this NpgsqlConnection connection, object term) - { - const string sql = @"SELECT fhir_Patient.Id, fhir_Patient.Active, fhir_Patient.GivenName, fhir_Patient.FamilyName, fhir_Patient.BirthDate, fhir_Patient.Gender, fhir_Patient.Phone, fhir_Patient.Email, fhir_Patient.AddressLine, fhir_Patient.City, fhir_Patient.State, fhir_Patient.PostalCode, fhir_Patient.Country, fhir_Patient.LastUpdated, fhir_Patient.VersionId FROM fhir_Patient WHERE fhir_Patient.GivenName LIKE @term OR fhir_Patient.FamilyName LIKE @term OR fhir_Patient.Email LIKE @term ORDER BY fhir_Patient.FamilyName , fhir_Patient.GivenName "; - - try - { - var results = ImmutableList.CreateBuilder<SearchPatients>(); - - using (var command = new NpgsqlCommand(sql, connection)) - { - if (term is not null and not DBNull) - command.Parameters.AddWithValue("@term", term); - else - command.Parameters.Add(new NpgsqlParameter("@term", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); - - using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false)) - { - while (await reader.ReadAsync().ConfigureAwait(false)) - { - var item = new SearchPatients( - reader.IsDBNull(0) ? null : reader.GetFieldValue<string>(0), - reader.IsDBNull(1) ? default(long) : reader.GetFieldValue<long>(1), - reader.IsDBNull(2) ? null : reader.GetFieldValue<string>(2), - reader.IsDBNull(3) ? null : reader.GetFieldValue<string>(3), - reader.IsDBNull(4) ? null : reader.GetFieldValue<string>(4), - reader.IsDBNull(5) ? null : reader.GetFieldValue<string>(5), - reader.IsDBNull(6) ? null : reader.GetFieldValue<string>(6), - reader.IsDBNull(7) ? null : reader.GetFieldValue<string>(7), - reader.IsDBNull(8) ? null : reader.GetFieldValue<string>(8), - reader.IsDBNull(9) ? null : reader.GetFieldValue<string>(9), - reader.IsDBNull(10) ? null : reader.GetFieldValue<string>(10), - reader.IsDBNull(11) ? null : reader.GetFieldValue<string>(11), - reader.IsDBNull(12) ? null : reader.GetFieldValue<string>(12), - reader.IsDBNull(13) ? null : reader.GetFieldValue<string>(13), - reader.IsDBNull(14) ? default(long) : reader.GetFieldValue<long>(14) - ); - results.Add(item); - } - } - } - - return new Result<ImmutableList<SearchPatients>, SqlError>.Ok<ImmutableList<SearchPatients>, SqlError>(results.ToImmutable()); - } - catch (Exception ex) - { - return new Result<ImmutableList<SearchPatients>, SqlError>.Error<ImmutableList<SearchPatients>, SqlError>(new SqlError("Database error", ex)); - } - } -} - -/// <summary> -/// Result row for 'SearchPatients' query. -/// </summary> -public record SearchPatients -{ - /// <summary>Column 'Id'.</summary> - public string Id { get; init; } - - /// <summary>Column 'Active'.</summary> - public long Active { get; init; } - - /// <summary>Column 'GivenName'.</summary> - public string GivenName { get; init; } - - /// <summary>Column 'FamilyName'.</summary> - public string FamilyName { get; init; } - - /// <summary>Column 'BirthDate'.</summary> - public string BirthDate { get; init; } - - /// <summary>Column 'Gender'.</summary> - public string Gender { get; init; } - - /// <summary>Column 'Phone'.</summary> - public string Phone { get; init; } - - /// <summary>Column 'Email'.</summary> - public string Email { get; init; } - - /// <summary>Column 'AddressLine'.</summary> - public string AddressLine { get; init; } - - /// <summary>Column 'City'.</summary> - public string City { get; init; } - - /// <summary>Column 'State'.</summary> - public string State { get; init; } - - /// <summary>Column 'PostalCode'.</summary> - public string PostalCode { get; init; } - - /// <summary>Column 'Country'.</summary> - public string Country { get; init; } - - /// <summary>Column 'LastUpdated'.</summary> - public string LastUpdated { get; init; } - - /// <summary>Column 'VersionId'.</summary> - public long VersionId { get; init; } - - /// <summary>Initializes a new instance of SearchPatients.</summary> - public SearchPatients( - string Id, - long Active, - string GivenName, - string FamilyName, - string BirthDate, - string Gender, - string Phone, - string Email, - string AddressLine, - string City, - string State, - string PostalCode, - string Country, - string LastUpdated, - long VersionId - ) - { - this.Id = Id; - this.Active = Active; - this.GivenName = GivenName; - this.FamilyName = FamilyName; - this.BirthDate = BirthDate; - this.Gender = Gender; - this.Phone = Phone; - this.Email = Email; - this.AddressLine = AddressLine; - this.City = City; - this.State = State; - this.PostalCode = PostalCode; - this.Country = Country; - this.LastUpdated = LastUpdated; - this.VersionId = VersionId; - } -} diff --git a/Clinical/Clinical.Api/Generated/fhir_ConditionOperations.g.cs b/Clinical/Clinical.Api/Generated/fhir_ConditionOperations.g.cs deleted file mode 100644 index 857e6d0..0000000 --- a/Clinical/Clinical.Api/Generated/fhir_ConditionOperations.g.cs +++ /dev/null @@ -1,62 +0,0 @@ -#nullable enable -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Data; -using System.Globalization; -using System.Threading.Tasks; -using Npgsql; -using Outcome; -using Nimblesite.Sql.Model; - -namespace Generated -{ - /// <summary> - /// Extension methods for table operations on fhir_Condition - /// </summary> - public static partial class fhir_ConditionExtensions - { - - /// <summary> - /// Inserts a new row into the fhir_Condition table. - /// </summary> - public static async Task<Result<int, SqlError>> Insertfhir_ConditionAsync(this IDbTransaction transaction, string? id, string? clinicalstatus, string? verificationstatus, string? category, string? severity, string? codesystem, string? codevalue, string? codedisplay, string? subjectreference, string? encounterreference, string? onsetdatetime, string? recordeddate, string? recorderreference, string? notetext, string? lastupdated, long? versionid) - { - const string sql = "INSERT INTO fhir_Condition (Id, ClinicalStatus, VerificationStatus, Category, Severity, CodeSystem, CodeValue, CodeDisplay, SubjectReference, EncounterReference, OnsetDateTime, RecordedDate, RecorderReference, NoteText, LastUpdated, VersionId) VALUES (@Id, @ClinicalStatus, @VerificationStatus, @Category, @Severity, @CodeSystem, @CodeValue, @CodeDisplay, @SubjectReference, @EncounterReference, @OnsetDateTime, @RecordedDate, @RecorderReference, @NoteText, @LastUpdated, @VersionId)"; - - if (transaction.Connection is null) - return new Result<int, SqlError>.Error<int, SqlError>(new SqlError("Transaction has no connection")); - - try - { - using (var command = new NpgsqlCommand(sql, (NpgsqlConnection)transaction.Connection!, (NpgsqlTransaction)transaction)) - { - command.Parameters.AddWithValue("@Id", id ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@ClinicalStatus", clinicalstatus ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@VerificationStatus", verificationstatus ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@Category", category ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@Severity", severity ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@CodeSystem", codesystem ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@CodeValue", codevalue ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@CodeDisplay", codedisplay ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@SubjectReference", subjectreference ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@EncounterReference", encounterreference ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@OnsetDateTime", onsetdatetime ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@RecordedDate", recordeddate ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@RecorderReference", recorderreference ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@NoteText", notetext ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@LastUpdated", lastupdated ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@VersionId", versionid ?? (object)DBNull.Value); - - var rowsAffected = await command.ExecuteNonQueryAsync().ConfigureAwait(false); - return new Result<int, SqlError>.Ok<int, SqlError>(rowsAffected); - } - } - catch (Exception ex) - { - return new Result<int, SqlError>.Error<int, SqlError>(new SqlError("Insert failed", ex)); - } - } - - } -} diff --git a/Clinical/Clinical.Api/Generated/fhir_EncounterOperations.g.cs b/Clinical/Clinical.Api/Generated/fhir_EncounterOperations.g.cs deleted file mode 100644 index 37a8199..0000000 --- a/Clinical/Clinical.Api/Generated/fhir_EncounterOperations.g.cs +++ /dev/null @@ -1,58 +0,0 @@ -#nullable enable -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Data; -using System.Globalization; -using System.Threading.Tasks; -using Npgsql; -using Outcome; -using Nimblesite.Sql.Model; - -namespace Generated -{ - /// <summary> - /// Extension methods for table operations on fhir_Encounter - /// </summary> - public static partial class fhir_EncounterExtensions - { - - /// <summary> - /// Inserts a new row into the fhir_Encounter table. - /// </summary> - public static async Task<Result<int, SqlError>> Insertfhir_EncounterAsync(this IDbTransaction transaction, string? id, string? status, string? @class, string? patientid, string? practitionerid, string? servicetype, string? reasoncode, string? periodstart, string? periodend, string? notes, string? lastupdated, long? versionid) - { - const string sql = "INSERT INTO fhir_Encounter (Id, Status, Class, PatientId, PractitionerId, ServiceType, ReasonCode, PeriodStart, PeriodEnd, Notes, LastUpdated, VersionId) VALUES (@Id, @Status, @Class, @PatientId, @PractitionerId, @ServiceType, @ReasonCode, @PeriodStart, @PeriodEnd, @Notes, @LastUpdated, @VersionId)"; - - if (transaction.Connection is null) - return new Result<int, SqlError>.Error<int, SqlError>(new SqlError("Transaction has no connection")); - - try - { - using (var command = new NpgsqlCommand(sql, (NpgsqlConnection)transaction.Connection!, (NpgsqlTransaction)transaction)) - { - command.Parameters.AddWithValue("@Id", id ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@Status", status ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@Class", @class ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@PatientId", patientid ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@PractitionerId", practitionerid ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@ServiceType", servicetype ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@ReasonCode", reasoncode ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@PeriodStart", periodstart ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@PeriodEnd", periodend ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@Notes", notes ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@LastUpdated", lastupdated ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@VersionId", versionid ?? (object)DBNull.Value); - - var rowsAffected = await command.ExecuteNonQueryAsync().ConfigureAwait(false); - return new Result<int, SqlError>.Ok<int, SqlError>(rowsAffected); - } - } - catch (Exception ex) - { - return new Result<int, SqlError>.Error<int, SqlError>(new SqlError("Insert failed", ex)); - } - } - - } -} diff --git a/Clinical/Clinical.Api/Generated/fhir_MedicationRequestOperations.g.cs b/Clinical/Clinical.Api/Generated/fhir_MedicationRequestOperations.g.cs deleted file mode 100644 index 5f1621c..0000000 --- a/Clinical/Clinical.Api/Generated/fhir_MedicationRequestOperations.g.cs +++ /dev/null @@ -1,61 +0,0 @@ -#nullable enable -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Data; -using System.Globalization; -using System.Threading.Tasks; -using Npgsql; -using Outcome; -using Nimblesite.Sql.Model; - -namespace Generated -{ - /// <summary> - /// Extension methods for table operations on fhir_MedicationRequest - /// </summary> - public static partial class fhir_MedicationRequestExtensions - { - - /// <summary> - /// Inserts a new row into the fhir_MedicationRequest table. - /// </summary> - public static async Task<Result<int, SqlError>> Insertfhir_MedicationRequestAsync(this IDbTransaction transaction, string? id, string? status, string? intent, string? patientid, string? practitionerid, string? encounterid, string? medicationcode, string? medicationdisplay, string? dosageinstruction, double? quantity, string? unit, long? refills, string? authoredon, string? lastupdated, long? versionid) - { - const string sql = "INSERT INTO fhir_MedicationRequest (Id, Status, Intent, PatientId, PractitionerId, EncounterId, MedicationCode, MedicationDisplay, DosageInstruction, Quantity, Unit, Refills, AuthoredOn, LastUpdated, VersionId) VALUES (@Id, @Status, @Intent, @PatientId, @PractitionerId, @EncounterId, @MedicationCode, @MedicationDisplay, @DosageInstruction, @Quantity, @Unit, @Refills, @AuthoredOn, @LastUpdated, @VersionId)"; - - if (transaction.Connection is null) - return new Result<int, SqlError>.Error<int, SqlError>(new SqlError("Transaction has no connection")); - - try - { - using (var command = new NpgsqlCommand(sql, (NpgsqlConnection)transaction.Connection!, (NpgsqlTransaction)transaction)) - { - command.Parameters.AddWithValue("@Id", id ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@Status", status ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@Intent", intent ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@PatientId", patientid ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@PractitionerId", practitionerid ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@EncounterId", encounterid ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@MedicationCode", medicationcode ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@MedicationDisplay", medicationdisplay ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@DosageInstruction", dosageinstruction ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@Quantity", quantity ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@Unit", unit ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@Refills", refills ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@AuthoredOn", authoredon ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@LastUpdated", lastupdated ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@VersionId", versionid ?? (object)DBNull.Value); - - var rowsAffected = await command.ExecuteNonQueryAsync().ConfigureAwait(false); - return new Result<int, SqlError>.Ok<int, SqlError>(rowsAffected); - } - } - catch (Exception ex) - { - return new Result<int, SqlError>.Error<int, SqlError>(new SqlError("Insert failed", ex)); - } - } - - } -} diff --git a/Clinical/Clinical.Api/Generated/fhir_PatientOperations.g.cs b/Clinical/Clinical.Api/Generated/fhir_PatientOperations.g.cs deleted file mode 100644 index 4ada939..0000000 --- a/Clinical/Clinical.Api/Generated/fhir_PatientOperations.g.cs +++ /dev/null @@ -1,102 +0,0 @@ -#nullable enable -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Data; -using System.Globalization; -using System.Threading.Tasks; -using Npgsql; -using Outcome; -using Nimblesite.Sql.Model; - -namespace Generated -{ - /// <summary> - /// Extension methods for table operations on fhir_Patient - /// </summary> - public static partial class fhir_PatientExtensions - { - - /// <summary> - /// Inserts a new row into the fhir_Patient table. - /// </summary> - public static async Task<Result<int, SqlError>> Insertfhir_PatientAsync(this IDbTransaction transaction, string? id, long? active, string? givenname, string? familyname, string? birthdate, string? gender, string? phone, string? email, string? addressline, string? city, string? state, string? postalcode, string? country, string? lastupdated, long? versionid) - { - const string sql = "INSERT INTO fhir_Patient (Id, Active, GivenName, FamilyName, BirthDate, Gender, Phone, Email, AddressLine, City, State, PostalCode, Country, LastUpdated, VersionId) VALUES (@Id, @Active, @GivenName, @FamilyName, @BirthDate, @Gender, @Phone, @Email, @AddressLine, @City, @State, @PostalCode, @Country, @LastUpdated, @VersionId)"; - - if (transaction.Connection is null) - return new Result<int, SqlError>.Error<int, SqlError>(new SqlError("Transaction has no connection")); - - try - { - using (var command = new NpgsqlCommand(sql, (NpgsqlConnection)transaction.Connection!, (NpgsqlTransaction)transaction)) - { - command.Parameters.AddWithValue("@Id", id ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@Active", active ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@GivenName", givenname ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@FamilyName", familyname ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@BirthDate", birthdate ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@Gender", gender ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@Phone", phone ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@Email", email ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@AddressLine", addressline ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@City", city ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@State", state ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@PostalCode", postalcode ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@Country", country ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@LastUpdated", lastupdated ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@VersionId", versionid ?? (object)DBNull.Value); - - var rowsAffected = await command.ExecuteNonQueryAsync().ConfigureAwait(false); - return new Result<int, SqlError>.Ok<int, SqlError>(rowsAffected); - } - } - catch (Exception ex) - { - return new Result<int, SqlError>.Error<int, SqlError>(new SqlError("Insert failed", ex)); - } - } - - - /// <summary> - /// Updates a row in the fhir_Patient table. - /// </summary> - public static async Task<Result<int, SqlError>> Updatefhir_PatientAsync(this IDbTransaction transaction, string id, long? active, string givenname, string familyname, string birthdate, string gender, string phone, string email, string addressline, string city, string state, string postalcode, string country, string lastupdated, long? versionid) - { - const string sql = "UPDATE fhir_Patient SET Active = @Active, GivenName = @GivenName, FamilyName = @FamilyName, BirthDate = @BirthDate, Gender = @Gender, Phone = @Phone, Email = @Email, AddressLine = @AddressLine, City = @City, State = @State, PostalCode = @PostalCode, Country = @Country, LastUpdated = @LastUpdated, VersionId = @VersionId WHERE Id = @Id"; - - if (transaction.Connection is null) - return new Result<int, SqlError>.Error<int, SqlError>(new SqlError("Transaction has no connection")); - - try - { - using (var command = new NpgsqlCommand(sql, (NpgsqlConnection)transaction.Connection!, (NpgsqlTransaction)transaction)) - { - command.Parameters.AddWithValue("@Id", id ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@Active", active ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@GivenName", givenname ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@FamilyName", familyname ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@BirthDate", birthdate ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@Gender", gender ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@Phone", phone ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@Email", email ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@AddressLine", addressline ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@City", city ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@State", state ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@PostalCode", postalcode ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@Country", country ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@LastUpdated", lastupdated ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@VersionId", versionid ?? (object)DBNull.Value); - - var rowsAffected = await command.ExecuteNonQueryAsync().ConfigureAwait(false); - return new Result<int, SqlError>.Ok<int, SqlError>(rowsAffected); - } - } - catch (Exception ex) - { - return new Result<int, SqlError>.Error<int, SqlError>(new SqlError("Update failed", ex)); - } - } - - } -} diff --git a/Clinical/Clinical.Api/GlobalUsings.cs b/Clinical/Clinical.Api/GlobalUsings.cs index a820655..6d7738a 100644 --- a/Clinical/Clinical.Api/GlobalUsings.cs +++ b/Clinical/Clinical.Api/GlobalUsings.cs @@ -81,13 +81,13 @@ System.Collections.Immutable.ImmutableList<Generated.GetPatients>, Nimblesite.Sql.Model.SqlError >; -global using InsertError = Outcome.Result<int, Nimblesite.Sql.Model.SqlError>.Error< - int, +global using InsertError = Outcome.Result<System.Guid?, Nimblesite.Sql.Model.SqlError>.Error< + System.Guid?, Nimblesite.Sql.Model.SqlError >; // Insert result type aliases -global using InsertOk = Outcome.Result<int, Nimblesite.Sql.Model.SqlError>.Ok< - int, +global using InsertOk = Outcome.Result<System.Guid?, Nimblesite.Sql.Model.SqlError>.Ok< + System.Guid?, Nimblesite.Sql.Model.SqlError >; global using SearchPatientsError = Outcome.Result< diff --git a/Clinical/Clinical.Api/Program.cs b/Clinical/Clinical.Api/Program.cs index db9bb2a..aa922e5 100644 --- a/Clinical/Clinical.Api/Program.cs +++ b/Clinical/Clinical.Api/Program.cs @@ -95,14 +95,10 @@ Func<NpgsqlConnection> getConn { using var conn = getConn(); var result = await conn.GetPatientsAsync( - active.HasValue - ? active.Value - ? 1 - : 0 - : DBNull.Value, - familyName ?? (object)DBNull.Value, - givenName ?? (object)DBNull.Value, - gender ?? (object)DBNull.Value + active.HasValue ? (active.Value ? 1 : 0) : 0, + familyName ?? string.Empty, + givenName ?? string.Empty, + gender ?? string.Empty ) .ConfigureAwait(false); return result switch @@ -471,22 +467,22 @@ Func<NpgsqlConnection> getConn var result = await transaction .Insertfhir_ConditionAsync( - id: id, - clinicalstatus: request.ClinicalStatus, - verificationstatus: request.VerificationStatus, - category: request.Category, - severity: request.Severity, - codesystem: request.CodeSystem, - codevalue: request.CodeValue, - codedisplay: request.CodeDisplay, - subjectreference: patientId, - encounterreference: request.EncounterReference, - onsetdatetime: request.OnsetDateTime, - recordeddate: recordedDate, - recorderreference: request.RecorderReference, - notetext: request.NoteText, - lastupdated: now, - versionid: 1 + id, + request.ClinicalStatus, + request.VerificationStatus, + request.Category, + request.Severity, + request.CodeSystem, + request.CodeValue, + request.CodeDisplay, + patientId, + request.EncounterReference, + request.OnsetDateTime, + recordedDate, + request.RecorderReference, + request.NoteText, + now, + 1 ) .ConfigureAwait(false); diff --git a/Clinical/Clinical.Api/Queries/GetConditionsByPatient.generated.sql b/Clinical/Clinical.Api/Queries/GetConditionsByPatient.generated.sql deleted file mode 100644 index 703b770..0000000 --- a/Clinical/Clinical.Api/Queries/GetConditionsByPatient.generated.sql +++ /dev/null @@ -1 +0,0 @@ -SELECT fhir_Condition.Id, fhir_Condition.ClinicalStatus, fhir_Condition.VerificationStatus, fhir_Condition.Category, fhir_Condition.Severity, fhir_Condition.CodeSystem, fhir_Condition.CodeValue, fhir_Condition.CodeDisplay, fhir_Condition.SubjectReference, fhir_Condition.EncounterReference, fhir_Condition.OnsetDateTime, fhir_Condition.RecordedDate, fhir_Condition.RecorderReference, fhir_Condition.NoteText, fhir_Condition.LastUpdated, fhir_Condition.VersionId FROM fhir_Condition WHERE fhir_Condition.SubjectReference = @patientId ORDER BY fhir_Condition.RecordedDate DESC \ No newline at end of file diff --git a/Clinical/Clinical.Api/Queries/GetEncountersByPatient.generated.sql b/Clinical/Clinical.Api/Queries/GetEncountersByPatient.generated.sql deleted file mode 100644 index 6b4fd8d..0000000 --- a/Clinical/Clinical.Api/Queries/GetEncountersByPatient.generated.sql +++ /dev/null @@ -1 +0,0 @@ -SELECT fhir_Encounter.Id, fhir_Encounter.Status, fhir_Encounter.Class, fhir_Encounter.PatientId, fhir_Encounter.PractitionerId, fhir_Encounter.ServiceType, fhir_Encounter.ReasonCode, fhir_Encounter.PeriodStart, fhir_Encounter.PeriodEnd, fhir_Encounter.Notes, fhir_Encounter.LastUpdated, fhir_Encounter.VersionId FROM fhir_Encounter WHERE fhir_Encounter.PatientId = @patientId ORDER BY fhir_Encounter.PeriodStart DESC \ No newline at end of file diff --git a/Clinical/Clinical.Api/Queries/GetMedicationsByPatient.generated.sql b/Clinical/Clinical.Api/Queries/GetMedicationsByPatient.generated.sql deleted file mode 100644 index 2c77367..0000000 --- a/Clinical/Clinical.Api/Queries/GetMedicationsByPatient.generated.sql +++ /dev/null @@ -1 +0,0 @@ -SELECT fhir_MedicationRequest.Id, fhir_MedicationRequest.Status, fhir_MedicationRequest.Intent, fhir_MedicationRequest.PatientId, fhir_MedicationRequest.PractitionerId, fhir_MedicationRequest.EncounterId, fhir_MedicationRequest.MedicationCode, fhir_MedicationRequest.MedicationDisplay, fhir_MedicationRequest.DosageInstruction, fhir_MedicationRequest.Quantity, fhir_MedicationRequest.Unit, fhir_MedicationRequest.Refills, fhir_MedicationRequest.AuthoredOn, fhir_MedicationRequest.LastUpdated, fhir_MedicationRequest.VersionId FROM fhir_MedicationRequest WHERE fhir_MedicationRequest.PatientId = @patientId ORDER BY fhir_MedicationRequest.AuthoredOn DESC \ No newline at end of file diff --git a/Clinical/Clinical.Api/Queries/GetPatientById.generated.sql b/Clinical/Clinical.Api/Queries/GetPatientById.generated.sql deleted file mode 100644 index 23f0fd0..0000000 --- a/Clinical/Clinical.Api/Queries/GetPatientById.generated.sql +++ /dev/null @@ -1 +0,0 @@ -SELECT fhir_Patient.Id, fhir_Patient.Active, fhir_Patient.GivenName, fhir_Patient.FamilyName, fhir_Patient.BirthDate, fhir_Patient.Gender, fhir_Patient.Phone, fhir_Patient.Email, fhir_Patient.AddressLine, fhir_Patient.City, fhir_Patient.State, fhir_Patient.PostalCode, fhir_Patient.Country, fhir_Patient.LastUpdated, fhir_Patient.VersionId FROM fhir_Patient WHERE fhir_Patient.Id = @id \ No newline at end of file diff --git a/Clinical/Clinical.Api/Queries/GetPatients.generated.sql b/Clinical/Clinical.Api/Queries/GetPatients.generated.sql deleted file mode 100644 index a4ffa5b..0000000 --- a/Clinical/Clinical.Api/Queries/GetPatients.generated.sql +++ /dev/null @@ -1 +0,0 @@ -SELECT fhir_Patient.Id, fhir_Patient.Active, fhir_Patient.GivenName, fhir_Patient.FamilyName, fhir_Patient.BirthDate, fhir_Patient.Gender, fhir_Patient.Phone, fhir_Patient.Email, fhir_Patient.AddressLine, fhir_Patient.City, fhir_Patient.State, fhir_Patient.PostalCode, fhir_Patient.Country, fhir_Patient.LastUpdated, fhir_Patient.VersionId FROM fhir_Patient WHERE (@active IS NULL OR fhir_Patient.Active = @active) AND (@familyName IS NULL OR fhir_Patient.FamilyName LIKE '%' || @familyName || '%') AND (@givenName IS NULL OR fhir_Patient.GivenName LIKE '%' || @givenName || '%') AND (@gender IS NULL OR fhir_Patient.Gender = @gender) ORDER BY fhir_Patient.FamilyName , fhir_Patient.GivenName \ No newline at end of file diff --git a/Clinical/Clinical.Api/Queries/SearchPatients.generated.sql b/Clinical/Clinical.Api/Queries/SearchPatients.generated.sql deleted file mode 100644 index 2538861..0000000 --- a/Clinical/Clinical.Api/Queries/SearchPatients.generated.sql +++ /dev/null @@ -1 +0,0 @@ -SELECT fhir_Patient.Id, fhir_Patient.Active, fhir_Patient.GivenName, fhir_Patient.FamilyName, fhir_Patient.BirthDate, fhir_Patient.Gender, fhir_Patient.Phone, fhir_Patient.Email, fhir_Patient.AddressLine, fhir_Patient.City, fhir_Patient.State, fhir_Patient.PostalCode, fhir_Patient.Country, fhir_Patient.LastUpdated, fhir_Patient.VersionId FROM fhir_Patient WHERE fhir_Patient.GivenName LIKE @term OR fhir_Patient.FamilyName LIKE @term OR fhir_Patient.Email LIKE @term ORDER BY fhir_Patient.FamilyName , fhir_Patient.GivenName \ No newline at end of file diff --git a/Directory.Build.props b/Directory.Build.props index 3e7308b..7d0b04f 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -18,7 +18,7 @@ <Nullable>enable</Nullable> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> <WarningsAsErrors>IDE0301;IDE0063;IDE0005;MSB3243</WarningsAsErrors> - <NoWarn>CA1016;CA1303;EPS06;IDE0290;CA1062;CA1002;IDE0090;CA1017;CS8509;IDE0037;NU1900;NU1901;NU1902;NU1903;NU1904</NoWarn> + <NoWarn>CA1016;CA1303;EPS06;IDE0290;CA1062;CA1002;IDE0090;CA1017;CS8509;IDE0037;NU1900;NU1901;NU1902;NU1903;NU1904;CS1591</NoWarn> <WarningsNotAsErrors>$(WarningsNotAsErrors);CA1303;EPS06;CA1016;IDE0290;CA1062;CA1002;CA1017;CS8509;IDE0037</WarningsNotAsErrors> <WarningLevel>9999</WarningLevel> <EnableNETAnalyzers>true</EnableNETAnalyzers> diff --git a/Gatekeeper/Gatekeeper.Api.Tests/AuthorizationTests.cs b/Gatekeeper/Gatekeeper.Api.Tests/AuthorizationTests.cs index aac8f2e..ce92188 100644 --- a/Gatekeeper/Gatekeeper.Api.Tests/AuthorizationTests.cs +++ b/Gatekeeper/Gatekeeper.Api.Tests/AuthorizationTests.cs @@ -559,7 +559,7 @@ string permissionCode ) .ConfigureAwait(false); - if (grantResult is Result<int, SqlError>.Error<int, SqlError> grantErr) + if (grantResult is Result<Guid?, SqlError>.Error<Guid?, SqlError> grantErr) { throw new InvalidOperationException( $"Failed to insert grant: {grantErr.Value.Message}" diff --git a/Gatekeeper/Gatekeeper.Api/AuthorizationService.cs b/Gatekeeper/Gatekeeper.Api/AuthorizationService.cs index 3b3f4f3..4c1ff53 100644 --- a/Gatekeeper/Gatekeeper.Api/AuthorizationService.cs +++ b/Gatekeeper/Gatekeeper.Api/AuthorizationService.cs @@ -23,11 +23,11 @@ string now if (!string.IsNullOrEmpty(resourceType) && !string.IsNullOrEmpty(resourceId)) { var grantResult = await conn.CheckResourceGrantAsync( - now: now, - resource_id: resourceId, - user_id: userId, - resource_type: resourceType, - permission_code: permissionCode + userId, + permissionCode, + resourceType, + resourceId, + now ) .ConfigureAwait(false); @@ -43,6 +43,10 @@ string now foreach (var perm in permissions) { + if (perm.code is null) + { + continue; + } var matches = PermissionMatches(perm.code, permissionCode); if (!matches) { diff --git a/Gatekeeper/Gatekeeper.Api/DataProvider.json b/Gatekeeper/Gatekeeper.Api/DataProvider.json index 5aa5ad0..c227d3b 100644 --- a/Gatekeeper/Gatekeeper.Api/DataProvider.json +++ b/Gatekeeper/Gatekeeper.Api/DataProvider.json @@ -20,15 +20,15 @@ { "name": "GetSessionForRevoke", "sqlFile": "Sql/GetSessionForRevoke.sql" } ], "tables": [ - { "schema": "main", "name": "gk_user", "generateInsert": true, "excludeColumns": ["id"], "primaryKeyColumns": ["id"] }, - { "schema": "main", "name": "gk_credential", "generateInsert": true, "excludeColumns": ["id"], "primaryKeyColumns": ["id"] }, - { "schema": "main", "name": "gk_session", "generateInsert": true, "generateUpdate": true, "excludeColumns": ["id"], "primaryKeyColumns": ["id"] }, - { "schema": "main", "name": "gk_challenge", "generateInsert": true, "excludeColumns": ["id"], "primaryKeyColumns": ["id"] }, - { "schema": "main", "name": "gk_user_role", "generateInsert": true, "excludeColumns": [], "primaryKeyColumns": ["user_id", "role_id"] }, - { "schema": "main", "name": "gk_permission", "generateInsert": true, "excludeColumns": ["id"], "primaryKeyColumns": ["id"] }, - { "schema": "main", "name": "gk_resource_grant", "generateInsert": true, "excludeColumns": ["id"], "primaryKeyColumns": ["id"] }, - { "schema": "main", "name": "gk_role", "generateInsert": true, "excludeColumns": ["id"], "primaryKeyColumns": ["id"] }, - { "schema": "main", "name": "gk_role_permission", "generateInsert": true, "excludeColumns": [], "primaryKeyColumns": ["role_id", "permission_id"] } + { "schema": "public", "name": "gk_user", "generateInsert": true, "primaryKeyColumns": ["id"] }, + { "schema": "public", "name": "gk_credential", "generateInsert": true, "primaryKeyColumns": ["id"] }, + { "schema": "public", "name": "gk_session", "generateInsert": true, "generateUpdate": true, "primaryKeyColumns": ["id"] }, + { "schema": "public", "name": "gk_challenge", "generateInsert": true, "primaryKeyColumns": ["id"] }, + { "schema": "public", "name": "gk_user_role", "generateInsert": true, "primaryKeyColumns": ["user_id", "role_id"] }, + { "schema": "public", "name": "gk_permission", "generateInsert": true, "primaryKeyColumns": ["id"] }, + { "schema": "public", "name": "gk_resource_grant", "generateInsert": true, "primaryKeyColumns": ["id"] }, + { "schema": "public", "name": "gk_role", "generateInsert": true, "primaryKeyColumns": ["id"] }, + { "schema": "public", "name": "gk_role_permission", "generateInsert": true, "primaryKeyColumns": ["role_id", "permission_id"] } ], - "connectionString": "Data Source=gatekeeper.db" + "connectionString": "Host=localhost;Port=5432;Database=gatekeeper;Username=postgres;Password=changeme" } diff --git a/Gatekeeper/Gatekeeper.Api/Gatekeeper.Api.csproj b/Gatekeeper/Gatekeeper.Api/Gatekeeper.Api.csproj index 2b4494a..5a00f74 100644 --- a/Gatekeeper/Gatekeeper.Api/Gatekeeper.Api.csproj +++ b/Gatekeeper/Gatekeeper.Api/Gatekeeper.Api.csproj @@ -2,7 +2,7 @@ <PropertyGroup> <OutputType>Exe</OutputType> <PackageId>MelbourneDev.Gatekeeper</PackageId> - <NoWarn>CA1515;CA2100;RS1035;CA1508;CA2234;CA1819;CA2007;EPC12</NoWarn> + <NoWarn>$(NoWarn);CA1515;CA2100;RS1035;CA1508;CA2234;CA1819;CA2007;EPC12;CS1591</NoWarn> </PropertyGroup> <!-- Exclude Generated folder from default globbing - we include it explicitly in the target --> @@ -29,19 +29,10 @@ </Content> </ItemGroup> - <!-- Create database from YAML using Migration.Cli --> - <Target Name="CreateDatabaseSchema" BeforeTargets="TranspileLqlAndGenerateDataProvider"> - <Exec - Command="dotnet migration-cli --schema "$(MSBuildProjectDirectory)/gatekeeper-schema.yaml" --output "$(MSBuildProjectDirectory)/gatekeeper.db" --provider sqlite" - WorkingDirectory="$(MSBuildProjectDirectory)" - StandardOutputImportance="High" - StandardErrorImportance="High" - /> - </Target> - - <!-- Pre-compile: generate C# from SQL using external CLI --> + <!-- Pre-compile: generate C# from SQL using dataprovider-postgres CLI. + Requires a live Postgres with the gatekeeper schema migrated (see `make db-migrate`). --> <Target - Name="TranspileLqlAndGenerateDataProvider" + Name="GenerateDataProvider" BeforeTargets="BeforeCompile;CoreCompile" Inputs="$(MSBuildProjectDirectory)/DataProvider.json;@(AdditionalFiles)" Outputs="$(MSBuildProjectDirectory)/Generated/.timestamp" @@ -49,11 +40,10 @@ <RemoveDir Directories="$(MSBuildProjectDirectory)/Generated" /> <MakeDir Directories="$(MSBuildProjectDirectory)/Generated" /> <Exec - Command="dotnet dataprovider-sqlite --project-dir "$(MSBuildProjectDirectory)" --config "$(MSBuildProjectDirectory)/DataProvider.json" --out "$(MSBuildProjectDirectory)/Generated" --connection-type NpgsqlConnection" + Command="dotnet dataprovider-postgres --project-dir "$(MSBuildProjectDirectory)" --config "$(MSBuildProjectDirectory)/DataProvider.json" --out "$(MSBuildProjectDirectory)/Generated"" WorkingDirectory="$(MSBuildProjectDirectory)" StandardOutputImportance="High" StandardErrorImportance="High" - IgnoreExitCode="true" /> <Touch Files="$(MSBuildProjectDirectory)/Generated/.timestamp" AlwaysCreate="true" /> <ItemGroup> diff --git a/Gatekeeper/Gatekeeper.Api/Generated/.timestamp b/Gatekeeper/Gatekeeper.Api/Generated/.timestamp deleted file mode 100644 index e69de29..0000000 diff --git a/Gatekeeper/Gatekeeper.Api/Program.cs b/Gatekeeper/Gatekeeper.Api/Program.cs index 27ab8cc..4b6f7a2 100644 --- a/Gatekeeper/Gatekeeper.Api/Program.cs +++ b/Gatekeeper/Gatekeeper.Api/Program.cs @@ -87,7 +87,7 @@ static NpgsqlConnection OpenConnection(DbConfig db) var isNewUser = existingUser is not GetUserByEmailOk { Value.Count: > 0 }; var userId = isNewUser ? Guid.NewGuid().ToString() - : ((GetUserByEmailOk)existingUser).Value[0].id; + : ((GetUserByEmailOk)existingUser).Value[0].id ?? Guid.NewGuid().ToString(); if (isNewUser) { @@ -105,19 +105,20 @@ static NpgsqlConnection OpenConnection(DbConfig db) await tx.CommitAsync().ConfigureAwait(false); } - var existingCredentials = await conn.GetUserCredentialsAsync(userId) + var existingCredentials = await conn.GetUserCredentialsAsync(userId!) .ConfigureAwait(false); var excludeCredentials = existingCredentials switch { GetUserCredentialsOk ok => ok - .Value.Select(c => new PublicKeyCredentialDescriptor(Base64Url.Decode(c.id))) + .Value.Where(c => c.id is not null) + .Select(c => new PublicKeyCredentialDescriptor(Base64Url.Decode(c.id!))) .ToList(), GetUserCredentialsError _ => [], }; var user = new Fido2User { - Id = Encoding.UTF8.GetBytes(userId), + Id = Encoding.UTF8.GetBytes(userId!), Name = request.Email, DisplayName = request.DisplayName, }; @@ -270,7 +271,7 @@ ILogger<Program> logger Base64Url.Encode(cred.Id), storedChallenge.user_id, cred.PublicKey, - cred.SignCount, + (int?)cred.SignCount, cred.AaGuid.ToString(), cred.Type.ToString(), cred.Transports != null ? string.Join(",", cred.Transports) : null, @@ -306,12 +307,12 @@ ILogger<Program> logger var rolesResult = await conn.GetUserRolesAsync(storedChallenge.user_id, now) .ConfigureAwait(false); var roles = rolesResult is GetUserRolesOk rolesOk - ? rolesOk.Value.Select(r => r.name).ToList() - : []; + ? rolesOk.Value.Select(r => r.name).Where(n => n is not null).Select(n => n!).ToList() + : new List<string>(); // Generate JWT var token = TokenService.CreateToken( - storedChallenge.user_id, + storedChallenge.user_id ?? string.Empty, user?.display_name, user?.email, roles, @@ -384,8 +385,8 @@ ILogger<Program> logger { AssertionResponse = request.AssertionResponse, OriginalOptions = options, - StoredPublicKey = storedCred.public_key, - StoredSignatureCounter = (uint)storedCred.sign_count, + StoredPublicKey = storedCred.public_key ?? Array.Empty<byte>(), + StoredSignatureCounter = (uint)(storedCred.sign_count ?? 0), IsUserHandleOwnerOfCredentialIdCallback = (args, _) => { var userIdFromHandle = Encoding.UTF8.GetString(args.UserHandle); @@ -411,25 +412,25 @@ UPDATE gk_credential using var userUpdateCmd = conn.CreateCommand(); userUpdateCmd.CommandText = "UPDATE gk_user SET last_login_at = @now WHERE id = @id"; userUpdateCmd.Parameters.AddWithValue("@now", now); - userUpdateCmd.Parameters.AddWithValue("@id", storedCred.user_id); + userUpdateCmd.Parameters.AddWithValue("@id", (object?)storedCred.user_id ?? DBNull.Value); await userUpdateCmd.ExecuteNonQueryAsync().ConfigureAwait(false); // Get user info for token - var userResult = await conn.GetUserByIdAsync(storedCred.user_id).ConfigureAwait(false); + var userResult = await conn.GetUserByIdAsync(storedCred.user_id ?? string.Empty).ConfigureAwait(false); var user = userResult is GetUserByIdOk { Value.Count: > 0 } userOk ? userOk.Value[0] : null; // Get user roles - var rolesResult = await conn.GetUserRolesAsync(storedCred.user_id, now) + var rolesResult = await conn.GetUserRolesAsync(storedCred.user_id ?? string.Empty, now) .ConfigureAwait(false); var roles = rolesResult is GetUserRolesOk rolesOk - ? rolesOk.Value.Select(r => r.name).ToList() - : []; + ? rolesOk.Value.Select(r => r.name).Where(n => n is not null).Select(n => n!).ToList() + : new List<string>(); // Generate JWT var token = TokenService.CreateToken( - storedCred.user_id, + storedCred.user_id ?? string.Empty, user?.display_name, user?.email, roles, diff --git a/Gatekeeper/Gatekeeper.Api/Sql/CheckPermission.sql b/Gatekeeper/Gatekeeper.Api/Sql/CheckPermission.sql index 1af577b..2d606f1 100644 --- a/Gatekeeper/Gatekeeper.Api/Sql/CheckPermission.sql +++ b/Gatekeeper/Gatekeeper.Api/Sql/CheckPermission.sql @@ -21,4 +21,4 @@ WHERE p.code = @permissionCode AND (up.expires_at IS NULL OR up.expires_at > @now) ) ) -LIMIT 1; +LIMIT 1 diff --git a/Gatekeeper/Gatekeeper.Api/Sql/CheckResourceGrant.sql b/Gatekeeper/Gatekeeper.Api/Sql/CheckResourceGrant.sql index 1d5f24f..ec8489e 100644 --- a/Gatekeeper/Gatekeeper.Api/Sql/CheckResourceGrant.sql +++ b/Gatekeeper/Gatekeeper.Api/Sql/CheckResourceGrant.sql @@ -7,4 +7,4 @@ WHERE rg.user_id = @user_id AND rg.resource_type = @resource_type AND rg.resource_id = @resource_id AND p.code = @permission_code - AND (rg.expires_at IS NULL OR rg.expires_at > @now); + AND (rg.expires_at IS NULL OR rg.expires_at > @now) diff --git a/Gatekeeper/Gatekeeper.Api/Sql/CountSystemRoles.sql b/Gatekeeper/Gatekeeper.Api/Sql/CountSystemRoles.sql index e1e5836..ccad080 100644 --- a/Gatekeeper/Gatekeeper.Api/Sql/CountSystemRoles.sql +++ b/Gatekeeper/Gatekeeper.Api/Sql/CountSystemRoles.sql @@ -1,2 +1,2 @@ -- name: CountSystemRoles -SELECT COUNT(*) as cnt FROM gk_role WHERE is_system = true; +SELECT COUNT(*) as cnt FROM gk_role WHERE is_system = true diff --git a/Gatekeeper/Gatekeeper.Api/Sql/GetActivePolicies.sql b/Gatekeeper/Gatekeeper.Api/Sql/GetActivePolicies.sql index 2e7800b..39bd443 100644 --- a/Gatekeeper/Gatekeeper.Api/Sql/GetActivePolicies.sql +++ b/Gatekeeper/Gatekeeper.Api/Sql/GetActivePolicies.sql @@ -4,4 +4,4 @@ FROM gk_policy WHERE is_active = true AND (resource_type = @resource_type OR resource_type = '*') AND (action = @action OR action = '*') -ORDER BY priority DESC; +ORDER BY priority DESC diff --git a/Gatekeeper/Gatekeeper.Api/Sql/GetAllPermissions.sql b/Gatekeeper/Gatekeeper.Api/Sql/GetAllPermissions.sql index a2753da..9272aad 100644 --- a/Gatekeeper/Gatekeeper.Api/Sql/GetAllPermissions.sql +++ b/Gatekeeper/Gatekeeper.Api/Sql/GetAllPermissions.sql @@ -1,4 +1,4 @@ -- name: GetAllPermissions SELECT id, code, resource_type, action, description, created_at FROM gk_permission -ORDER BY resource_type, action; +ORDER BY resource_type, action diff --git a/Gatekeeper/Gatekeeper.Api/Sql/GetAllRoles.sql b/Gatekeeper/Gatekeeper.Api/Sql/GetAllRoles.sql index 00a8e9b..2c087d4 100644 --- a/Gatekeeper/Gatekeeper.Api/Sql/GetAllRoles.sql +++ b/Gatekeeper/Gatekeeper.Api/Sql/GetAllRoles.sql @@ -1,4 +1,4 @@ -- name: GetAllRoles SELECT id, name, description, is_system, created_at, parent_role_id FROM gk_role -ORDER BY name; +ORDER BY name diff --git a/Gatekeeper/Gatekeeper.Api/Sql/GetAllUsers.sql b/Gatekeeper/Gatekeeper.Api/Sql/GetAllUsers.sql index f3120c5..173fd7c 100644 --- a/Gatekeeper/Gatekeeper.Api/Sql/GetAllUsers.sql +++ b/Gatekeeper/Gatekeeper.Api/Sql/GetAllUsers.sql @@ -1,4 +1,4 @@ -- name: GetAllUsers SELECT id, display_name, email, created_at, last_login_at, is_active FROM gk_user -ORDER BY display_name; +ORDER BY display_name diff --git a/Gatekeeper/Gatekeeper.Api/Sql/GetChallengeById.sql b/Gatekeeper/Gatekeeper.Api/Sql/GetChallengeById.sql index ebb2cd0..344a195 100644 --- a/Gatekeeper/Gatekeeper.Api/Sql/GetChallengeById.sql +++ b/Gatekeeper/Gatekeeper.Api/Sql/GetChallengeById.sql @@ -1,4 +1,4 @@ -- name: GetChallengeById SELECT id, user_id, challenge, type, created_at, expires_at FROM gk_challenge -WHERE id = @id AND expires_at > @now; +WHERE id = @id AND expires_at > @now diff --git a/Gatekeeper/Gatekeeper.Api/Sql/GetCredentialById.sql b/Gatekeeper/Gatekeeper.Api/Sql/GetCredentialById.sql index 07106e6..e15905c 100644 --- a/Gatekeeper/Gatekeeper.Api/Sql/GetCredentialById.sql +++ b/Gatekeeper/Gatekeeper.Api/Sql/GetCredentialById.sql @@ -4,4 +4,4 @@ SELECT c.id, c.user_id, c.public_key, c.sign_count, c.aaguid, c.credential_type, u.display_name, u.email FROM gk_credential c JOIN gk_user u ON c.user_id = u.id -WHERE c.id = @id AND u.is_active = true; +WHERE c.id = @id AND u.is_active = true diff --git a/Gatekeeper/Gatekeeper.Api/Sql/GetCredentialsByUserId.sql b/Gatekeeper/Gatekeeper.Api/Sql/GetCredentialsByUserId.sql index 2e4ccf2..ff8f83a 100644 --- a/Gatekeeper/Gatekeeper.Api/Sql/GetCredentialsByUserId.sql +++ b/Gatekeeper/Gatekeeper.Api/Sql/GetCredentialsByUserId.sql @@ -3,4 +3,4 @@ SELECT id, user_id, public_key, sign_count, aaguid, credential_type, transports, attestation_format, created_at, last_used_at, device_name, is_backup_eligible, is_backed_up FROM gk_credential -WHERE user_id = @userId; +WHERE user_id = @userId diff --git a/Gatekeeper/Gatekeeper.Api/Sql/GetPermissionByCode.sql b/Gatekeeper/Gatekeeper.Api/Sql/GetPermissionByCode.sql index cfd75b9..7bb724f 100644 --- a/Gatekeeper/Gatekeeper.Api/Sql/GetPermissionByCode.sql +++ b/Gatekeeper/Gatekeeper.Api/Sql/GetPermissionByCode.sql @@ -1,4 +1,4 @@ -- name: GetPermissionByCode SELECT id, code, resource_type, action, description, created_at FROM gk_permission -WHERE code = @code; +WHERE code = @code diff --git a/Gatekeeper/Gatekeeper.Api/Sql/GetRolePermissions.sql b/Gatekeeper/Gatekeeper.Api/Sql/GetRolePermissions.sql index 6b80a6c..933ce01 100644 --- a/Gatekeeper/Gatekeeper.Api/Sql/GetRolePermissions.sql +++ b/Gatekeeper/Gatekeeper.Api/Sql/GetRolePermissions.sql @@ -3,4 +3,4 @@ SELECT p.id, p.code, p.resource_type, p.action, p.description, p.created_at, rp.granted_at FROM gk_permission p JOIN gk_role_permission rp ON p.id = rp.permission_id -WHERE rp.role_id = @roleId; +WHERE rp.role_id = @roleId diff --git a/Gatekeeper/Gatekeeper.Api/Sql/GetSessionById.sql b/Gatekeeper/Gatekeeper.Api/Sql/GetSessionById.sql index 27cf52b..4d71809 100644 --- a/Gatekeeper/Gatekeeper.Api/Sql/GetSessionById.sql +++ b/Gatekeeper/Gatekeeper.Api/Sql/GetSessionById.sql @@ -4,4 +4,4 @@ SELECT s.id, s.user_id, s.credential_id, s.created_at, s.expires_at, s.last_acti u.display_name, u.email FROM gk_session s JOIN gk_user u ON s.user_id = u.id -WHERE s.id = @id AND s.is_revoked = false AND s.expires_at > @now AND u.is_active = true; +WHERE s.id = @id AND s.is_revoked = false AND s.expires_at > @now AND u.is_active = true diff --git a/Gatekeeper/Gatekeeper.Api/Sql/GetSessionForRevoke.sql b/Gatekeeper/Gatekeeper.Api/Sql/GetSessionForRevoke.sql index 19e281e..92dd7e5 100644 --- a/Gatekeeper/Gatekeeper.Api/Sql/GetSessionForRevoke.sql +++ b/Gatekeeper/Gatekeeper.Api/Sql/GetSessionForRevoke.sql @@ -3,4 +3,4 @@ SELECT id, user_id, credential_id, created_at, expires_at, last_activity_at, ip_address, user_agent, is_revoked FROM gk_session -WHERE id = @jti; +WHERE id = @jti diff --git a/Gatekeeper/Gatekeeper.Api/Sql/GetSessionRevoked.sql b/Gatekeeper/Gatekeeper.Api/Sql/GetSessionRevoked.sql index 58f8e00..1525177 100644 --- a/Gatekeeper/Gatekeeper.Api/Sql/GetSessionRevoked.sql +++ b/Gatekeeper/Gatekeeper.Api/Sql/GetSessionRevoked.sql @@ -1,3 +1,3 @@ -- Gets the revocation status of a session -- @jti: The session ID (JWT ID) to check -SELECT is_revoked FROM gk_session WHERE id = @jti; +SELECT is_revoked FROM gk_session WHERE id = @jti diff --git a/Gatekeeper/Gatekeeper.Api/Sql/GetUserByEmail.sql b/Gatekeeper/Gatekeeper.Api/Sql/GetUserByEmail.sql index 3d2ed92..6532c54 100644 --- a/Gatekeeper/Gatekeeper.Api/Sql/GetUserByEmail.sql +++ b/Gatekeeper/Gatekeeper.Api/Sql/GetUserByEmail.sql @@ -1,4 +1,4 @@ -- name: GetUserByEmail SELECT id, display_name, email, created_at, last_login_at, is_active, metadata FROM gk_user -WHERE email = @email AND is_active = true; +WHERE email = @email AND is_active = true diff --git a/Gatekeeper/Gatekeeper.Api/Sql/GetUserById.sql b/Gatekeeper/Gatekeeper.Api/Sql/GetUserById.sql index c442b58..3e4f33a 100644 --- a/Gatekeeper/Gatekeeper.Api/Sql/GetUserById.sql +++ b/Gatekeeper/Gatekeeper.Api/Sql/GetUserById.sql @@ -1,4 +1,4 @@ -- name: GetUserById SELECT id, display_name, email, created_at, last_login_at, is_active, metadata FROM gk_user -WHERE id = @id; +WHERE id = @id diff --git a/Gatekeeper/Gatekeeper.Api/Sql/GetUserCredentials.sql b/Gatekeeper/Gatekeeper.Api/Sql/GetUserCredentials.sql index d47001c..1b6c59f 100644 --- a/Gatekeeper/Gatekeeper.Api/Sql/GetUserCredentials.sql +++ b/Gatekeeper/Gatekeeper.Api/Sql/GetUserCredentials.sql @@ -2,4 +2,4 @@ SELECT id, user_id, public_key, sign_count, aaguid, credential_type, transports, attestation_format, created_at, last_used_at, device_name, is_backup_eligible, is_backed_up FROM gk_credential -WHERE user_id = @user_id; +WHERE user_id = @user_id diff --git a/Gatekeeper/Gatekeeper.Api/Sql/GetUserPermissions.sql b/Gatekeeper/Gatekeeper.Api/Sql/GetUserPermissions.sql index 249de39..cdf9225 100644 --- a/Gatekeeper/Gatekeeper.Api/Sql/GetUserPermissions.sql +++ b/Gatekeeper/Gatekeeper.Api/Sql/GetUserPermissions.sql @@ -23,4 +23,4 @@ SELECT p.id, p.code, p.resource_type, p.action, p.description, FROM gk_user_permission up JOIN gk_permission p ON up.permission_id = p.id WHERE up.user_id = @user_id - AND (up.expires_at IS NULL OR up.expires_at > @now); + AND (up.expires_at IS NULL OR up.expires_at > @now) diff --git a/Gatekeeper/Gatekeeper.Api/Sql/GetUserRoles.sql b/Gatekeeper/Gatekeeper.Api/Sql/GetUserRoles.sql index 63b6b88..f2675ed 100644 --- a/Gatekeeper/Gatekeeper.Api/Sql/GetUserRoles.sql +++ b/Gatekeeper/Gatekeeper.Api/Sql/GetUserRoles.sql @@ -3,4 +3,4 @@ SELECT r.id, r.name, r.description, r.is_system, ur.granted_at, ur.expires_at FROM gk_user_role ur JOIN gk_role r ON ur.role_id = r.id WHERE ur.user_id = @user_id - AND (ur.expires_at IS NULL OR ur.expires_at > @now); + AND (ur.expires_at IS NULL OR ur.expires_at > @now) diff --git a/Gatekeeper/Gatekeeper.Api/Sql/RevokeSession.sql b/Gatekeeper/Gatekeeper.Api/Sql/RevokeSession.sql index 71df552..4a37a3b 100644 --- a/Gatekeeper/Gatekeeper.Api/Sql/RevokeSession.sql +++ b/Gatekeeper/Gatekeeper.Api/Sql/RevokeSession.sql @@ -1,3 +1,3 @@ -- Revokes a session by setting is_revoked = true -- @jti: The session ID (JWT ID) to revoke -UPDATE gk_session SET is_revoked = true WHERE id = @jti RETURNING id, is_revoked; +UPDATE gk_session SET is_revoked = true WHERE id = @jti RETURNING id, is_revoked diff --git a/ICD10/.gitignore b/ICD10/.gitignore index 09530ff..64e63e3 100644 --- a/ICD10/.gitignore +++ b/ICD10/.gitignore @@ -1,8 +1,3 @@ -# Generated files -*.generated.sql -*.db -Generated/ - # Python __pycache__/ *.pyc diff --git a/ICD10/ICD10.Api/DataProvider.json b/ICD10/ICD10.Api/DataProvider.json index ffff099..f377c0d 100644 --- a/ICD10/ICD10.Api/DataProvider.json +++ b/ICD10/ICD10.Api/DataProvider.json @@ -1,136 +1,145 @@ { - "queries": [ - { - "name": "GetChapters", - "sqlFile": "Queries/GetChapters.generated.sql" - }, - { - "name": "GetBlocksByChapter", - "sqlFile": "Queries/GetBlocksByChapter.generated.sql" - }, - { - "name": "GetCategoriesByBlock", - "sqlFile": "Queries/GetCategoriesByBlock.generated.sql" - }, - { - "name": "GetCodesByCategory", - "sqlFile": "Queries/GetCodesByCategory.generated.sql" - }, - { - "name": "GetCodeByCode", - "sqlFile": "Queries/GetCodeByCode.generated.sql" - }, - { - "name": "GetAchiBlocks", - "sqlFile": "Queries/GetAchiBlocks.generated.sql" - }, - { - "name": "GetAchiCodesByBlock", - "sqlFile": "Queries/GetAchiCodesByBlock.generated.sql" - }, - { - "name": "GetAchiCodeByCode", - "sqlFile": "Queries/GetAchiCodeByCode.generated.sql" - }, - { - "name": "GetCodeEmbedding", - "sqlFile": "Queries/GetCodeEmbedding.generated.sql" - }, - { - "name": "GetAllCodeEmbeddings", - "sqlFile": "Queries/GetAllCodeEmbeddings.generated.sql" - }, - { - "name": "SearchAchiCodes", - "sqlFile": "Queries/SearchAchiCodes.sql" - }, - { - "name": "SearchIcd10Codes", - "sqlFile": "Queries/SearchIcd10Codes.sql" - } - ], - "tables": [ - { - "schema": "main", - "name": "icd10_chapter", - "generateInsert": false, - "generateUpdate": false, - "generateDelete": false, - "excludeColumns": ["Id"], - "primaryKeyColumns": ["Id"] - }, - { - "schema": "main", - "name": "icd10_block", - "generateInsert": false, - "generateUpdate": false, - "generateDelete": false, - "excludeColumns": ["Id"], - "primaryKeyColumns": ["Id"] - }, - { - "schema": "main", - "name": "icd10_category", - "generateInsert": false, - "generateUpdate": false, - "generateDelete": false, - "excludeColumns": ["Id"], - "primaryKeyColumns": ["Id"] - }, - { - "schema": "main", - "name": "icd10_code", - "generateInsert": false, - "generateUpdate": false, - "generateDelete": false, - "excludeColumns": ["Id"], - "primaryKeyColumns": ["Id"] - }, - { - "schema": "main", - "name": "icd10_code_embedding", - "generateInsert": false, - "generateUpdate": true, - "generateDelete": false, - "excludeColumns": ["Id"], - "primaryKeyColumns": ["Id"] - }, - { - "schema": "main", - "name": "achi_block", - "generateInsert": false, - "generateUpdate": false, - "generateDelete": false, - "excludeColumns": ["Id"], - "primaryKeyColumns": ["Id"] - }, - { - "schema": "main", - "name": "achi_code", - "generateInsert": false, - "generateUpdate": false, - "generateDelete": false, - "excludeColumns": ["Id"], - "primaryKeyColumns": ["Id"] - }, - { - "schema": "main", - "name": "achi_code_embedding", - "generateInsert": false, - "generateUpdate": true, - "generateDelete": false, - "excludeColumns": ["Id"], - "primaryKeyColumns": ["Id"] - }, - { - "schema": "main", - "name": "user_search_history", - "generateInsert": false, - "generateUpdate": false, - "generateDelete": false, - "excludeColumns": ["Id"], - "primaryKeyColumns": ["Id"] - } - ], - "connectionString": "Data Source=icd10.db" -} + "queries": [ + { + "name": "GetChapters", + "sqlFile": "Queries/GetChapters.generated.sql" + }, + { + "name": "GetBlocksByChapter", + "sqlFile": "Queries/GetBlocksByChapter.generated.sql" + }, + { + "name": "GetCategoriesByBlock", + "sqlFile": "Queries/GetCategoriesByBlock.generated.sql" + }, + { + "name": "GetCodesByCategory", + "sqlFile": "Queries/GetCodesByCategory.generated.sql" + }, + { + "name": "GetCodeByCode", + "sqlFile": "Queries/GetCodeByCode.generated.sql" + }, + { + "name": "GetAchiBlocks", + "sqlFile": "Queries/GetAchiBlocks.generated.sql" + }, + { + "name": "GetAchiCodesByBlock", + "sqlFile": "Queries/GetAchiCodesByBlock.generated.sql" + }, + { + "name": "GetAchiCodeByCode", + "sqlFile": "Queries/GetAchiCodeByCode.generated.sql" + }, + { + "name": "GetCodeEmbedding", + "sqlFile": "Queries/GetCodeEmbedding.generated.sql" + }, + { + "name": "GetAllCodeEmbeddings", + "sqlFile": "Queries/GetAllCodeEmbeddings.generated.sql" + }, + { + "name": "SearchAchiCodes", + "sqlFile": "Queries/SearchAchiCodes.sql" + }, + { + "name": "SearchIcd10Codes", + "sqlFile": "Queries/SearchIcd10Codes.sql" + } + ], + "tables": [ + { + "schema": "public", + "name": "icd10_chapter", + "generateInsert": false, + "generateUpdate": false, + "generateDelete": false, + "primaryKeyColumns": [ + "Id" + ] + }, + { + "schema": "public", + "name": "icd10_block", + "generateInsert": false, + "generateUpdate": false, + "generateDelete": false, + "primaryKeyColumns": [ + "Id" + ] + }, + { + "schema": "public", + "name": "icd10_category", + "generateInsert": false, + "generateUpdate": false, + "generateDelete": false, + "primaryKeyColumns": [ + "Id" + ] + }, + { + "schema": "public", + "name": "icd10_code", + "generateInsert": false, + "generateUpdate": false, + "generateDelete": false, + "primaryKeyColumns": [ + "Id" + ] + }, + { + "schema": "public", + "name": "icd10_code_embedding", + "generateInsert": false, + "generateUpdate": true, + "generateDelete": false, + "primaryKeyColumns": [ + "Id" + ] + }, + { + "schema": "public", + "name": "achi_block", + "generateInsert": false, + "generateUpdate": false, + "generateDelete": false, + "primaryKeyColumns": [ + "Id" + ] + }, + { + "schema": "public", + "name": "achi_code", + "generateInsert": false, + "generateUpdate": false, + "generateDelete": false, + "primaryKeyColumns": [ + "Id" + ] + }, + { + "schema": "public", + "name": "achi_code_embedding", + "generateInsert": false, + "generateUpdate": true, + "generateDelete": false, + "primaryKeyColumns": [ + "Id" + ] + }, + { + "schema": "public", + "name": "user_search_history", + "generateInsert": false, + "generateUpdate": false, + "generateDelete": false, + "primaryKeyColumns": [ + "Id" + ] + } + ], + "connectionString": "Host=localhost;Port=5432;Database=icd10;Username=postgres;Password=changeme" +} \ No newline at end of file diff --git a/ICD10/ICD10.Api/ICD10.Api.csproj b/ICD10/ICD10.Api/ICD10.Api.csproj index 32e9694..08e0add 100644 --- a/ICD10/ICD10.Api/ICD10.Api.csproj +++ b/ICD10/ICD10.Api/ICD10.Api.csproj @@ -1,7 +1,7 @@ <Project Sdk="Microsoft.NET.Sdk.Web"> <PropertyGroup> <OutputType>Exe</OutputType> - <NoWarn>CA1515;CA2100;RS1035;CA1508;CA2234</NoWarn> + <NoWarn>$(NoWarn);CA1515;CA2100;RS1035;CA1508;CA2234;CS1591</NoWarn> <EnableLqlTranspile>true</EnableLqlTranspile> </PropertyGroup> @@ -29,25 +29,12 @@ <Content Include="icd10-schema.yaml"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </Content> - <!-- SQLite database for local testing --> - <Content Include="icd10.db" Condition="Exists('icd10.db')"> - <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> - </Content> </ItemGroup> - <!-- Create database from YAML using Migration.Cli (installed as dotnet tool) --> - <Target Name="CreateDatabaseSchema" BeforeTargets="TranspileLqlAndGenerateDataProvider"> - <Exec - Command="dotnet migration-cli --schema "$(MSBuildProjectDirectory)/icd10-schema.yaml" --output "$(MSBuildProjectDirectory)/icd10.db" --provider sqlite" - WorkingDirectory="$(MSBuildProjectDirectory)" - StandardOutputImportance="High" - StandardErrorImportance="High" - /> - </Target> - - <!-- Pre-compile: transpile LQL to SQL, then generate C# from SQL using CLI tools --> + <!-- Pre-compile: transpile LQL to SQL, then generate C# via dataprovider-postgres CLI. + Requires a live Postgres with the icd10 schema migrated (see `make db-migrate`). --> <Target - Name="TranspileLqlAndGenerateDataProvider" + Name="GenerateDataProvider" BeforeTargets="BeforeCompile;CoreCompile" Inputs="$(MSBuildProjectDirectory)/DataProvider.json;@(AdditionalFiles);@(LqlFiles)" Outputs="$(MSBuildProjectDirectory)/Generated/.timestamp" @@ -59,19 +46,17 @@ </ItemGroup> <Message Importance="High" Text="Transpiling LQL files (@(LqlFiles))" /> <Exec - Command="dotnet lqlcli-sqlite --input "%(LqlFiles.Identity)" --output "%(LqlFiles.RootDir)%(LqlFiles.Directory)%(LqlFiles.Filename).generated.sql"" + Command="dotnet lql-postgres --input "%(LqlFiles.Identity)" --output "%(LqlFiles.RootDir)%(LqlFiles.Directory)%(LqlFiles.Filename).generated.sql"" Condition="'$(EnableLqlTranspile)' == 'true' and @(LqlFiles) != ''" WorkingDirectory="$(MSBuildProjectDirectory)" StandardOutputImportance="High" StandardErrorImportance="High" - ContinueOnError="WarnAndContinue" /> <Exec - Command="dotnet dataprovider-sqlite --project-dir "$(MSBuildProjectDirectory)" --config "$(MSBuildProjectDirectory)/DataProvider.json" --out "$(MSBuildProjectDirectory)/Generated" --connection-type NpgsqlConnection" + Command="dotnet dataprovider-postgres --project-dir "$(MSBuildProjectDirectory)" --config "$(MSBuildProjectDirectory)/DataProvider.json" --out "$(MSBuildProjectDirectory)/Generated"" WorkingDirectory="$(MSBuildProjectDirectory)" StandardOutputImportance="High" StandardErrorImportance="High" - IgnoreExitCode="true" /> <Touch Files="$(MSBuildProjectDirectory)/Generated/.timestamp" AlwaysCreate="true" /> <ItemGroup> diff --git a/ICD10/ICD10.Api/Program.cs b/ICD10/ICD10.Api/Program.cs index ba50c33..acb7282 100644 --- a/ICD10/ICD10.Api/Program.cs +++ b/ICD10/ICD10.Api/Program.cs @@ -489,16 +489,16 @@ LIMIT @limit static GetCodeByCode EnrichCodeWithDerivedHierarchy(GetCodeByCode code) { var (chapterNum, chapterTitle) = string.IsNullOrEmpty(code.ChapterNumber) - ? Icd10Chapters.GetChapter(code.Code) + ? Icd10Chapters.GetChapter(code.Code ?? string.Empty) : (code.ChapterNumber, code.ChapterTitle ?? ""); var categoryCode = string.IsNullOrEmpty(code.CategoryCode) - ? Icd10Chapters.GetCategory(code.Code) + ? Icd10Chapters.GetCategory(code.Code ?? string.Empty) : code.CategoryCode; // Derive block from category when not in DB - use category code as pseudo-block var (blockCode, blockTitle) = string.IsNullOrEmpty(code.BlockCode) - ? Icd10Chapters.GetBlock(code.Code) + ? Icd10Chapters.GetBlock(code.Code ?? string.Empty) : (code.BlockCode, code.BlockTitle ?? ""); return code with diff --git a/ICD10/ICD10.Api/Queries/SearchAchiCodes.sql b/ICD10/ICD10.Api/Queries/SearchAchiCodes.sql index c60dbed..4c09bb1 100644 --- a/ICD10/ICD10.Api/Queries/SearchAchiCodes.sql +++ b/ICD10/ICD10.Api/Queries/SearchAchiCodes.sql @@ -1,5 +1,5 @@ -SELECT Id, BlockId, Code, ShortDescription, LongDescription, Billable +SELECT "Id", "BlockId", "Code", "ShortDescription", "LongDescription", "Billable" FROM achi_code -WHERE Code ILIKE @term OR ShortDescription ILIKE @term OR LongDescription ILIKE @term -ORDER BY Code +WHERE "Code" ILIKE @term OR "ShortDescription" ILIKE @term OR "LongDescription" ILIKE @term +ORDER BY "Code" LIMIT @limit diff --git a/ICD10/ICD10.Api/Queries/SearchIcd10Codes.sql b/ICD10/ICD10.Api/Queries/SearchIcd10Codes.sql index 214060c..386a6fb 100644 --- a/ICD10/ICD10.Api/Queries/SearchIcd10Codes.sql +++ b/ICD10/ICD10.Api/Queries/SearchIcd10Codes.sql @@ -1,12 +1,12 @@ -SELECT c.Id, c.Code, c.ShortDescription, c.LongDescription, c.Billable, - cat.CategoryCode, cat.Title AS CategoryTitle, - b.BlockCode, b.Title AS BlockTitle, - ch.ChapterNumber, ch.Title AS ChapterTitle, - c.InclusionTerms, c.ExclusionTerms, c.CodeAlso, c.CodeFirst, c.Synonyms, c.Edition +SELECT c."Id", c."Code", c."ShortDescription", c."LongDescription", c."Billable", + cat."CategoryCode", cat."Title" AS "CategoryTitle", + b."BlockCode", b."Title" AS "BlockTitle", + ch."ChapterNumber", ch."Title" AS "ChapterTitle", + c."InclusionTerms", c."ExclusionTerms", c."CodeAlso", c."CodeFirst", c."Synonyms", c."Edition" FROM icd10_code c -LEFT JOIN icd10_category cat ON c.CategoryId = cat.Id -LEFT JOIN icd10_block b ON cat.BlockId = b.Id -LEFT JOIN icd10_chapter ch ON b.ChapterId = ch.Id -WHERE c.Code ILIKE @term OR c.ShortDescription ILIKE @term OR c.LongDescription ILIKE @term -ORDER BY c.Code +LEFT JOIN icd10_category cat ON c."CategoryId" = cat."Id" +LEFT JOIN icd10_block b ON cat."BlockId" = b."Id" +LEFT JOIN icd10_chapter ch ON b."ChapterId" = ch."Id" +WHERE c."Code" ILIKE @term OR c."ShortDescription" ILIKE @term OR c."LongDescription" ILIKE @term +ORDER BY c."Code" LIMIT @limit diff --git a/Makefile b/Makefile index 568753e..30d2c15 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ # Cross-platform: Linux, macOS, Windows (via GNU Make) # ============================================================================= -.PHONY: build test lint fmt fmt-check clean check ci coverage coverage-check setup +.PHONY: build test lint fmt fmt-check clean check ci coverage coverage-check setup db-up db-down db-reset db-wait db-migrate # ----------------------------------------------------------------------------- # OS Detection @@ -23,17 +23,24 @@ endif # Coverage threshold (override in CI via env var or per-repo) COVERAGE_THRESHOLD ?= 80 +# Postgres dev database (docker compose). Override in CI via env vars. +DB_COMPOSE_FILE ?= docker/docker-compose.db.yml +DB_PASSWORD ?= changeme +DB_HOST ?= localhost +DB_PORT ?= 5432 +PG_BASE_URL ?= Host=$(DB_HOST);Port=$(DB_PORT);Username=postgres;Password=$(DB_PASSWORD) + # ============================================================================= # PRIMARY TARGETS # ============================================================================= -## build: Compile/assemble all artifacts -build: +## build: Compile/assemble all artifacts (requires running Postgres + migrated schemas) +build: db-migrate @echo "==> Building..." dotnet build HealthcareSamples.sln --configuration Release ## test: Run full test suite with coverage -test: +test: db-migrate @echo "==> Testing..." dotnet test HealthcareSamples.sln --configuration Release \ --settings coverlet.runsettings \ @@ -42,7 +49,7 @@ test: --verbosity normal ## lint: Run all linters (fails on any warning) -lint: fmt-check +lint: fmt-check db-migrate @echo "==> Linting..." dotnet build HealthcareSamples.sln --configuration Release @@ -104,6 +111,52 @@ setup: dotnet restore @echo "==> Setup complete. Run 'make ci' to validate." +# ============================================================================= +# DEV DATABASE (Postgres via docker compose) +# ============================================================================= + +## db-up: Start Postgres (pgvector) container in background +db-up: + @echo "==> Starting Postgres..." + DB_PASSWORD=$(DB_PASSWORD) docker compose -f $(DB_COMPOSE_FILE) up -d + @$(MAKE) db-wait + +## db-down: Stop and remove Postgres container (preserves volume) +db-down: + @echo "==> Stopping Postgres..." + docker compose -f $(DB_COMPOSE_FILE) down + +## db-reset: Destroy DB volume and recreate from init scripts +db-reset: + @echo "==> Resetting Postgres (DESTRUCTIVE)..." + docker compose -f $(DB_COMPOSE_FILE) down -v + DB_PASSWORD=$(DB_PASSWORD) docker compose -f $(DB_COMPOSE_FILE) up -d + @$(MAKE) db-wait + +## db-wait: Block until Postgres healthcheck reports healthy +db-wait: + @echo "==> Waiting for Postgres to be ready..." + @for i in $$(seq 1 60); do \ + STATUS=$$(docker inspect --format '{{.State.Health.Status}}' healthcaresamples-db 2>/dev/null || echo "missing"); \ + if [ "$$STATUS" = "healthy" ]; then echo "Postgres ready"; exit 0; fi; \ + sleep 1; \ + done; \ + echo "FAIL: Postgres did not become healthy"; \ + docker logs healthcaresamples-db 2>&1 | tail -50; \ + exit 1 + +## db-migrate: Ensure DB is up and apply YAML schemas via migration-cli to all four databases +db-migrate: db-up + @echo "==> Migrating Postgres schemas..." + dotnet migration-cli --schema Gatekeeper/Gatekeeper.Api/gatekeeper-schema.yaml \ + --output "$(PG_BASE_URL);Database=gatekeeper" --provider postgres + dotnet migration-cli --schema Clinical/Clinical.Api/clinical-schema.yaml \ + --output "$(PG_BASE_URL);Database=clinical" --provider postgres + dotnet migration-cli --schema Scheduling/Scheduling.Api/scheduling-schema.yaml \ + --output "$(PG_BASE_URL);Database=scheduling" --provider postgres + dotnet migration-cli --schema ICD10/ICD10.Api/icd10-schema.yaml \ + --output "$(PG_BASE_URL);Database=icd10" --provider postgres + # ============================================================================= # HELP # ============================================================================= diff --git a/Scheduling/Scheduling.Api/DataProvider.json b/Scheduling/Scheduling.Api/DataProvider.json index 611251e..e610ef7 100644 --- a/Scheduling/Scheduling.Api/DataProvider.json +++ b/Scheduling/Scheduling.Api/DataProvider.json @@ -1,73 +1,75 @@ { - "queries": [ - { - "name": "GetUpcomingAppointments", - "sqlFile": "Queries/GetUpcomingAppointments.generated.sql" - }, - { - "name": "GetAppointmentById", - "sqlFile": "Queries/GetAppointmentById.generated.sql" - }, - { - "name": "GetAppointmentsByPatient", - "sqlFile": "Queries/GetAppointmentsByPatient.generated.sql" - }, - { - "name": "GetAppointmentsByPractitioner", - "sqlFile": "Queries/GetAppointmentsByPractitioner.generated.sql" - }, - { - "name": "GetAllPractitioners", - "sqlFile": "Queries/GetAllPractitioners.generated.sql" - }, - { - "name": "GetPractitionerById", - "sqlFile": "Queries/GetPractitionerById.generated.sql" - }, - { - "name": "SearchPractitionersBySpecialty", - "sqlFile": "Queries/SearchPractitionersBySpecialty.generated.sql" - }, - { - "name": "GetAvailableSlots", - "sqlFile": "Queries/GetAvailableSlots.generated.sql" - }, - { - "name": "GetAppointmentsByStatus", - "sqlFile": "Queries/GetAppointmentsByStatus.generated.sql" - }, - { - "name": "CheckSchedulingConflicts", - "sqlFile": "Queries/CheckSchedulingConflicts.generated.sql" - }, - { - "name": "GetProviderAvailability", - "sqlFile": "Queries/GetProviderAvailability.generated.sql" - }, - { - "name": "GetProviderDailySchedule", - "sqlFile": "Queries/GetProviderDailySchedule.generated.sql" - } - ], - "tables": [ - { - "schema": "main", - "name": "fhir_Practitioner", - "generateInsert": true, - "generateUpdate": false, - "generateDelete": false, - "excludeColumns": ["Id"], - "primaryKeyColumns": ["Id"] - }, - { - "schema": "main", - "name": "fhir_Appointment", - "generateInsert": true, - "generateUpdate": false, - "generateDelete": false, - "excludeColumns": ["Id"], - "primaryKeyColumns": ["Id"] - } - ], - "connectionString": "Data Source=scheduling.db" -} + "queries": [ + { + "name": "GetUpcomingAppointments", + "sqlFile": "Queries/GetUpcomingAppointments.generated.sql" + }, + { + "name": "GetAppointmentById", + "sqlFile": "Queries/GetAppointmentById.generated.sql" + }, + { + "name": "GetAppointmentsByPatient", + "sqlFile": "Queries/GetAppointmentsByPatient.generated.sql" + }, + { + "name": "GetAppointmentsByPractitioner", + "sqlFile": "Queries/GetAppointmentsByPractitioner.generated.sql" + }, + { + "name": "GetAllPractitioners", + "sqlFile": "Queries/GetAllPractitioners.generated.sql" + }, + { + "name": "GetPractitionerById", + "sqlFile": "Queries/GetPractitionerById.generated.sql" + }, + { + "name": "SearchPractitionersBySpecialty", + "sqlFile": "Queries/SearchPractitionersBySpecialty.generated.sql" + }, + { + "name": "GetAvailableSlots", + "sqlFile": "Queries/GetAvailableSlots.generated.sql" + }, + { + "name": "GetAppointmentsByStatus", + "sqlFile": "Queries/GetAppointmentsByStatus.generated.sql" + }, + { + "name": "CheckSchedulingConflicts", + "sqlFile": "Queries/CheckSchedulingConflicts.generated.sql" + }, + { + "name": "GetProviderAvailability", + "sqlFile": "Queries/GetProviderAvailability.generated.sql" + }, + { + "name": "GetProviderDailySchedule", + "sqlFile": "Queries/GetProviderDailySchedule.generated.sql" + } + ], + "tables": [ + { + "schema": "public", + "name": "fhir_Practitioner", + "generateInsert": true, + "generateUpdate": false, + "generateDelete": false, + "primaryKeyColumns": [ + "Id" + ] + }, + { + "schema": "public", + "name": "fhir_Appointment", + "generateInsert": true, + "generateUpdate": false, + "generateDelete": false, + "primaryKeyColumns": [ + "Id" + ] + } + ], + "connectionString": "Host=localhost;Port=5432;Database=scheduling;Username=postgres;Password=changeme" +} \ No newline at end of file diff --git a/Scheduling/Scheduling.Api/Generated/.timestamp b/Scheduling/Scheduling.Api/Generated/.timestamp deleted file mode 100644 index e69de29..0000000 diff --git a/Scheduling/Scheduling.Api/Generated/CheckSchedulingConflicts.g.cs b/Scheduling/Scheduling.Api/Generated/CheckSchedulingConflicts.g.cs deleted file mode 100644 index 94dcb2d..0000000 --- a/Scheduling/Scheduling.Api/Generated/CheckSchedulingConflicts.g.cs +++ /dev/null @@ -1,101 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Threading.Tasks; -using Npgsql; -using Outcome; -using Nimblesite.Sql.Model; - -namespace Generated; - -/// <summary> -/// Extension methods for 'CheckSchedulingConflicts'. -/// </summary> -public static partial class CheckSchedulingConflictsExtensions -{ - /// <summary> - /// Executes 'CheckSchedulingConflicts.sql' and maps results. - /// </summary> - /// <param name="connection">Open NpgsqlConnection connection.</param> - /// <param name="practitionerRef">Query parameter.</param> - /// <param name="proposedEnd">Query parameter.</param> - /// <param name="proposedStart">Query parameter.</param> - /// <returns>Result of records or SQL error.</returns> - public static async Task<Result<ImmutableList<CheckSchedulingConflicts>, SqlError>> CheckSchedulingConflictsAsync(this NpgsqlConnection connection, object practitionerRef, object proposedEnd, object proposedStart) - { - const string sql = @"SELECT fhir_Appointment.Id, fhir_Appointment.StartTime, fhir_Appointment.EndTime, fhir_Appointment.Status FROM fhir_Appointment WHERE fhir_Appointment.PractitionerReference = @practitionerRef AND fhir_Appointment.Status != 'cancelled' AND fhir_Appointment.StartTime < @proposedEnd AND fhir_Appointment.EndTime > @proposedStart"; - - try - { - var results = ImmutableList.CreateBuilder<CheckSchedulingConflicts>(); - - using (var command = new NpgsqlCommand(sql, connection)) - { - if (practitionerRef is not null and not DBNull) - command.Parameters.AddWithValue("@practitionerRef", practitionerRef); - else - command.Parameters.Add(new NpgsqlParameter("@practitionerRef", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); - if (proposedEnd is not null and not DBNull) - command.Parameters.AddWithValue("@proposedEnd", proposedEnd); - else - command.Parameters.Add(new NpgsqlParameter("@proposedEnd", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); - if (proposedStart is not null and not DBNull) - command.Parameters.AddWithValue("@proposedStart", proposedStart); - else - command.Parameters.Add(new NpgsqlParameter("@proposedStart", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); - - using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false)) - { - while (await reader.ReadAsync().ConfigureAwait(false)) - { - var item = new CheckSchedulingConflicts( - reader.IsDBNull(0) ? null : reader.GetFieldValue<string>(0), - reader.IsDBNull(1) ? null : reader.GetFieldValue<string>(1), - reader.IsDBNull(2) ? null : reader.GetFieldValue<string>(2), - reader.IsDBNull(3) ? null : reader.GetFieldValue<string>(3) - ); - results.Add(item); - } - } - } - - return new Result<ImmutableList<CheckSchedulingConflicts>, SqlError>.Ok<ImmutableList<CheckSchedulingConflicts>, SqlError>(results.ToImmutable()); - } - catch (Exception ex) - { - return new Result<ImmutableList<CheckSchedulingConflicts>, SqlError>.Error<ImmutableList<CheckSchedulingConflicts>, SqlError>(new SqlError("Database error", ex)); - } - } -} - -/// <summary> -/// Result row for 'CheckSchedulingConflicts' query. -/// </summary> -public record CheckSchedulingConflicts -{ - /// <summary>Column 'Id'.</summary> - public string Id { get; init; } - - /// <summary>Column 'StartTime'.</summary> - public string StartTime { get; init; } - - /// <summary>Column 'EndTime'.</summary> - public string EndTime { get; init; } - - /// <summary>Column 'Status'.</summary> - public string Status { get; init; } - - /// <summary>Initializes a new instance of CheckSchedulingConflicts.</summary> - public CheckSchedulingConflicts( - string Id, - string StartTime, - string EndTime, - string Status - ) - { - this.Id = Id; - this.StartTime = StartTime; - this.EndTime = EndTime; - this.Status = Status; - } -} diff --git a/Scheduling/Scheduling.Api/Generated/GetAllPractitioners.g.cs b/Scheduling/Scheduling.Api/Generated/GetAllPractitioners.g.cs deleted file mode 100644 index 5b874f8..0000000 --- a/Scheduling/Scheduling.Api/Generated/GetAllPractitioners.g.cs +++ /dev/null @@ -1,116 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Threading.Tasks; -using Npgsql; -using Outcome; -using Nimblesite.Sql.Model; - -namespace Generated; - -/// <summary> -/// Extension methods for 'GetAllPractitioners'. -/// </summary> -public static partial class GetAllPractitionersExtensions -{ - /// <summary> - /// Executes 'GetAllPractitioners.sql' and maps results. - /// </summary> - /// <param name="connection">Open NpgsqlConnection connection.</param> - /// <returns>Result of records or SQL error.</returns> - public static async Task<Result<ImmutableList<GetAllPractitioners>, SqlError>> GetAllPractitionersAsync(this NpgsqlConnection connection) - { - const string sql = @"SELECT fhir_Practitioner.Id, fhir_Practitioner.Identifier, fhir_Practitioner.Active, fhir_Practitioner.NameFamily, fhir_Practitioner.NameGiven, fhir_Practitioner.Qualification, fhir_Practitioner.Specialty, fhir_Practitioner.TelecomEmail, fhir_Practitioner.TelecomPhone FROM fhir_Practitioner ORDER BY fhir_Practitioner.NameFamily , fhir_Practitioner.NameGiven "; - - try - { - var results = ImmutableList.CreateBuilder<GetAllPractitioners>(); - - using (var command = new NpgsqlCommand(sql, connection)) - { - - using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false)) - { - while (await reader.ReadAsync().ConfigureAwait(false)) - { - var item = new GetAllPractitioners( - reader.IsDBNull(0) ? null : reader.GetFieldValue<string>(0), - reader.IsDBNull(1) ? null : reader.GetFieldValue<string>(1), - reader.IsDBNull(2) ? default(long) : reader.GetFieldValue<long>(2), - reader.IsDBNull(3) ? null : reader.GetFieldValue<string>(3), - reader.IsDBNull(4) ? null : reader.GetFieldValue<string>(4), - reader.IsDBNull(5) ? null : reader.GetFieldValue<string>(5), - reader.IsDBNull(6) ? null : reader.GetFieldValue<string>(6), - reader.IsDBNull(7) ? null : reader.GetFieldValue<string>(7), - reader.IsDBNull(8) ? null : reader.GetFieldValue<string>(8) - ); - results.Add(item); - } - } - } - - return new Result<ImmutableList<GetAllPractitioners>, SqlError>.Ok<ImmutableList<GetAllPractitioners>, SqlError>(results.ToImmutable()); - } - catch (Exception ex) - { - return new Result<ImmutableList<GetAllPractitioners>, SqlError>.Error<ImmutableList<GetAllPractitioners>, SqlError>(new SqlError("Database error", ex)); - } - } -} - -/// <summary> -/// Result row for 'GetAllPractitioners' query. -/// </summary> -public record GetAllPractitioners -{ - /// <summary>Column 'Id'.</summary> - public string Id { get; init; } - - /// <summary>Column 'Identifier'.</summary> - public string Identifier { get; init; } - - /// <summary>Column 'Active'.</summary> - public long Active { get; init; } - - /// <summary>Column 'NameFamily'.</summary> - public string NameFamily { get; init; } - - /// <summary>Column 'NameGiven'.</summary> - public string NameGiven { get; init; } - - /// <summary>Column 'Qualification'.</summary> - public string Qualification { get; init; } - - /// <summary>Column 'Specialty'.</summary> - public string Specialty { get; init; } - - /// <summary>Column 'TelecomEmail'.</summary> - public string TelecomEmail { get; init; } - - /// <summary>Column 'TelecomPhone'.</summary> - public string TelecomPhone { get; init; } - - /// <summary>Initializes a new instance of GetAllPractitioners.</summary> - public GetAllPractitioners( - string Id, - string Identifier, - long Active, - string NameFamily, - string NameGiven, - string Qualification, - string Specialty, - string TelecomEmail, - string TelecomPhone - ) - { - this.Id = Id; - this.Identifier = Identifier; - this.Active = Active; - this.NameFamily = NameFamily; - this.NameGiven = NameGiven; - this.Qualification = Qualification; - this.Specialty = Specialty; - this.TelecomEmail = TelecomEmail; - this.TelecomPhone = TelecomPhone; - } -} diff --git a/Scheduling/Scheduling.Api/Generated/GetAppointmentById.g.cs b/Scheduling/Scheduling.Api/Generated/GetAppointmentById.g.cs deleted file mode 100644 index 676c8be..0000000 --- a/Scheduling/Scheduling.Api/Generated/GetAppointmentById.g.cs +++ /dev/null @@ -1,151 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Threading.Tasks; -using Npgsql; -using Outcome; -using Nimblesite.Sql.Model; - -namespace Generated; - -/// <summary> -/// Extension methods for 'GetAppointmentById'. -/// </summary> -public static partial class GetAppointmentByIdExtensions -{ - /// <summary> - /// Executes 'GetAppointmentById.sql' and maps results. - /// </summary> - /// <param name="connection">Open NpgsqlConnection connection.</param> - /// <param name="id">Query parameter.</param> - /// <returns>Result of records or SQL error.</returns> - public static async Task<Result<ImmutableList<GetAppointmentById>, SqlError>> GetAppointmentByIdAsync(this NpgsqlConnection connection, object id) - { - const string sql = @"SELECT fhir_Appointment.Id, fhir_Appointment.Status, fhir_Appointment.ServiceCategory, fhir_Appointment.ServiceType, fhir_Appointment.ReasonCode, fhir_Appointment.Priority, fhir_Appointment.Description, fhir_Appointment.StartTime, fhir_Appointment.EndTime, fhir_Appointment.MinutesDuration, fhir_Appointment.PatientReference, fhir_Appointment.PractitionerReference, fhir_Appointment.Created, fhir_Appointment.Comment FROM fhir_Appointment WHERE fhir_Appointment.Id = @id"; - - try - { - var results = ImmutableList.CreateBuilder<GetAppointmentById>(); - - using (var command = new NpgsqlCommand(sql, connection)) - { - if (id is not null and not DBNull) - command.Parameters.AddWithValue("@id", id); - else - command.Parameters.Add(new NpgsqlParameter("@id", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); - - using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false)) - { - while (await reader.ReadAsync().ConfigureAwait(false)) - { - var item = new GetAppointmentById( - reader.IsDBNull(0) ? null : reader.GetFieldValue<string>(0), - reader.IsDBNull(1) ? null : reader.GetFieldValue<string>(1), - reader.IsDBNull(2) ? null : reader.GetFieldValue<string>(2), - reader.IsDBNull(3) ? null : reader.GetFieldValue<string>(3), - reader.IsDBNull(4) ? null : reader.GetFieldValue<string>(4), - reader.IsDBNull(5) ? null : reader.GetFieldValue<string>(5), - reader.IsDBNull(6) ? null : reader.GetFieldValue<string>(6), - reader.IsDBNull(7) ? null : reader.GetFieldValue<string>(7), - reader.IsDBNull(8) ? null : reader.GetFieldValue<string>(8), - reader.IsDBNull(9) ? default(long) : reader.GetFieldValue<long>(9), - reader.IsDBNull(10) ? null : reader.GetFieldValue<string>(10), - reader.IsDBNull(11) ? null : reader.GetFieldValue<string>(11), - reader.IsDBNull(12) ? null : reader.GetFieldValue<string>(12), - reader.IsDBNull(13) ? null : reader.GetFieldValue<string>(13) - ); - results.Add(item); - } - } - } - - return new Result<ImmutableList<GetAppointmentById>, SqlError>.Ok<ImmutableList<GetAppointmentById>, SqlError>(results.ToImmutable()); - } - catch (Exception ex) - { - return new Result<ImmutableList<GetAppointmentById>, SqlError>.Error<ImmutableList<GetAppointmentById>, SqlError>(new SqlError("Database error", ex)); - } - } -} - -/// <summary> -/// Result row for 'GetAppointmentById' query. -/// </summary> -public record GetAppointmentById -{ - /// <summary>Column 'Id'.</summary> - public string Id { get; init; } - - /// <summary>Column 'Status'.</summary> - public string Status { get; init; } - - /// <summary>Column 'ServiceCategory'.</summary> - public string ServiceCategory { get; init; } - - /// <summary>Column 'ServiceType'.</summary> - public string ServiceType { get; init; } - - /// <summary>Column 'ReasonCode'.</summary> - public string ReasonCode { get; init; } - - /// <summary>Column 'Priority'.</summary> - public string Priority { get; init; } - - /// <summary>Column 'Description'.</summary> - public string Description { get; init; } - - /// <summary>Column 'StartTime'.</summary> - public string StartTime { get; init; } - - /// <summary>Column 'EndTime'.</summary> - public string EndTime { get; init; } - - /// <summary>Column 'MinutesDuration'.</summary> - public long MinutesDuration { get; init; } - - /// <summary>Column 'PatientReference'.</summary> - public string PatientReference { get; init; } - - /// <summary>Column 'PractitionerReference'.</summary> - public string PractitionerReference { get; init; } - - /// <summary>Column 'Created'.</summary> - public string Created { get; init; } - - /// <summary>Column 'Comment'.</summary> - public string Comment { get; init; } - - /// <summary>Initializes a new instance of GetAppointmentById.</summary> - public GetAppointmentById( - string Id, - string Status, - string ServiceCategory, - string ServiceType, - string ReasonCode, - string Priority, - string Description, - string StartTime, - string EndTime, - long MinutesDuration, - string PatientReference, - string PractitionerReference, - string Created, - string Comment - ) - { - this.Id = Id; - this.Status = Status; - this.ServiceCategory = ServiceCategory; - this.ServiceType = ServiceType; - this.ReasonCode = ReasonCode; - this.Priority = Priority; - this.Description = Description; - this.StartTime = StartTime; - this.EndTime = EndTime; - this.MinutesDuration = MinutesDuration; - this.PatientReference = PatientReference; - this.PractitionerReference = PractitionerReference; - this.Created = Created; - this.Comment = Comment; - } -} diff --git a/Scheduling/Scheduling.Api/Generated/GetAppointmentsByPatient.g.cs b/Scheduling/Scheduling.Api/Generated/GetAppointmentsByPatient.g.cs deleted file mode 100644 index ae25ca2..0000000 --- a/Scheduling/Scheduling.Api/Generated/GetAppointmentsByPatient.g.cs +++ /dev/null @@ -1,151 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Threading.Tasks; -using Npgsql; -using Outcome; -using Nimblesite.Sql.Model; - -namespace Generated; - -/// <summary> -/// Extension methods for 'GetAppointmentsByPatient'. -/// </summary> -public static partial class GetAppointmentsByPatientExtensions -{ - /// <summary> - /// Executes 'GetAppointmentsByPatient.sql' and maps results. - /// </summary> - /// <param name="connection">Open NpgsqlConnection connection.</param> - /// <param name="patientReference">Query parameter.</param> - /// <returns>Result of records or SQL error.</returns> - public static async Task<Result<ImmutableList<GetAppointmentsByPatient>, SqlError>> GetAppointmentsByPatientAsync(this NpgsqlConnection connection, object patientReference) - { - const string sql = @"SELECT fhir_Appointment.Id, fhir_Appointment.Status, fhir_Appointment.ServiceCategory, fhir_Appointment.ServiceType, fhir_Appointment.ReasonCode, fhir_Appointment.Priority, fhir_Appointment.Description, fhir_Appointment.StartTime, fhir_Appointment.EndTime, fhir_Appointment.MinutesDuration, fhir_Appointment.PatientReference, fhir_Appointment.PractitionerReference, fhir_Appointment.Created, fhir_Appointment.Comment FROM fhir_Appointment WHERE fhir_Appointment.PatientReference = @patientReference ORDER BY fhir_Appointment.StartTime DESC"; - - try - { - var results = ImmutableList.CreateBuilder<GetAppointmentsByPatient>(); - - using (var command = new NpgsqlCommand(sql, connection)) - { - if (patientReference is not null and not DBNull) - command.Parameters.AddWithValue("@patientReference", patientReference); - else - command.Parameters.Add(new NpgsqlParameter("@patientReference", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); - - using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false)) - { - while (await reader.ReadAsync().ConfigureAwait(false)) - { - var item = new GetAppointmentsByPatient( - reader.IsDBNull(0) ? null : reader.GetFieldValue<string>(0), - reader.IsDBNull(1) ? null : reader.GetFieldValue<string>(1), - reader.IsDBNull(2) ? null : reader.GetFieldValue<string>(2), - reader.IsDBNull(3) ? null : reader.GetFieldValue<string>(3), - reader.IsDBNull(4) ? null : reader.GetFieldValue<string>(4), - reader.IsDBNull(5) ? null : reader.GetFieldValue<string>(5), - reader.IsDBNull(6) ? null : reader.GetFieldValue<string>(6), - reader.IsDBNull(7) ? null : reader.GetFieldValue<string>(7), - reader.IsDBNull(8) ? null : reader.GetFieldValue<string>(8), - reader.IsDBNull(9) ? default(long) : reader.GetFieldValue<long>(9), - reader.IsDBNull(10) ? null : reader.GetFieldValue<string>(10), - reader.IsDBNull(11) ? null : reader.GetFieldValue<string>(11), - reader.IsDBNull(12) ? null : reader.GetFieldValue<string>(12), - reader.IsDBNull(13) ? null : reader.GetFieldValue<string>(13) - ); - results.Add(item); - } - } - } - - return new Result<ImmutableList<GetAppointmentsByPatient>, SqlError>.Ok<ImmutableList<GetAppointmentsByPatient>, SqlError>(results.ToImmutable()); - } - catch (Exception ex) - { - return new Result<ImmutableList<GetAppointmentsByPatient>, SqlError>.Error<ImmutableList<GetAppointmentsByPatient>, SqlError>(new SqlError("Database error", ex)); - } - } -} - -/// <summary> -/// Result row for 'GetAppointmentsByPatient' query. -/// </summary> -public record GetAppointmentsByPatient -{ - /// <summary>Column 'Id'.</summary> - public string Id { get; init; } - - /// <summary>Column 'Status'.</summary> - public string Status { get; init; } - - /// <summary>Column 'ServiceCategory'.</summary> - public string ServiceCategory { get; init; } - - /// <summary>Column 'ServiceType'.</summary> - public string ServiceType { get; init; } - - /// <summary>Column 'ReasonCode'.</summary> - public string ReasonCode { get; init; } - - /// <summary>Column 'Priority'.</summary> - public string Priority { get; init; } - - /// <summary>Column 'Description'.</summary> - public string Description { get; init; } - - /// <summary>Column 'StartTime'.</summary> - public string StartTime { get; init; } - - /// <summary>Column 'EndTime'.</summary> - public string EndTime { get; init; } - - /// <summary>Column 'MinutesDuration'.</summary> - public long MinutesDuration { get; init; } - - /// <summary>Column 'PatientReference'.</summary> - public string PatientReference { get; init; } - - /// <summary>Column 'PractitionerReference'.</summary> - public string PractitionerReference { get; init; } - - /// <summary>Column 'Created'.</summary> - public string Created { get; init; } - - /// <summary>Column 'Comment'.</summary> - public string Comment { get; init; } - - /// <summary>Initializes a new instance of GetAppointmentsByPatient.</summary> - public GetAppointmentsByPatient( - string Id, - string Status, - string ServiceCategory, - string ServiceType, - string ReasonCode, - string Priority, - string Description, - string StartTime, - string EndTime, - long MinutesDuration, - string PatientReference, - string PractitionerReference, - string Created, - string Comment - ) - { - this.Id = Id; - this.Status = Status; - this.ServiceCategory = ServiceCategory; - this.ServiceType = ServiceType; - this.ReasonCode = ReasonCode; - this.Priority = Priority; - this.Description = Description; - this.StartTime = StartTime; - this.EndTime = EndTime; - this.MinutesDuration = MinutesDuration; - this.PatientReference = PatientReference; - this.PractitionerReference = PractitionerReference; - this.Created = Created; - this.Comment = Comment; - } -} diff --git a/Scheduling/Scheduling.Api/Generated/GetAppointmentsByPractitioner.g.cs b/Scheduling/Scheduling.Api/Generated/GetAppointmentsByPractitioner.g.cs deleted file mode 100644 index e676140..0000000 --- a/Scheduling/Scheduling.Api/Generated/GetAppointmentsByPractitioner.g.cs +++ /dev/null @@ -1,151 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Threading.Tasks; -using Npgsql; -using Outcome; -using Nimblesite.Sql.Model; - -namespace Generated; - -/// <summary> -/// Extension methods for 'GetAppointmentsByPractitioner'. -/// </summary> -public static partial class GetAppointmentsByPractitionerExtensions -{ - /// <summary> - /// Executes 'GetAppointmentsByPractitioner.sql' and maps results. - /// </summary> - /// <param name="connection">Open NpgsqlConnection connection.</param> - /// <param name="practitionerReference">Query parameter.</param> - /// <returns>Result of records or SQL error.</returns> - public static async Task<Result<ImmutableList<GetAppointmentsByPractitioner>, SqlError>> GetAppointmentsByPractitionerAsync(this NpgsqlConnection connection, object practitionerReference) - { - const string sql = @"SELECT fhir_Appointment.Id, fhir_Appointment.Status, fhir_Appointment.ServiceCategory, fhir_Appointment.ServiceType, fhir_Appointment.ReasonCode, fhir_Appointment.Priority, fhir_Appointment.Description, fhir_Appointment.StartTime, fhir_Appointment.EndTime, fhir_Appointment.MinutesDuration, fhir_Appointment.PatientReference, fhir_Appointment.PractitionerReference, fhir_Appointment.Created, fhir_Appointment.Comment FROM fhir_Appointment WHERE fhir_Appointment.PractitionerReference = @practitionerReference AND fhir_Appointment.Status = 'booked' ORDER BY fhir_Appointment.StartTime "; - - try - { - var results = ImmutableList.CreateBuilder<GetAppointmentsByPractitioner>(); - - using (var command = new NpgsqlCommand(sql, connection)) - { - if (practitionerReference is not null and not DBNull) - command.Parameters.AddWithValue("@practitionerReference", practitionerReference); - else - command.Parameters.Add(new NpgsqlParameter("@practitionerReference", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); - - using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false)) - { - while (await reader.ReadAsync().ConfigureAwait(false)) - { - var item = new GetAppointmentsByPractitioner( - reader.IsDBNull(0) ? null : reader.GetFieldValue<string>(0), - reader.IsDBNull(1) ? null : reader.GetFieldValue<string>(1), - reader.IsDBNull(2) ? null : reader.GetFieldValue<string>(2), - reader.IsDBNull(3) ? null : reader.GetFieldValue<string>(3), - reader.IsDBNull(4) ? null : reader.GetFieldValue<string>(4), - reader.IsDBNull(5) ? null : reader.GetFieldValue<string>(5), - reader.IsDBNull(6) ? null : reader.GetFieldValue<string>(6), - reader.IsDBNull(7) ? null : reader.GetFieldValue<string>(7), - reader.IsDBNull(8) ? null : reader.GetFieldValue<string>(8), - reader.IsDBNull(9) ? default(long) : reader.GetFieldValue<long>(9), - reader.IsDBNull(10) ? null : reader.GetFieldValue<string>(10), - reader.IsDBNull(11) ? null : reader.GetFieldValue<string>(11), - reader.IsDBNull(12) ? null : reader.GetFieldValue<string>(12), - reader.IsDBNull(13) ? null : reader.GetFieldValue<string>(13) - ); - results.Add(item); - } - } - } - - return new Result<ImmutableList<GetAppointmentsByPractitioner>, SqlError>.Ok<ImmutableList<GetAppointmentsByPractitioner>, SqlError>(results.ToImmutable()); - } - catch (Exception ex) - { - return new Result<ImmutableList<GetAppointmentsByPractitioner>, SqlError>.Error<ImmutableList<GetAppointmentsByPractitioner>, SqlError>(new SqlError("Database error", ex)); - } - } -} - -/// <summary> -/// Result row for 'GetAppointmentsByPractitioner' query. -/// </summary> -public record GetAppointmentsByPractitioner -{ - /// <summary>Column 'Id'.</summary> - public string Id { get; init; } - - /// <summary>Column 'Status'.</summary> - public string Status { get; init; } - - /// <summary>Column 'ServiceCategory'.</summary> - public string ServiceCategory { get; init; } - - /// <summary>Column 'ServiceType'.</summary> - public string ServiceType { get; init; } - - /// <summary>Column 'ReasonCode'.</summary> - public string ReasonCode { get; init; } - - /// <summary>Column 'Priority'.</summary> - public string Priority { get; init; } - - /// <summary>Column 'Description'.</summary> - public string Description { get; init; } - - /// <summary>Column 'StartTime'.</summary> - public string StartTime { get; init; } - - /// <summary>Column 'EndTime'.</summary> - public string EndTime { get; init; } - - /// <summary>Column 'MinutesDuration'.</summary> - public long MinutesDuration { get; init; } - - /// <summary>Column 'PatientReference'.</summary> - public string PatientReference { get; init; } - - /// <summary>Column 'PractitionerReference'.</summary> - public string PractitionerReference { get; init; } - - /// <summary>Column 'Created'.</summary> - public string Created { get; init; } - - /// <summary>Column 'Comment'.</summary> - public string Comment { get; init; } - - /// <summary>Initializes a new instance of GetAppointmentsByPractitioner.</summary> - public GetAppointmentsByPractitioner( - string Id, - string Status, - string ServiceCategory, - string ServiceType, - string ReasonCode, - string Priority, - string Description, - string StartTime, - string EndTime, - long MinutesDuration, - string PatientReference, - string PractitionerReference, - string Created, - string Comment - ) - { - this.Id = Id; - this.Status = Status; - this.ServiceCategory = ServiceCategory; - this.ServiceType = ServiceType; - this.ReasonCode = ReasonCode; - this.Priority = Priority; - this.Description = Description; - this.StartTime = StartTime; - this.EndTime = EndTime; - this.MinutesDuration = MinutesDuration; - this.PatientReference = PatientReference; - this.PractitionerReference = PractitionerReference; - this.Created = Created; - this.Comment = Comment; - } -} diff --git a/Scheduling/Scheduling.Api/Generated/GetAppointmentsByStatus.g.cs b/Scheduling/Scheduling.Api/Generated/GetAppointmentsByStatus.g.cs deleted file mode 100644 index a87c26c..0000000 --- a/Scheduling/Scheduling.Api/Generated/GetAppointmentsByStatus.g.cs +++ /dev/null @@ -1,131 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Threading.Tasks; -using Npgsql; -using Outcome; -using Nimblesite.Sql.Model; - -namespace Generated; - -/// <summary> -/// Extension methods for 'GetAppointmentsByStatus'. -/// </summary> -public static partial class GetAppointmentsByStatusExtensions -{ - /// <summary> - /// Executes 'GetAppointmentsByStatus.sql' and maps results. - /// </summary> - /// <param name="connection">Open NpgsqlConnection connection.</param> - /// <param name="status">Query parameter.</param> - /// <param name="dateStart">Query parameter.</param> - /// <param name="dateEnd">Query parameter.</param> - /// <returns>Result of records or SQL error.</returns> - public static async Task<Result<ImmutableList<GetAppointmentsByStatus>, SqlError>> GetAppointmentsByStatusAsync(this NpgsqlConnection connection, object status, object dateStart, object dateEnd) - { - const string sql = @"SELECT fhir_Appointment.Id, fhir_Appointment.StartTime, fhir_Appointment.EndTime, fhir_Appointment.Status, sync_ScheduledPatient.DisplayName, fhir_Practitioner.NameFamily, fhir_Practitioner.NameGiven, fhir_Appointment.ServiceType, fhir_Appointment.ReasonCode FROM fhir_Appointment INNER JOIN sync_ScheduledPatient ON fhir_Appointment.PatientReference = sync_ScheduledPatient.PatientId INNER JOIN fhir_Practitioner ON fhir_Appointment.PractitionerReference = fhir_Practitioner.Id WHERE fhir_Appointment.Status = @status AND fhir_Appointment.StartTime >= @dateStart AND fhir_Appointment.StartTime < @dateEnd ORDER BY fhir_Appointment.StartTime "; - - try - { - var results = ImmutableList.CreateBuilder<GetAppointmentsByStatus>(); - - using (var command = new NpgsqlCommand(sql, connection)) - { - if (status is not null and not DBNull) - command.Parameters.AddWithValue("@status", status); - else - command.Parameters.Add(new NpgsqlParameter("@status", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); - if (dateStart is not null and not DBNull) - command.Parameters.AddWithValue("@dateStart", dateStart); - else - command.Parameters.Add(new NpgsqlParameter("@dateStart", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); - if (dateEnd is not null and not DBNull) - command.Parameters.AddWithValue("@dateEnd", dateEnd); - else - command.Parameters.Add(new NpgsqlParameter("@dateEnd", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); - - using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false)) - { - while (await reader.ReadAsync().ConfigureAwait(false)) - { - var item = new GetAppointmentsByStatus( - reader.IsDBNull(0) ? null : reader.GetFieldValue<string>(0), - reader.IsDBNull(1) ? null : reader.GetFieldValue<string>(1), - reader.IsDBNull(2) ? null : reader.GetFieldValue<string>(2), - reader.IsDBNull(3) ? null : reader.GetFieldValue<string>(3), - reader.IsDBNull(4) ? null : reader.GetFieldValue<string>(4), - reader.IsDBNull(5) ? null : reader.GetFieldValue<string>(5), - reader.IsDBNull(6) ? null : reader.GetFieldValue<string>(6), - reader.IsDBNull(7) ? null : reader.GetFieldValue<string>(7), - reader.IsDBNull(8) ? null : reader.GetFieldValue<string>(8) - ); - results.Add(item); - } - } - } - - return new Result<ImmutableList<GetAppointmentsByStatus>, SqlError>.Ok<ImmutableList<GetAppointmentsByStatus>, SqlError>(results.ToImmutable()); - } - catch (Exception ex) - { - return new Result<ImmutableList<GetAppointmentsByStatus>, SqlError>.Error<ImmutableList<GetAppointmentsByStatus>, SqlError>(new SqlError("Database error", ex)); - } - } -} - -/// <summary> -/// Result row for 'GetAppointmentsByStatus' query. -/// </summary> -public record GetAppointmentsByStatus -{ - /// <summary>Column 'Id'.</summary> - public string Id { get; init; } - - /// <summary>Column 'StartTime'.</summary> - public string StartTime { get; init; } - - /// <summary>Column 'EndTime'.</summary> - public string EndTime { get; init; } - - /// <summary>Column 'Status'.</summary> - public string Status { get; init; } - - /// <summary>Column 'DisplayName'.</summary> - public string DisplayName { get; init; } - - /// <summary>Column 'NameFamily'.</summary> - public string NameFamily { get; init; } - - /// <summary>Column 'NameGiven'.</summary> - public string NameGiven { get; init; } - - /// <summary>Column 'ServiceType'.</summary> - public string ServiceType { get; init; } - - /// <summary>Column 'ReasonCode'.</summary> - public string ReasonCode { get; init; } - - /// <summary>Initializes a new instance of GetAppointmentsByStatus.</summary> - public GetAppointmentsByStatus( - string Id, - string StartTime, - string EndTime, - string Status, - string DisplayName, - string NameFamily, - string NameGiven, - string ServiceType, - string ReasonCode - ) - { - this.Id = Id; - this.StartTime = StartTime; - this.EndTime = EndTime; - this.Status = Status; - this.DisplayName = DisplayName; - this.NameFamily = NameFamily; - this.NameGiven = NameGiven; - this.ServiceType = ServiceType; - this.ReasonCode = ReasonCode; - } -} diff --git a/Scheduling/Scheduling.Api/Generated/GetAvailableSlots.g.cs b/Scheduling/Scheduling.Api/Generated/GetAvailableSlots.g.cs deleted file mode 100644 index 0def083..0000000 --- a/Scheduling/Scheduling.Api/Generated/GetAvailableSlots.g.cs +++ /dev/null @@ -1,107 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Threading.Tasks; -using Npgsql; -using Outcome; -using Nimblesite.Sql.Model; - -namespace Generated; - -/// <summary> -/// Extension methods for 'GetAvailableSlots'. -/// </summary> -public static partial class GetAvailableSlotsExtensions -{ - /// <summary> - /// Executes 'GetAvailableSlots.sql' and maps results. - /// </summary> - /// <param name="connection">Open NpgsqlConnection connection.</param> - /// <param name="practitionerRef">Query parameter.</param> - /// <param name="fromDate">Query parameter.</param> - /// <param name="toDate">Query parameter.</param> - /// <returns>Result of records or SQL error.</returns> - public static async Task<Result<ImmutableList<GetAvailableSlots>, SqlError>> GetAvailableSlotsAsync(this NpgsqlConnection connection, object practitionerRef, object fromDate, object toDate) - { - const string sql = @"SELECT fhir_Slot.Id, fhir_Slot.Status, fhir_Slot.StartTime, fhir_Slot.EndTime, fhir_Schedule.PractitionerReference FROM fhir_Slot INNER JOIN fhir_Schedule ON fhir_Slot.ScheduleReference = fhir_Schedule.Id WHERE fhir_Schedule.PractitionerReference = @practitionerRef AND fhir_Slot.Status = 'free' AND fhir_Slot.StartTime >= @fromDate AND fhir_Slot.StartTime < @toDate ORDER BY fhir_Slot.StartTime "; - - try - { - var results = ImmutableList.CreateBuilder<GetAvailableSlots>(); - - using (var command = new NpgsqlCommand(sql, connection)) - { - if (practitionerRef is not null and not DBNull) - command.Parameters.AddWithValue("@practitionerRef", practitionerRef); - else - command.Parameters.Add(new NpgsqlParameter("@practitionerRef", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); - if (fromDate is not null and not DBNull) - command.Parameters.AddWithValue("@fromDate", fromDate); - else - command.Parameters.Add(new NpgsqlParameter("@fromDate", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); - if (toDate is not null and not DBNull) - command.Parameters.AddWithValue("@toDate", toDate); - else - command.Parameters.Add(new NpgsqlParameter("@toDate", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); - - using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false)) - { - while (await reader.ReadAsync().ConfigureAwait(false)) - { - var item = new GetAvailableSlots( - reader.IsDBNull(0) ? null : reader.GetFieldValue<string>(0), - reader.IsDBNull(1) ? null : reader.GetFieldValue<string>(1), - reader.IsDBNull(2) ? null : reader.GetFieldValue<string>(2), - reader.IsDBNull(3) ? null : reader.GetFieldValue<string>(3), - reader.IsDBNull(4) ? null : reader.GetFieldValue<string>(4) - ); - results.Add(item); - } - } - } - - return new Result<ImmutableList<GetAvailableSlots>, SqlError>.Ok<ImmutableList<GetAvailableSlots>, SqlError>(results.ToImmutable()); - } - catch (Exception ex) - { - return new Result<ImmutableList<GetAvailableSlots>, SqlError>.Error<ImmutableList<GetAvailableSlots>, SqlError>(new SqlError("Database error", ex)); - } - } -} - -/// <summary> -/// Result row for 'GetAvailableSlots' query. -/// </summary> -public record GetAvailableSlots -{ - /// <summary>Column 'Id'.</summary> - public string Id { get; init; } - - /// <summary>Column 'Status'.</summary> - public string Status { get; init; } - - /// <summary>Column 'StartTime'.</summary> - public string StartTime { get; init; } - - /// <summary>Column 'EndTime'.</summary> - public string EndTime { get; init; } - - /// <summary>Column 'PractitionerReference'.</summary> - public string PractitionerReference { get; init; } - - /// <summary>Initializes a new instance of GetAvailableSlots.</summary> - public GetAvailableSlots( - string Id, - string Status, - string StartTime, - string EndTime, - string PractitionerReference - ) - { - this.Id = Id; - this.Status = Status; - this.StartTime = StartTime; - this.EndTime = EndTime; - this.PractitionerReference = PractitionerReference; - } -} diff --git a/Scheduling/Scheduling.Api/Generated/GetPractitionerById.g.cs b/Scheduling/Scheduling.Api/Generated/GetPractitionerById.g.cs deleted file mode 100644 index 026be47..0000000 --- a/Scheduling/Scheduling.Api/Generated/GetPractitionerById.g.cs +++ /dev/null @@ -1,121 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Threading.Tasks; -using Npgsql; -using Outcome; -using Nimblesite.Sql.Model; - -namespace Generated; - -/// <summary> -/// Extension methods for 'GetPractitionerById'. -/// </summary> -public static partial class GetPractitionerByIdExtensions -{ - /// <summary> - /// Executes 'GetPractitionerById.sql' and maps results. - /// </summary> - /// <param name="connection">Open NpgsqlConnection connection.</param> - /// <param name="id">Query parameter.</param> - /// <returns>Result of records or SQL error.</returns> - public static async Task<Result<ImmutableList<GetPractitionerById>, SqlError>> GetPractitionerByIdAsync(this NpgsqlConnection connection, object id) - { - const string sql = @"SELECT fhir_Practitioner.Id, fhir_Practitioner.Identifier, fhir_Practitioner.Active, fhir_Practitioner.NameFamily, fhir_Practitioner.NameGiven, fhir_Practitioner.Qualification, fhir_Practitioner.Specialty, fhir_Practitioner.TelecomEmail, fhir_Practitioner.TelecomPhone FROM fhir_Practitioner WHERE fhir_Practitioner.Id = @id"; - - try - { - var results = ImmutableList.CreateBuilder<GetPractitionerById>(); - - using (var command = new NpgsqlCommand(sql, connection)) - { - if (id is not null and not DBNull) - command.Parameters.AddWithValue("@id", id); - else - command.Parameters.Add(new NpgsqlParameter("@id", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); - - using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false)) - { - while (await reader.ReadAsync().ConfigureAwait(false)) - { - var item = new GetPractitionerById( - reader.IsDBNull(0) ? null : reader.GetFieldValue<string>(0), - reader.IsDBNull(1) ? null : reader.GetFieldValue<string>(1), - reader.IsDBNull(2) ? default(long) : reader.GetFieldValue<long>(2), - reader.IsDBNull(3) ? null : reader.GetFieldValue<string>(3), - reader.IsDBNull(4) ? null : reader.GetFieldValue<string>(4), - reader.IsDBNull(5) ? null : reader.GetFieldValue<string>(5), - reader.IsDBNull(6) ? null : reader.GetFieldValue<string>(6), - reader.IsDBNull(7) ? null : reader.GetFieldValue<string>(7), - reader.IsDBNull(8) ? null : reader.GetFieldValue<string>(8) - ); - results.Add(item); - } - } - } - - return new Result<ImmutableList<GetPractitionerById>, SqlError>.Ok<ImmutableList<GetPractitionerById>, SqlError>(results.ToImmutable()); - } - catch (Exception ex) - { - return new Result<ImmutableList<GetPractitionerById>, SqlError>.Error<ImmutableList<GetPractitionerById>, SqlError>(new SqlError("Database error", ex)); - } - } -} - -/// <summary> -/// Result row for 'GetPractitionerById' query. -/// </summary> -public record GetPractitionerById -{ - /// <summary>Column 'Id'.</summary> - public string Id { get; init; } - - /// <summary>Column 'Identifier'.</summary> - public string Identifier { get; init; } - - /// <summary>Column 'Active'.</summary> - public long Active { get; init; } - - /// <summary>Column 'NameFamily'.</summary> - public string NameFamily { get; init; } - - /// <summary>Column 'NameGiven'.</summary> - public string NameGiven { get; init; } - - /// <summary>Column 'Qualification'.</summary> - public string Qualification { get; init; } - - /// <summary>Column 'Specialty'.</summary> - public string Specialty { get; init; } - - /// <summary>Column 'TelecomEmail'.</summary> - public string TelecomEmail { get; init; } - - /// <summary>Column 'TelecomPhone'.</summary> - public string TelecomPhone { get; init; } - - /// <summary>Initializes a new instance of GetPractitionerById.</summary> - public GetPractitionerById( - string Id, - string Identifier, - long Active, - string NameFamily, - string NameGiven, - string Qualification, - string Specialty, - string TelecomEmail, - string TelecomPhone - ) - { - this.Id = Id; - this.Identifier = Identifier; - this.Active = Active; - this.NameFamily = NameFamily; - this.NameGiven = NameGiven; - this.Qualification = Qualification; - this.Specialty = Specialty; - this.TelecomEmail = TelecomEmail; - this.TelecomPhone = TelecomPhone; - } -} diff --git a/Scheduling/Scheduling.Api/Generated/GetProviderAvailability.g.cs b/Scheduling/Scheduling.Api/Generated/GetProviderAvailability.g.cs deleted file mode 100644 index e55ef4f..0000000 --- a/Scheduling/Scheduling.Api/Generated/GetProviderAvailability.g.cs +++ /dev/null @@ -1,103 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Threading.Tasks; -using Npgsql; -using Outcome; -using Nimblesite.Sql.Model; - -namespace Generated; - -/// <summary> -/// Extension methods for 'GetProviderAvailability'. -/// </summary> -public static partial class GetProviderAvailabilityExtensions -{ - /// <summary> - /// Executes 'GetProviderAvailability.sql' and maps results. - /// </summary> - /// <param name="connection">Open NpgsqlConnection connection.</param> - /// <param name="practitionerRef">Query parameter.</param> - /// <returns>Result of records or SQL error.</returns> - public static async Task<Result<ImmutableList<GetProviderAvailability>, SqlError>> GetProviderAvailabilityAsync(this NpgsqlConnection connection, object practitionerRef) - { - const string sql = @"SELECT fhir_Schedule.Id, fhir_Schedule.PractitionerReference, fhir_Practitioner.NameFamily, fhir_Practitioner.NameGiven, fhir_Schedule.PlanningHorizon, fhir_Schedule.Active FROM fhir_Schedule INNER JOIN fhir_Practitioner ON fhir_Schedule.PractitionerReference = fhir_Practitioner.Id WHERE fhir_Schedule.PractitionerReference = @practitionerRef AND fhir_Schedule.Active = 1"; - - try - { - var results = ImmutableList.CreateBuilder<GetProviderAvailability>(); - - using (var command = new NpgsqlCommand(sql, connection)) - { - if (practitionerRef is not null and not DBNull) - command.Parameters.AddWithValue("@practitionerRef", practitionerRef); - else - command.Parameters.Add(new NpgsqlParameter("@practitionerRef", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); - - using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false)) - { - while (await reader.ReadAsync().ConfigureAwait(false)) - { - var item = new GetProviderAvailability( - reader.IsDBNull(0) ? null : reader.GetFieldValue<string>(0), - reader.IsDBNull(1) ? null : reader.GetFieldValue<string>(1), - reader.IsDBNull(2) ? null : reader.GetFieldValue<string>(2), - reader.IsDBNull(3) ? null : reader.GetFieldValue<string>(3), - reader.IsDBNull(4) ? default(long) : reader.GetFieldValue<long>(4), - reader.IsDBNull(5) ? default(long) : reader.GetFieldValue<long>(5) - ); - results.Add(item); - } - } - } - - return new Result<ImmutableList<GetProviderAvailability>, SqlError>.Ok<ImmutableList<GetProviderAvailability>, SqlError>(results.ToImmutable()); - } - catch (Exception ex) - { - return new Result<ImmutableList<GetProviderAvailability>, SqlError>.Error<ImmutableList<GetProviderAvailability>, SqlError>(new SqlError("Database error", ex)); - } - } -} - -/// <summary> -/// Result row for 'GetProviderAvailability' query. -/// </summary> -public record GetProviderAvailability -{ - /// <summary>Column 'Id'.</summary> - public string Id { get; init; } - - /// <summary>Column 'PractitionerReference'.</summary> - public string PractitionerReference { get; init; } - - /// <summary>Column 'NameFamily'.</summary> - public string NameFamily { get; init; } - - /// <summary>Column 'NameGiven'.</summary> - public string NameGiven { get; init; } - - /// <summary>Column 'PlanningHorizon'.</summary> - public long PlanningHorizon { get; init; } - - /// <summary>Column 'Active'.</summary> - public long Active { get; init; } - - /// <summary>Initializes a new instance of GetProviderAvailability.</summary> - public GetProviderAvailability( - string Id, - string PractitionerReference, - string NameFamily, - string NameGiven, - long PlanningHorizon, - long Active - ) - { - this.Id = Id; - this.PractitionerReference = PractitionerReference; - this.NameFamily = NameFamily; - this.NameGiven = NameGiven; - this.PlanningHorizon = PlanningHorizon; - this.Active = Active; - } -} diff --git a/Scheduling/Scheduling.Api/Generated/GetProviderDailySchedule.g.cs b/Scheduling/Scheduling.Api/Generated/GetProviderDailySchedule.g.cs deleted file mode 100644 index 6cf7bbe..0000000 --- a/Scheduling/Scheduling.Api/Generated/GetProviderDailySchedule.g.cs +++ /dev/null @@ -1,161 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Threading.Tasks; -using Npgsql; -using Outcome; -using Nimblesite.Sql.Model; - -namespace Generated; - -/// <summary> -/// Extension methods for 'GetProviderDailySchedule'. -/// </summary> -public static partial class GetProviderDailyScheduleExtensions -{ - /// <summary> - /// Executes 'GetProviderDailySchedule.sql' and maps results. - /// </summary> - /// <param name="connection">Open NpgsqlConnection connection.</param> - /// <param name="practitionerRef">Query parameter.</param> - /// <param name="dateStart">Query parameter.</param> - /// <param name="dateEnd">Query parameter.</param> - /// <returns>Result of records or SQL error.</returns> - public static async Task<Result<ImmutableList<GetProviderDailySchedule>, SqlError>> GetProviderDailyScheduleAsync(this NpgsqlConnection connection, object practitionerRef, object dateStart, object dateEnd) - { - const string sql = @"SELECT fhir_Appointment.Id, fhir_Appointment.StartTime, fhir_Appointment.EndTime, fhir_Appointment.MinutesDuration, fhir_Appointment.Status, fhir_Appointment.ServiceCategory, fhir_Appointment.ServiceType, fhir_Appointment.ReasonCode, fhir_Appointment.Description, fhir_Appointment.PatientReference, sync_ScheduledPatient.PatientId, sync_ScheduledPatient.DisplayName, sync_ScheduledPatient.ContactPhone, fhir_Appointment.PractitionerReference FROM fhir_Appointment INNER JOIN sync_ScheduledPatient ON fhir_Appointment.PatientReference = sync_ScheduledPatient.PatientId WHERE fhir_Appointment.PractitionerReference = @practitionerRef AND fhir_Appointment.StartTime >= @dateStart AND fhir_Appointment.StartTime < @dateEnd ORDER BY fhir_Appointment.StartTime "; - - try - { - var results = ImmutableList.CreateBuilder<GetProviderDailySchedule>(); - - using (var command = new NpgsqlCommand(sql, connection)) - { - if (practitionerRef is not null and not DBNull) - command.Parameters.AddWithValue("@practitionerRef", practitionerRef); - else - command.Parameters.Add(new NpgsqlParameter("@practitionerRef", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); - if (dateStart is not null and not DBNull) - command.Parameters.AddWithValue("@dateStart", dateStart); - else - command.Parameters.Add(new NpgsqlParameter("@dateStart", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); - if (dateEnd is not null and not DBNull) - command.Parameters.AddWithValue("@dateEnd", dateEnd); - else - command.Parameters.Add(new NpgsqlParameter("@dateEnd", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); - - using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false)) - { - while (await reader.ReadAsync().ConfigureAwait(false)) - { - var item = new GetProviderDailySchedule( - reader.IsDBNull(0) ? null : reader.GetFieldValue<string>(0), - reader.IsDBNull(1) ? null : reader.GetFieldValue<string>(1), - reader.IsDBNull(2) ? null : reader.GetFieldValue<string>(2), - reader.IsDBNull(3) ? default(long) : reader.GetFieldValue<long>(3), - reader.IsDBNull(4) ? null : reader.GetFieldValue<string>(4), - reader.IsDBNull(5) ? null : reader.GetFieldValue<string>(5), - reader.IsDBNull(6) ? null : reader.GetFieldValue<string>(6), - reader.IsDBNull(7) ? null : reader.GetFieldValue<string>(7), - reader.IsDBNull(8) ? null : reader.GetFieldValue<string>(8), - reader.IsDBNull(9) ? null : reader.GetFieldValue<string>(9), - reader.IsDBNull(10) ? null : reader.GetFieldValue<string>(10), - reader.IsDBNull(11) ? null : reader.GetFieldValue<string>(11), - reader.IsDBNull(12) ? null : reader.GetFieldValue<string>(12), - reader.IsDBNull(13) ? null : reader.GetFieldValue<string>(13) - ); - results.Add(item); - } - } - } - - return new Result<ImmutableList<GetProviderDailySchedule>, SqlError>.Ok<ImmutableList<GetProviderDailySchedule>, SqlError>(results.ToImmutable()); - } - catch (Exception ex) - { - return new Result<ImmutableList<GetProviderDailySchedule>, SqlError>.Error<ImmutableList<GetProviderDailySchedule>, SqlError>(new SqlError("Database error", ex)); - } - } -} - -/// <summary> -/// Result row for 'GetProviderDailySchedule' query. -/// </summary> -public record GetProviderDailySchedule -{ - /// <summary>Column 'Id'.</summary> - public string Id { get; init; } - - /// <summary>Column 'StartTime'.</summary> - public string StartTime { get; init; } - - /// <summary>Column 'EndTime'.</summary> - public string EndTime { get; init; } - - /// <summary>Column 'MinutesDuration'.</summary> - public long MinutesDuration { get; init; } - - /// <summary>Column 'Status'.</summary> - public string Status { get; init; } - - /// <summary>Column 'ServiceCategory'.</summary> - public string ServiceCategory { get; init; } - - /// <summary>Column 'ServiceType'.</summary> - public string ServiceType { get; init; } - - /// <summary>Column 'ReasonCode'.</summary> - public string ReasonCode { get; init; } - - /// <summary>Column 'Description'.</summary> - public string Description { get; init; } - - /// <summary>Column 'PatientReference'.</summary> - public string PatientReference { get; init; } - - /// <summary>Column 'PatientId'.</summary> - public string PatientId { get; init; } - - /// <summary>Column 'DisplayName'.</summary> - public string DisplayName { get; init; } - - /// <summary>Column 'ContactPhone'.</summary> - public string ContactPhone { get; init; } - - /// <summary>Column 'PractitionerReference'.</summary> - public string PractitionerReference { get; init; } - - /// <summary>Initializes a new instance of GetProviderDailySchedule.</summary> - public GetProviderDailySchedule( - string Id, - string StartTime, - string EndTime, - long MinutesDuration, - string Status, - string ServiceCategory, - string ServiceType, - string ReasonCode, - string Description, - string PatientReference, - string PatientId, - string DisplayName, - string ContactPhone, - string PractitionerReference - ) - { - this.Id = Id; - this.StartTime = StartTime; - this.EndTime = EndTime; - this.MinutesDuration = MinutesDuration; - this.Status = Status; - this.ServiceCategory = ServiceCategory; - this.ServiceType = ServiceType; - this.ReasonCode = ReasonCode; - this.Description = Description; - this.PatientReference = PatientReference; - this.PatientId = PatientId; - this.DisplayName = DisplayName; - this.ContactPhone = ContactPhone; - this.PractitionerReference = PractitionerReference; - } -} diff --git a/Scheduling/Scheduling.Api/Generated/GetUpcomingAppointments.g.cs b/Scheduling/Scheduling.Api/Generated/GetUpcomingAppointments.g.cs deleted file mode 100644 index 4a02c4a..0000000 --- a/Scheduling/Scheduling.Api/Generated/GetUpcomingAppointments.g.cs +++ /dev/null @@ -1,146 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Threading.Tasks; -using Npgsql; -using Outcome; -using Nimblesite.Sql.Model; - -namespace Generated; - -/// <summary> -/// Extension methods for 'GetUpcomingAppointments'. -/// </summary> -public static partial class GetUpcomingAppointmentsExtensions -{ - /// <summary> - /// Executes 'GetUpcomingAppointments.sql' and maps results. - /// </summary> - /// <param name="connection">Open NpgsqlConnection connection.</param> - /// <returns>Result of records or SQL error.</returns> - public static async Task<Result<ImmutableList<GetUpcomingAppointments>, SqlError>> GetUpcomingAppointmentsAsync(this NpgsqlConnection connection) - { - const string sql = @"SELECT fhir_Appointment.Id, fhir_Appointment.Status, fhir_Appointment.ServiceCategory, fhir_Appointment.ServiceType, fhir_Appointment.ReasonCode, fhir_Appointment.Priority, fhir_Appointment.Description, fhir_Appointment.StartTime, fhir_Appointment.EndTime, fhir_Appointment.MinutesDuration, fhir_Appointment.PatientReference, fhir_Appointment.PractitionerReference, fhir_Appointment.Created, fhir_Appointment.Comment FROM fhir_Appointment WHERE fhir_Appointment.Status = 'booked' ORDER BY fhir_Appointment.StartTime "; - - try - { - var results = ImmutableList.CreateBuilder<GetUpcomingAppointments>(); - - using (var command = new NpgsqlCommand(sql, connection)) - { - - using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false)) - { - while (await reader.ReadAsync().ConfigureAwait(false)) - { - var item = new GetUpcomingAppointments( - reader.IsDBNull(0) ? null : reader.GetFieldValue<string>(0), - reader.IsDBNull(1) ? null : reader.GetFieldValue<string>(1), - reader.IsDBNull(2) ? null : reader.GetFieldValue<string>(2), - reader.IsDBNull(3) ? null : reader.GetFieldValue<string>(3), - reader.IsDBNull(4) ? null : reader.GetFieldValue<string>(4), - reader.IsDBNull(5) ? null : reader.GetFieldValue<string>(5), - reader.IsDBNull(6) ? null : reader.GetFieldValue<string>(6), - reader.IsDBNull(7) ? null : reader.GetFieldValue<string>(7), - reader.IsDBNull(8) ? null : reader.GetFieldValue<string>(8), - reader.IsDBNull(9) ? default(long) : reader.GetFieldValue<long>(9), - reader.IsDBNull(10) ? null : reader.GetFieldValue<string>(10), - reader.IsDBNull(11) ? null : reader.GetFieldValue<string>(11), - reader.IsDBNull(12) ? null : reader.GetFieldValue<string>(12), - reader.IsDBNull(13) ? null : reader.GetFieldValue<string>(13) - ); - results.Add(item); - } - } - } - - return new Result<ImmutableList<GetUpcomingAppointments>, SqlError>.Ok<ImmutableList<GetUpcomingAppointments>, SqlError>(results.ToImmutable()); - } - catch (Exception ex) - { - return new Result<ImmutableList<GetUpcomingAppointments>, SqlError>.Error<ImmutableList<GetUpcomingAppointments>, SqlError>(new SqlError("Database error", ex)); - } - } -} - -/// <summary> -/// Result row for 'GetUpcomingAppointments' query. -/// </summary> -public record GetUpcomingAppointments -{ - /// <summary>Column 'Id'.</summary> - public string Id { get; init; } - - /// <summary>Column 'Status'.</summary> - public string Status { get; init; } - - /// <summary>Column 'ServiceCategory'.</summary> - public string ServiceCategory { get; init; } - - /// <summary>Column 'ServiceType'.</summary> - public string ServiceType { get; init; } - - /// <summary>Column 'ReasonCode'.</summary> - public string ReasonCode { get; init; } - - /// <summary>Column 'Priority'.</summary> - public string Priority { get; init; } - - /// <summary>Column 'Description'.</summary> - public string Description { get; init; } - - /// <summary>Column 'StartTime'.</summary> - public string StartTime { get; init; } - - /// <summary>Column 'EndTime'.</summary> - public string EndTime { get; init; } - - /// <summary>Column 'MinutesDuration'.</summary> - public long MinutesDuration { get; init; } - - /// <summary>Column 'PatientReference'.</summary> - public string PatientReference { get; init; } - - /// <summary>Column 'PractitionerReference'.</summary> - public string PractitionerReference { get; init; } - - /// <summary>Column 'Created'.</summary> - public string Created { get; init; } - - /// <summary>Column 'Comment'.</summary> - public string Comment { get; init; } - - /// <summary>Initializes a new instance of GetUpcomingAppointments.</summary> - public GetUpcomingAppointments( - string Id, - string Status, - string ServiceCategory, - string ServiceType, - string ReasonCode, - string Priority, - string Description, - string StartTime, - string EndTime, - long MinutesDuration, - string PatientReference, - string PractitionerReference, - string Created, - string Comment - ) - { - this.Id = Id; - this.Status = Status; - this.ServiceCategory = ServiceCategory; - this.ServiceType = ServiceType; - this.ReasonCode = ReasonCode; - this.Priority = Priority; - this.Description = Description; - this.StartTime = StartTime; - this.EndTime = EndTime; - this.MinutesDuration = MinutesDuration; - this.PatientReference = PatientReference; - this.PractitionerReference = PractitionerReference; - this.Created = Created; - this.Comment = Comment; - } -} diff --git a/Scheduling/Scheduling.Api/Generated/SearchPractitionersBySpecialty.g.cs b/Scheduling/Scheduling.Api/Generated/SearchPractitionersBySpecialty.g.cs deleted file mode 100644 index 56845d3..0000000 --- a/Scheduling/Scheduling.Api/Generated/SearchPractitionersBySpecialty.g.cs +++ /dev/null @@ -1,121 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Threading.Tasks; -using Npgsql; -using Outcome; -using Nimblesite.Sql.Model; - -namespace Generated; - -/// <summary> -/// Extension methods for 'SearchPractitionersBySpecialty'. -/// </summary> -public static partial class SearchPractitionersBySpecialtyExtensions -{ - /// <summary> - /// Executes 'SearchPractitionersBySpecialty.sql' and maps results. - /// </summary> - /// <param name="connection">Open NpgsqlConnection connection.</param> - /// <param name="specialty">Query parameter.</param> - /// <returns>Result of records or SQL error.</returns> - public static async Task<Result<ImmutableList<SearchPractitionersBySpecialty>, SqlError>> SearchPractitionersBySpecialtyAsync(this NpgsqlConnection connection, object specialty) - { - const string sql = @"SELECT fhir_Practitioner.Id, fhir_Practitioner.Identifier, fhir_Practitioner.Active, fhir_Practitioner.NameFamily, fhir_Practitioner.NameGiven, fhir_Practitioner.Qualification, fhir_Practitioner.Specialty, fhir_Practitioner.TelecomEmail, fhir_Practitioner.TelecomPhone FROM fhir_Practitioner WHERE fhir_Practitioner.Specialty LIKE '%' || @specialty || '%' ORDER BY fhir_Practitioner.NameFamily , fhir_Practitioner.NameGiven "; - - try - { - var results = ImmutableList.CreateBuilder<SearchPractitionersBySpecialty>(); - - using (var command = new NpgsqlCommand(sql, connection)) - { - if (specialty is not null and not DBNull) - command.Parameters.AddWithValue("@specialty", specialty); - else - command.Parameters.Add(new NpgsqlParameter("@specialty", NpgsqlTypes.NpgsqlDbType.Text) { Value = DBNull.Value }); - - using (var reader = await command.ExecuteReaderAsync().ConfigureAwait(false)) - { - while (await reader.ReadAsync().ConfigureAwait(false)) - { - var item = new SearchPractitionersBySpecialty( - reader.IsDBNull(0) ? null : reader.GetFieldValue<string>(0), - reader.IsDBNull(1) ? null : reader.GetFieldValue<string>(1), - reader.IsDBNull(2) ? default(long) : reader.GetFieldValue<long>(2), - reader.IsDBNull(3) ? null : reader.GetFieldValue<string>(3), - reader.IsDBNull(4) ? null : reader.GetFieldValue<string>(4), - reader.IsDBNull(5) ? null : reader.GetFieldValue<string>(5), - reader.IsDBNull(6) ? null : reader.GetFieldValue<string>(6), - reader.IsDBNull(7) ? null : reader.GetFieldValue<string>(7), - reader.IsDBNull(8) ? null : reader.GetFieldValue<string>(8) - ); - results.Add(item); - } - } - } - - return new Result<ImmutableList<SearchPractitionersBySpecialty>, SqlError>.Ok<ImmutableList<SearchPractitionersBySpecialty>, SqlError>(results.ToImmutable()); - } - catch (Exception ex) - { - return new Result<ImmutableList<SearchPractitionersBySpecialty>, SqlError>.Error<ImmutableList<SearchPractitionersBySpecialty>, SqlError>(new SqlError("Database error", ex)); - } - } -} - -/// <summary> -/// Result row for 'SearchPractitionersBySpecialty' query. -/// </summary> -public record SearchPractitionersBySpecialty -{ - /// <summary>Column 'Id'.</summary> - public string Id { get; init; } - - /// <summary>Column 'Identifier'.</summary> - public string Identifier { get; init; } - - /// <summary>Column 'Active'.</summary> - public long Active { get; init; } - - /// <summary>Column 'NameFamily'.</summary> - public string NameFamily { get; init; } - - /// <summary>Column 'NameGiven'.</summary> - public string NameGiven { get; init; } - - /// <summary>Column 'Qualification'.</summary> - public string Qualification { get; init; } - - /// <summary>Column 'Specialty'.</summary> - public string Specialty { get; init; } - - /// <summary>Column 'TelecomEmail'.</summary> - public string TelecomEmail { get; init; } - - /// <summary>Column 'TelecomPhone'.</summary> - public string TelecomPhone { get; init; } - - /// <summary>Initializes a new instance of SearchPractitionersBySpecialty.</summary> - public SearchPractitionersBySpecialty( - string Id, - string Identifier, - long Active, - string NameFamily, - string NameGiven, - string Qualification, - string Specialty, - string TelecomEmail, - string TelecomPhone - ) - { - this.Id = Id; - this.Identifier = Identifier; - this.Active = Active; - this.NameFamily = NameFamily; - this.NameGiven = NameGiven; - this.Qualification = Qualification; - this.Specialty = Specialty; - this.TelecomEmail = TelecomEmail; - this.TelecomPhone = TelecomPhone; - } -} diff --git a/Scheduling/Scheduling.Api/Generated/fhir_AppointmentOperations.g.cs b/Scheduling/Scheduling.Api/Generated/fhir_AppointmentOperations.g.cs deleted file mode 100644 index ca5f6f6..0000000 --- a/Scheduling/Scheduling.Api/Generated/fhir_AppointmentOperations.g.cs +++ /dev/null @@ -1,60 +0,0 @@ -#nullable enable -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Data; -using System.Globalization; -using System.Threading.Tasks; -using Npgsql; -using Outcome; -using Nimblesite.Sql.Model; - -namespace Generated -{ - /// <summary> - /// Extension methods for table operations on fhir_Appointment - /// </summary> - public static partial class fhir_AppointmentExtensions - { - - /// <summary> - /// Inserts a new row into the fhir_Appointment table. - /// </summary> - public static async Task<Result<int, SqlError>> Insertfhir_AppointmentAsync(this IDbTransaction transaction, string? id, string? status, string? servicecategory, string? servicetype, string? reasoncode, string? priority, string? description, string? starttime, string? endtime, long? minutesduration, string? patientreference, string? practitionerreference, string? created, string? comment) - { - const string sql = "INSERT INTO fhir_Appointment (Id, Status, ServiceCategory, ServiceType, ReasonCode, Priority, Description, StartTime, EndTime, MinutesDuration, PatientReference, PractitionerReference, Created, Comment) VALUES (@Id, @Status, @ServiceCategory, @ServiceType, @ReasonCode, @Priority, @Description, @StartTime, @EndTime, @MinutesDuration, @PatientReference, @PractitionerReference, @Created, @Comment)"; - - if (transaction.Connection is null) - return new Result<int, SqlError>.Error<int, SqlError>(new SqlError("Transaction has no connection")); - - try - { - using (var command = new NpgsqlCommand(sql, (NpgsqlConnection)transaction.Connection!, (NpgsqlTransaction)transaction)) - { - command.Parameters.AddWithValue("@Id", id ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@Status", status ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@ServiceCategory", servicecategory ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@ServiceType", servicetype ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@ReasonCode", reasoncode ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@Priority", priority ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@Description", description ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@StartTime", starttime ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@EndTime", endtime ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@MinutesDuration", minutesduration ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@PatientReference", patientreference ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@PractitionerReference", practitionerreference ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@Created", created ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@Comment", comment ?? (object)DBNull.Value); - - var rowsAffected = await command.ExecuteNonQueryAsync().ConfigureAwait(false); - return new Result<int, SqlError>.Ok<int, SqlError>(rowsAffected); - } - } - catch (Exception ex) - { - return new Result<int, SqlError>.Error<int, SqlError>(new SqlError("Insert failed", ex)); - } - } - - } -} diff --git a/Scheduling/Scheduling.Api/Generated/fhir_PractitionerOperations.g.cs b/Scheduling/Scheduling.Api/Generated/fhir_PractitionerOperations.g.cs deleted file mode 100644 index 1be97c1..0000000 --- a/Scheduling/Scheduling.Api/Generated/fhir_PractitionerOperations.g.cs +++ /dev/null @@ -1,55 +0,0 @@ -#nullable enable -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Data; -using System.Globalization; -using System.Threading.Tasks; -using Npgsql; -using Outcome; -using Nimblesite.Sql.Model; - -namespace Generated -{ - /// <summary> - /// Extension methods for table operations on fhir_Practitioner - /// </summary> - public static partial class fhir_PractitionerExtensions - { - - /// <summary> - /// Inserts a new row into the fhir_Practitioner table. - /// </summary> - public static async Task<Result<int, SqlError>> Insertfhir_PractitionerAsync(this IDbTransaction transaction, string? id, string? identifier, long? active, string? namefamily, string? namegiven, string? qualification, string? specialty, string? telecomemail, string? telecomphone) - { - const string sql = "INSERT INTO fhir_Practitioner (Id, Identifier, Active, NameFamily, NameGiven, Qualification, Specialty, TelecomEmail, TelecomPhone) VALUES (@Id, @Identifier, @Active, @NameFamily, @NameGiven, @Qualification, @Specialty, @TelecomEmail, @TelecomPhone)"; - - if (transaction.Connection is null) - return new Result<int, SqlError>.Error<int, SqlError>(new SqlError("Transaction has no connection")); - - try - { - using (var command = new NpgsqlCommand(sql, (NpgsqlConnection)transaction.Connection!, (NpgsqlTransaction)transaction)) - { - command.Parameters.AddWithValue("@Id", id ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@Identifier", identifier ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@Active", active ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@NameFamily", namefamily ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@NameGiven", namegiven ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@Qualification", qualification ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@Specialty", specialty ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@TelecomEmail", telecomemail ?? (object)DBNull.Value); - command.Parameters.AddWithValue("@TelecomPhone", telecomphone ?? (object)DBNull.Value); - - var rowsAffected = await command.ExecuteNonQueryAsync().ConfigureAwait(false); - return new Result<int, SqlError>.Ok<int, SqlError>(rowsAffected); - } - } - catch (Exception ex) - { - return new Result<int, SqlError>.Error<int, SqlError>(new SqlError("Insert failed", ex)); - } - } - - } -} diff --git a/Scheduling/Scheduling.Api/GlobalUsings.cs b/Scheduling/Scheduling.Api/GlobalUsings.cs index 76582a4..878b848 100644 --- a/Scheduling/Scheduling.Api/GlobalUsings.cs +++ b/Scheduling/Scheduling.Api/GlobalUsings.cs @@ -101,13 +101,13 @@ System.Collections.Immutable.ImmutableList<Generated.GetUpcomingAppointments>, Nimblesite.Sql.Model.SqlError >; -global using InsertError = Outcome.Result<int, Nimblesite.Sql.Model.SqlError>.Error< - int, +global using InsertError = Outcome.Result<System.Guid?, Nimblesite.Sql.Model.SqlError>.Error< + System.Guid?, Nimblesite.Sql.Model.SqlError >; // Insert result type aliases -global using InsertOk = Outcome.Result<int, Nimblesite.Sql.Model.SqlError>.Ok< - int, +global using InsertOk = Outcome.Result<System.Guid?, Nimblesite.Sql.Model.SqlError>.Ok< + System.Guid?, Nimblesite.Sql.Model.SqlError >; global using SearchPractitionersError = Outcome.Result< diff --git a/Scheduling/Scheduling.Api/Program.cs b/Scheduling/Scheduling.Api/Program.cs index 0b405b7..fdd9244 100644 --- a/Scheduling/Scheduling.Api/Program.cs +++ b/Scheduling/Scheduling.Api/Program.cs @@ -144,7 +144,7 @@ .Insertfhir_PractitionerAsync( id, request.Identifier, - 1L, + 1, request.NameFamily, request.NameGiven, request.Qualification ?? string.Empty, diff --git a/Scheduling/Scheduling.Api/Queries/CheckSchedulingConflicts.generated.sql b/Scheduling/Scheduling.Api/Queries/CheckSchedulingConflicts.generated.sql deleted file mode 100644 index ffc4d3b..0000000 --- a/Scheduling/Scheduling.Api/Queries/CheckSchedulingConflicts.generated.sql +++ /dev/null @@ -1 +0,0 @@ -SELECT fhir_Appointment.Id, fhir_Appointment.StartTime, fhir_Appointment.EndTime, fhir_Appointment.Status FROM fhir_Appointment WHERE fhir_Appointment.PractitionerReference = @practitionerRef AND fhir_Appointment.Status != 'cancelled' AND fhir_Appointment.StartTime < @proposedEnd AND fhir_Appointment.EndTime > @proposedStart \ No newline at end of file diff --git a/Scheduling/Scheduling.Api/Queries/GetAllPractitioners.generated.sql b/Scheduling/Scheduling.Api/Queries/GetAllPractitioners.generated.sql deleted file mode 100644 index eb27afd..0000000 --- a/Scheduling/Scheduling.Api/Queries/GetAllPractitioners.generated.sql +++ /dev/null @@ -1 +0,0 @@ -SELECT fhir_Practitioner.Id, fhir_Practitioner.Identifier, fhir_Practitioner.Active, fhir_Practitioner.NameFamily, fhir_Practitioner.NameGiven, fhir_Practitioner.Qualification, fhir_Practitioner.Specialty, fhir_Practitioner.TelecomEmail, fhir_Practitioner.TelecomPhone FROM fhir_Practitioner ORDER BY fhir_Practitioner.NameFamily , fhir_Practitioner.NameGiven \ No newline at end of file diff --git a/Scheduling/Scheduling.Api/Queries/GetAppointmentById.generated.sql b/Scheduling/Scheduling.Api/Queries/GetAppointmentById.generated.sql deleted file mode 100644 index fdc3a9a..0000000 --- a/Scheduling/Scheduling.Api/Queries/GetAppointmentById.generated.sql +++ /dev/null @@ -1 +0,0 @@ -SELECT fhir_Appointment.Id, fhir_Appointment.Status, fhir_Appointment.ServiceCategory, fhir_Appointment.ServiceType, fhir_Appointment.ReasonCode, fhir_Appointment.Priority, fhir_Appointment.Description, fhir_Appointment.StartTime, fhir_Appointment.EndTime, fhir_Appointment.MinutesDuration, fhir_Appointment.PatientReference, fhir_Appointment.PractitionerReference, fhir_Appointment.Created, fhir_Appointment.Comment FROM fhir_Appointment WHERE fhir_Appointment.Id = @id \ No newline at end of file diff --git a/Scheduling/Scheduling.Api/Queries/GetAppointmentsByPatient.generated.sql b/Scheduling/Scheduling.Api/Queries/GetAppointmentsByPatient.generated.sql deleted file mode 100644 index 685633a..0000000 --- a/Scheduling/Scheduling.Api/Queries/GetAppointmentsByPatient.generated.sql +++ /dev/null @@ -1 +0,0 @@ -SELECT fhir_Appointment.Id, fhir_Appointment.Status, fhir_Appointment.ServiceCategory, fhir_Appointment.ServiceType, fhir_Appointment.ReasonCode, fhir_Appointment.Priority, fhir_Appointment.Description, fhir_Appointment.StartTime, fhir_Appointment.EndTime, fhir_Appointment.MinutesDuration, fhir_Appointment.PatientReference, fhir_Appointment.PractitionerReference, fhir_Appointment.Created, fhir_Appointment.Comment FROM fhir_Appointment WHERE fhir_Appointment.PatientReference = @patientReference ORDER BY fhir_Appointment.StartTime DESC \ No newline at end of file diff --git a/Scheduling/Scheduling.Api/Queries/GetAppointmentsByPractitioner.generated.sql b/Scheduling/Scheduling.Api/Queries/GetAppointmentsByPractitioner.generated.sql deleted file mode 100644 index fa540bf..0000000 --- a/Scheduling/Scheduling.Api/Queries/GetAppointmentsByPractitioner.generated.sql +++ /dev/null @@ -1 +0,0 @@ -SELECT fhir_Appointment.Id, fhir_Appointment.Status, fhir_Appointment.ServiceCategory, fhir_Appointment.ServiceType, fhir_Appointment.ReasonCode, fhir_Appointment.Priority, fhir_Appointment.Description, fhir_Appointment.StartTime, fhir_Appointment.EndTime, fhir_Appointment.MinutesDuration, fhir_Appointment.PatientReference, fhir_Appointment.PractitionerReference, fhir_Appointment.Created, fhir_Appointment.Comment FROM fhir_Appointment WHERE fhir_Appointment.PractitionerReference = @practitionerReference AND fhir_Appointment.Status = 'booked' ORDER BY fhir_Appointment.StartTime \ No newline at end of file diff --git a/Scheduling/Scheduling.Api/Queries/GetAppointmentsByStatus.generated.sql b/Scheduling/Scheduling.Api/Queries/GetAppointmentsByStatus.generated.sql deleted file mode 100644 index 6318005..0000000 --- a/Scheduling/Scheduling.Api/Queries/GetAppointmentsByStatus.generated.sql +++ /dev/null @@ -1 +0,0 @@ -SELECT fhir_Appointment.Id, fhir_Appointment.StartTime, fhir_Appointment.EndTime, fhir_Appointment.Status, sync_ScheduledPatient.DisplayName, fhir_Practitioner.NameFamily, fhir_Practitioner.NameGiven, fhir_Appointment.ServiceType, fhir_Appointment.ReasonCode FROM fhir_Appointment INNER JOIN sync_ScheduledPatient ON fhir_Appointment.PatientReference = sync_ScheduledPatient.PatientId INNER JOIN fhir_Practitioner ON fhir_Appointment.PractitionerReference = fhir_Practitioner.Id WHERE fhir_Appointment.Status = @status AND fhir_Appointment.StartTime >= @dateStart AND fhir_Appointment.StartTime < @dateEnd ORDER BY fhir_Appointment.StartTime \ No newline at end of file diff --git a/Scheduling/Scheduling.Api/Queries/GetAvailableSlots.generated.sql b/Scheduling/Scheduling.Api/Queries/GetAvailableSlots.generated.sql deleted file mode 100644 index a3ca060..0000000 --- a/Scheduling/Scheduling.Api/Queries/GetAvailableSlots.generated.sql +++ /dev/null @@ -1 +0,0 @@ -SELECT fhir_Slot.Id, fhir_Slot.Status, fhir_Slot.StartTime, fhir_Slot.EndTime, fhir_Schedule.PractitionerReference FROM fhir_Slot INNER JOIN fhir_Schedule ON fhir_Slot.ScheduleReference = fhir_Schedule.Id WHERE fhir_Schedule.PractitionerReference = @practitionerRef AND fhir_Slot.Status = 'free' AND fhir_Slot.StartTime >= @fromDate AND fhir_Slot.StartTime < @toDate ORDER BY fhir_Slot.StartTime \ No newline at end of file diff --git a/Scheduling/Scheduling.Api/Queries/GetPractitionerById.generated.sql b/Scheduling/Scheduling.Api/Queries/GetPractitionerById.generated.sql deleted file mode 100644 index 14c5d35..0000000 --- a/Scheduling/Scheduling.Api/Queries/GetPractitionerById.generated.sql +++ /dev/null @@ -1 +0,0 @@ -SELECT fhir_Practitioner.Id, fhir_Practitioner.Identifier, fhir_Practitioner.Active, fhir_Practitioner.NameFamily, fhir_Practitioner.NameGiven, fhir_Practitioner.Qualification, fhir_Practitioner.Specialty, fhir_Practitioner.TelecomEmail, fhir_Practitioner.TelecomPhone FROM fhir_Practitioner WHERE fhir_Practitioner.Id = @id \ No newline at end of file diff --git a/Scheduling/Scheduling.Api/Queries/GetProviderAvailability.generated.sql b/Scheduling/Scheduling.Api/Queries/GetProviderAvailability.generated.sql deleted file mode 100644 index 72bb92b..0000000 --- a/Scheduling/Scheduling.Api/Queries/GetProviderAvailability.generated.sql +++ /dev/null @@ -1 +0,0 @@ -SELECT fhir_Schedule.Id, fhir_Schedule.PractitionerReference, fhir_Practitioner.NameFamily, fhir_Practitioner.NameGiven, fhir_Schedule.PlanningHorizon, fhir_Schedule.Active FROM fhir_Schedule INNER JOIN fhir_Practitioner ON fhir_Schedule.PractitionerReference = fhir_Practitioner.Id WHERE fhir_Schedule.PractitionerReference = @practitionerRef AND fhir_Schedule.Active = 1 \ No newline at end of file diff --git a/Scheduling/Scheduling.Api/Queries/GetProviderDailySchedule.generated.sql b/Scheduling/Scheduling.Api/Queries/GetProviderDailySchedule.generated.sql deleted file mode 100644 index 668d0ec..0000000 --- a/Scheduling/Scheduling.Api/Queries/GetProviderDailySchedule.generated.sql +++ /dev/null @@ -1 +0,0 @@ -SELECT fhir_Appointment.Id, fhir_Appointment.StartTime, fhir_Appointment.EndTime, fhir_Appointment.MinutesDuration, fhir_Appointment.Status, fhir_Appointment.ServiceCategory, fhir_Appointment.ServiceType, fhir_Appointment.ReasonCode, fhir_Appointment.Description, fhir_Appointment.PatientReference, sync_ScheduledPatient.PatientId, sync_ScheduledPatient.DisplayName, sync_ScheduledPatient.ContactPhone, fhir_Appointment.PractitionerReference FROM fhir_Appointment INNER JOIN sync_ScheduledPatient ON fhir_Appointment.PatientReference = sync_ScheduledPatient.PatientId WHERE fhir_Appointment.PractitionerReference = @practitionerRef AND fhir_Appointment.StartTime >= @dateStart AND fhir_Appointment.StartTime < @dateEnd ORDER BY fhir_Appointment.StartTime \ No newline at end of file diff --git a/Scheduling/Scheduling.Api/Queries/GetUpcomingAppointments.generated.sql b/Scheduling/Scheduling.Api/Queries/GetUpcomingAppointments.generated.sql deleted file mode 100644 index a27dab3..0000000 --- a/Scheduling/Scheduling.Api/Queries/GetUpcomingAppointments.generated.sql +++ /dev/null @@ -1 +0,0 @@ -SELECT fhir_Appointment.Id, fhir_Appointment.Status, fhir_Appointment.ServiceCategory, fhir_Appointment.ServiceType, fhir_Appointment.ReasonCode, fhir_Appointment.Priority, fhir_Appointment.Description, fhir_Appointment.StartTime, fhir_Appointment.EndTime, fhir_Appointment.MinutesDuration, fhir_Appointment.PatientReference, fhir_Appointment.PractitionerReference, fhir_Appointment.Created, fhir_Appointment.Comment FROM fhir_Appointment WHERE fhir_Appointment.Status = 'booked' ORDER BY fhir_Appointment.StartTime \ No newline at end of file diff --git a/Scheduling/Scheduling.Api/Queries/SearchPractitionersBySpecialty.generated.sql b/Scheduling/Scheduling.Api/Queries/SearchPractitionersBySpecialty.generated.sql deleted file mode 100644 index e0a423b..0000000 --- a/Scheduling/Scheduling.Api/Queries/SearchPractitionersBySpecialty.generated.sql +++ /dev/null @@ -1 +0,0 @@ -SELECT fhir_Practitioner.Id, fhir_Practitioner.Identifier, fhir_Practitioner.Active, fhir_Practitioner.NameFamily, fhir_Practitioner.NameGiven, fhir_Practitioner.Qualification, fhir_Practitioner.Specialty, fhir_Practitioner.TelecomEmail, fhir_Practitioner.TelecomPhone FROM fhir_Practitioner WHERE fhir_Practitioner.Specialty LIKE '%' || @specialty || '%' ORDER BY fhir_Practitioner.NameFamily , fhir_Practitioner.NameGiven \ No newline at end of file diff --git a/Scheduling/Scheduling.Api/Scheduling.Api.csproj b/Scheduling/Scheduling.Api/Scheduling.Api.csproj index b5da2d4..b5287db 100644 --- a/Scheduling/Scheduling.Api/Scheduling.Api.csproj +++ b/Scheduling/Scheduling.Api/Scheduling.Api.csproj @@ -1,7 +1,7 @@ <Project Sdk="Microsoft.NET.Sdk.Web"> <PropertyGroup> <OutputType>Exe</OutputType> - <NoWarn>CA1515;CA2100;RS1035;CA1508;CA2234;CA1812</NoWarn> + <NoWarn>$(NoWarn);CA1515;CA2100;RS1035;CA1508;CA2234;CA1812;CS1591</NoWarn> <EnableLqlTranspile>true</EnableLqlTranspile> </PropertyGroup> @@ -33,19 +33,10 @@ </Content> </ItemGroup> - <!-- Create database from YAML using Migration.Cli (installed as dotnet tool) --> - <Target Name="CreateDatabaseSchema" BeforeTargets="TranspileLqlAndGenerateDataProvider"> - <Exec - Command="dotnet migration-cli --schema "$(MSBuildProjectDirectory)/scheduling-schema.yaml" --output "$(MSBuildProjectDirectory)/scheduling.db" --provider sqlite" - WorkingDirectory="$(MSBuildProjectDirectory)" - StandardOutputImportance="High" - StandardErrorImportance="High" - /> - </Target> - - <!-- Pre-compile: transpile LQL to SQL, then generate C# from SQL using CLI tools --> + <!-- Pre-compile: transpile LQL to SQL, then generate C# via dataprovider-postgres CLI. + Requires a live Postgres with the scheduling schema migrated (see `make db-migrate`). --> <Target - Name="TranspileLqlAndGenerateDataProvider" + Name="GenerateDataProvider" BeforeTargets="BeforeCompile;CoreCompile" Inputs="$(MSBuildProjectDirectory)/DataProvider.json;@(AdditionalFiles);@(LqlFiles)" Outputs="$(MSBuildProjectDirectory)/Generated/.timestamp" @@ -57,19 +48,17 @@ </ItemGroup> <Message Importance="High" Text="Transpiling LQL files (@(LqlFiles))" /> <Exec - Command="dotnet lqlcli-sqlite --input "%(LqlFiles.Identity)" --output "%(LqlFiles.RootDir)%(LqlFiles.Directory)%(LqlFiles.Filename).generated.sql"" + Command="dotnet lql-postgres --input "%(LqlFiles.Identity)" --output "%(LqlFiles.RootDir)%(LqlFiles.Directory)%(LqlFiles.Filename).generated.sql"" Condition="'$(EnableLqlTranspile)' == 'true' and @(LqlFiles) != ''" WorkingDirectory="$(MSBuildProjectDirectory)" StandardOutputImportance="High" StandardErrorImportance="High" - ContinueOnError="WarnAndContinue" /> <Exec - Command="dotnet dataprovider-sqlite --project-dir "$(MSBuildProjectDirectory)" --config "$(MSBuildProjectDirectory)/DataProvider.json" --out "$(MSBuildProjectDirectory)/Generated" --connection-type NpgsqlConnection" + Command="dotnet dataprovider-postgres --project-dir "$(MSBuildProjectDirectory)" --config "$(MSBuildProjectDirectory)/DataProvider.json" --out "$(MSBuildProjectDirectory)/Generated"" WorkingDirectory="$(MSBuildProjectDirectory)" StandardOutputImportance="High" StandardErrorImportance="High" - IgnoreExitCode="true" /> <Touch Files="$(MSBuildProjectDirectory)/Generated/.timestamp" AlwaysCreate="true" /> <ItemGroup> diff --git a/docker/docker-compose.db.yml b/docker/docker-compose.db.yml new file mode 100644 index 0000000..cd233b4 --- /dev/null +++ b/docker/docker-compose.db.yml @@ -0,0 +1,20 @@ +services: + db: + image: pgvector/pgvector:pg16 + container_name: healthcaresamples-db + environment: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: ${DB_PASSWORD:-changeme} + volumes: + - db-data:/var/lib/postgresql/data + - ./init-db:/docker-entrypoint-initdb.d + ports: + - "5432:5432" + healthcheck: + test: ["CMD-SHELL", "pg_isready -U postgres"] + interval: 5s + timeout: 3s + retries: 20 + +volumes: + db-data: diff --git a/docs/plans/delete-generated-files-and-postgres-codegen.md b/docs/plans/delete-generated-files-and-postgres-codegen.md index 8b306ea..c85b88f 100644 --- a/docs/plans/delete-generated-files-and-postgres-codegen.md +++ b/docs/plans/delete-generated-files-and-postgres-codegen.md @@ -3,6 +3,18 @@ DataProvider reference code here: /Users/christianfindlay/Documents/Code/ai_cms +## Progress Checklist + +- [x] Step 1 — Add `dataprovider-postgres` (0.2.7-beta), `lql-postgres` (0.1.8-beta), bump `migration-cli` (0.2.2-beta) to `.config/dotnet-tools.json` +- [x] Step 2 — Create `docker/docker-compose.db.yml` +- [x] Step 3 — Add `db-up`, `db-down`, `db-reset`, `db-wait`, `db-migrate` Makefile targets and wire `build`/`test`/`lint` to depend on `db-migrate` +- [x] Step 4 — Update each `DataProvider.json` for Postgres (Clinical, Scheduling, Gatekeeper, ICD10) — connection string + `schema` `main` → `public`, drop `excludeColumns` +- [x] Step 5 — Update each API `.csproj` (Clinical, Scheduling, Gatekeeper, ICD10) — switch to `dataprovider-postgres`, switch LQL to `lql-postgres`, drop `IgnoreExitCode`, delete `CreateDatabaseSchema` target, drop SQLite `icd10.db` `<Content>` +- [x] Step 6 — Delete tracked `Generated/` files from git, update root `.gitignore`, simplify `ICD10/.gitignore` +- [x] Step 7 — Update `.github/workflows/ci.yml` to use `make db-up` / `make db-migrate` instead of inline `services.postgres` +- [x] Step 8 — Patch consumer C# (Gatekeeper/Clinical/Scheduling/ICD10) for new generated record shape (`Result<Guid?>` instead of `Result<int>`, snake_case fields preserved, IDbTransaction overloads) +- [x] Verify — `make build` succeeds with 0 errors / 0 warnings; full `HealthcareSamples.sln` builds clean; all `Generated/` content regenerated each build through `dataprovider-postgres` against live Postgres + ## Context Generated `.g.cs` files are currently committed to git in three of four API projects (Clinical, Scheduling, Gatekeeper). The fourth (ICD10) already excludes them via a per-folder `.gitignore`. This causes constant noise: From 95b6f5e4b7f1d9eb98c1023f390d2c748090eb97 Mon Sep 17 00:00:00 2001 From: Christian Findlay <16697547+MelbourneDeveloper@users.noreply.github.com> Date: Wed, 8 Apr 2026 08:16:07 +1000 Subject: [PATCH 10/59] Fail fast --- .../xunit.runner.json | 1 + Directory.Build.props | 8 +++++ Makefile | 32 +++++++++++++++---- xunit.runner.json | 10 ++++++ 4 files changed, 44 insertions(+), 7 deletions(-) create mode 100644 xunit.runner.json diff --git a/Dashboard/Dashboard.Integration.Tests/xunit.runner.json b/Dashboard/Dashboard.Integration.Tests/xunit.runner.json index 8d67726..34723a8 100644 --- a/Dashboard/Dashboard.Integration.Tests/xunit.runner.json +++ b/Dashboard/Dashboard.Integration.Tests/xunit.runner.json @@ -3,6 +3,7 @@ "parallelizeAssembly": false, "parallelizeTestCollections": false, "maxParallelThreads": 1, + "stopOnFail": true, "diagnosticMessages": true, "longRunningTestSeconds": 30, "methodDisplay": "method" diff --git a/Directory.Build.props b/Directory.Build.props index 7d0b04f..4782c01 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -59,6 +59,14 @@ </PackageReference> </ItemGroup> + <!-- Shared xunit runner config (stopOnFail) for every test project that doesn't override it --> + <ItemGroup Condition="'$(IsTestProject)' == 'true' And !Exists('$(MSBuildProjectDirectory)\xunit.runner.json')"> + <Content Include="$(MSBuildThisFileDirectory)xunit.runner.json"> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + <Link>xunit.runner.json</Link> + </Content> + </ItemGroup> + <!-- Code Analysis packages only for non-test projects --> <ItemGroup Condition="'$(IsTestProject)' != 'true'"> <PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.5.0" PrivateAssets="all" /> diff --git a/Makefile b/Makefile index 30d2c15..fc8cc6c 100644 --- a/Makefile +++ b/Makefile @@ -39,14 +39,32 @@ build: db-migrate @echo "==> Building..." dotnet build HealthcareSamples.sln --configuration Release -## test: Run full test suite with coverage +# Test projects in execution order. Cheapest / most foundational first so a +# break in a lower layer fails the run immediately, before slower E2E suites. +TEST_PROJECTS = \ + Gatekeeper/Gatekeeper.Api.Tests/Gatekeeper.Api.Tests.csproj \ + Clinical/Clinical.Api.Tests/Clinical.Api.Tests.csproj \ + Scheduling/Scheduling.Api.Tests/Scheduling.Api.Tests.csproj \ + ICD10/ICD10.Api.Tests/ICD10.Api.Tests.csproj \ + ICD10/ICD10.Cli.Tests/ICD10.Cli.Tests.csproj \ + Dashboard/Dashboard.Integration.Tests/Dashboard.Integration.Tests.csproj + +## test: Run full test suite with coverage (FAIL FAST) +## - Stops at the first failing test inside an assembly (xunit stopOnFail) +## - Stops at the first failing assembly across the suite (set -e) test: db-migrate - @echo "==> Testing..." - dotnet test HealthcareSamples.sln --configuration Release \ - --settings coverlet.runsettings \ - --collect:"XPlat Code Coverage" \ - --results-directory TestResults \ - --verbosity normal + @echo "==> Testing (fail-fast)..." + @set -e; \ + for proj in $(TEST_PROJECTS); do \ + echo ""; \ + echo "==> Testing $$proj"; \ + dotnet test "$$proj" --configuration Release \ + --settings coverlet.runsettings \ + --collect:"XPlat Code Coverage" \ + --results-directory TestResults \ + --verbosity normal \ + || { echo ""; echo "FAIL: $$proj failed -- aborting remaining test projects"; exit 1; }; \ + done ## lint: Run all linters (fails on any warning) lint: fmt-check db-migrate diff --git a/xunit.runner.json b/xunit.runner.json new file mode 100644 index 0000000..34723a8 --- /dev/null +++ b/xunit.runner.json @@ -0,0 +1,10 @@ +{ + "$schema": "https://xunit.net/schema/current/xunit.runner.schema.json", + "parallelizeAssembly": false, + "parallelizeTestCollections": false, + "maxParallelThreads": 1, + "stopOnFail": true, + "diagnosticMessages": true, + "longRunningTestSeconds": 30, + "methodDisplay": "method" +} From f95b4f7d83658e9a9a4b39bebe5cb6d3c9a00567 Mon Sep 17 00:00:00 2001 From: Christian Findlay <16697547+MelbourneDeveloper@users.noreply.github.com> Date: Wed, 8 Apr 2026 09:54:22 +1000 Subject: [PATCH 11/59] Fixes --- Clinical/Clinical.Api/Clinical.Api.csproj | 16 +- Clinical/Clinical.Api/Program.cs | 5 +- .../Gatekeeper.Api.Tests.csproj | 2 +- .../Gatekeeper.Api/AuthorizationService.cs | 2 +- Gatekeeper/Gatekeeper.Api/DataProvider.json | 4 +- .../Gatekeeper.Api/Gatekeeper.Api.csproj | 4 +- .../Gatekeeper.Api/JunctionTableInserts.cs | 174 ++++++++++++++++++ ICD10/ICD10.Api/ICD10.Api.csproj | 12 +- .../ICD10.TestSupport.csproj | 4 +- .../Scheduling.Api/Scheduling.Api.csproj | 16 +- 10 files changed, 223 insertions(+), 16 deletions(-) create mode 100644 Gatekeeper/Gatekeeper.Api/JunctionTableInserts.cs diff --git a/Clinical/Clinical.Api/Clinical.Api.csproj b/Clinical/Clinical.Api/Clinical.Api.csproj index d033082..3428a56 100644 --- a/Clinical/Clinical.Api/Clinical.Api.csproj +++ b/Clinical/Clinical.Api/Clinical.Api.csproj @@ -15,8 +15,8 @@ <PackageReference Include="Nimblesite.DataProvider.Core" Version="0.2.0-beta" /> <PackageReference Include="Nimblesite.Lql.Postgres" Version="0.2.0-beta" /> <PackageReference Include="Nimblesite.Sync.Postgres" Version="0.2.0-beta" /> - <PackageReference Include="Nimblesite.DataProvider.Migration.Core" Version="0.2.0-beta" /> - <PackageReference Include="Nimblesite.DataProvider.Migration.Postgres" Version="0.2.0-beta" /> + <PackageReference Include="Nimblesite.DataProvider.Migration.Core" Version="0.3.0-beta" /> + <PackageReference Include="Nimblesite.DataProvider.Migration.Postgres" Version="0.3.0-beta" /> </ItemGroup> <ItemGroup> @@ -60,6 +60,18 @@ StandardOutputImportance="High" StandardErrorImportance="High" /> + <!-- The dataprovider-postgres generator emits quoted PascalCase identifiers + in generated SELECT SQL (e.g. ""fhir_Encounter"".""Id""), but + PostgresDdlGenerator (used by DatabaseSetup) creates the underlying + tables with lowercase identifiers. This mismatch causes runtime + "relation does not exist" errors. Strip the SQL quotes from generated + code so Postgres folds them to lowercase, matching the actual tables. --> + <Exec + Command="sed -i.bak -E -e 's/""([A-Za-z_][A-Za-z0-9_]*)""/\1/g' -e 's/@active IS NULL/@active = -1/g' -e "s/@([A-Za-z_][A-Za-z0-9_]*) IS NULL/@\1 = ''/g" $(MSBuildProjectDirectory)/Generated/Get*.g.cs $(MSBuildProjectDirectory)/Generated/Search*.g.cs && rm -f $(MSBuildProjectDirectory)/Generated/*.g.cs.bak" + WorkingDirectory="$(MSBuildProjectDirectory)" + StandardOutputImportance="High" + StandardErrorImportance="High" + /> <Touch Files="$(MSBuildProjectDirectory)/Generated/.timestamp" AlwaysCreate="true" /> <ItemGroup> <Compile Include="$(MSBuildProjectDirectory)/Generated/**/*.g.cs" /> diff --git a/Clinical/Clinical.Api/Program.cs b/Clinical/Clinical.Api/Program.cs index aa922e5..6606de6 100644 --- a/Clinical/Clinical.Api/Program.cs +++ b/Clinical/Clinical.Api/Program.cs @@ -94,8 +94,11 @@ Func<NpgsqlConnection> getConn ) => { using var conn = getConn(); + // active is mapped to -1 (sentinel "no filter") when not provided -- the + // generated SQL is post-processed to read `@active = -1` instead of + // `@active IS NULL`, since the generator only produces non-nullable int. var result = await conn.GetPatientsAsync( - active.HasValue ? (active.Value ? 1 : 0) : 0, + active.HasValue ? (active.Value ? 1 : 0) : -1, familyName ?? string.Empty, givenName ?? string.Empty, gender ?? string.Empty diff --git a/Gatekeeper/Gatekeeper.Api.Tests/Gatekeeper.Api.Tests.csproj b/Gatekeeper/Gatekeeper.Api.Tests/Gatekeeper.Api.Tests.csproj index 4f20821..f5705ea 100644 --- a/Gatekeeper/Gatekeeper.Api.Tests/Gatekeeper.Api.Tests.csproj +++ b/Gatekeeper/Gatekeeper.Api.Tests/Gatekeeper.Api.Tests.csproj @@ -15,7 +15,7 @@ </PackageReference> <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="9.0.3" /> <PackageReference Include="Npgsql" Version="9.0.2" /> - <PackageReference Include="Nimblesite.DataProvider.Migration.Postgres" Version="0.2.0-beta" /> + <PackageReference Include="Nimblesite.DataProvider.Migration.Postgres" Version="0.3.0-beta" /> <PackageReference Include="coverlet.collector" Version="6.0.4"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> diff --git a/Gatekeeper/Gatekeeper.Api/AuthorizationService.cs b/Gatekeeper/Gatekeeper.Api/AuthorizationService.cs index 4c1ff53..34ba5f1 100644 --- a/Gatekeeper/Gatekeeper.Api/AuthorizationService.cs +++ b/Gatekeeper/Gatekeeper.Api/AuthorizationService.cs @@ -24,9 +24,9 @@ string now { var grantResult = await conn.CheckResourceGrantAsync( userId, - permissionCode, resourceType, resourceId, + permissionCode, now ) .ConfigureAwait(false); diff --git a/Gatekeeper/Gatekeeper.Api/DataProvider.json b/Gatekeeper/Gatekeeper.Api/DataProvider.json index c227d3b..44deec1 100644 --- a/Gatekeeper/Gatekeeper.Api/DataProvider.json +++ b/Gatekeeper/Gatekeeper.Api/DataProvider.json @@ -24,11 +24,9 @@ { "schema": "public", "name": "gk_credential", "generateInsert": true, "primaryKeyColumns": ["id"] }, { "schema": "public", "name": "gk_session", "generateInsert": true, "generateUpdate": true, "primaryKeyColumns": ["id"] }, { "schema": "public", "name": "gk_challenge", "generateInsert": true, "primaryKeyColumns": ["id"] }, - { "schema": "public", "name": "gk_user_role", "generateInsert": true, "primaryKeyColumns": ["user_id", "role_id"] }, { "schema": "public", "name": "gk_permission", "generateInsert": true, "primaryKeyColumns": ["id"] }, { "schema": "public", "name": "gk_resource_grant", "generateInsert": true, "primaryKeyColumns": ["id"] }, - { "schema": "public", "name": "gk_role", "generateInsert": true, "primaryKeyColumns": ["id"] }, - { "schema": "public", "name": "gk_role_permission", "generateInsert": true, "primaryKeyColumns": ["role_id", "permission_id"] } + { "schema": "public", "name": "gk_role", "generateInsert": true, "primaryKeyColumns": ["id"] } ], "connectionString": "Host=localhost;Port=5432;Database=gatekeeper;Username=postgres;Password=changeme" } diff --git a/Gatekeeper/Gatekeeper.Api/Gatekeeper.Api.csproj b/Gatekeeper/Gatekeeper.Api/Gatekeeper.Api.csproj index 5a00f74..39e28ff 100644 --- a/Gatekeeper/Gatekeeper.Api/Gatekeeper.Api.csproj +++ b/Gatekeeper/Gatekeeper.Api/Gatekeeper.Api.csproj @@ -15,8 +15,8 @@ <PackageReference Include="Fido2.AspNet" Version="4.0.0" /> <PackageReference Include="Npgsql" Version="9.0.2" /> <PackageReference Include="Nimblesite.DataProvider.Core" Version="0.2.0-beta" /> - <PackageReference Include="Nimblesite.DataProvider.Migration.Core" Version="0.2.0-beta" /> - <PackageReference Include="Nimblesite.DataProvider.Migration.Postgres" Version="0.2.0-beta" /> + <PackageReference Include="Nimblesite.DataProvider.Migration.Core" Version="0.3.0-beta" /> + <PackageReference Include="Nimblesite.DataProvider.Migration.Postgres" Version="0.3.0-beta" /> <PackageReference Include="Nimblesite.Sync.Postgres" Version="0.2.0-beta" /> </ItemGroup> diff --git a/Gatekeeper/Gatekeeper.Api/JunctionTableInserts.cs b/Gatekeeper/Gatekeeper.Api/JunctionTableInserts.cs new file mode 100644 index 0000000..73637ea --- /dev/null +++ b/Gatekeeper/Gatekeeper.Api/JunctionTableInserts.cs @@ -0,0 +1,174 @@ +// Hand-written replacements for junction-table insert extensions. +// +// The DataProvider Postgres code generator unconditionally appends +// "RETURNING id" to every generated INSERT, but `gk_user_role` and +// `gk_role_permission` use composite primary keys and do not have an +// `id` column. The generated code therefore throws at runtime +// ("column 'id' does not exist"), the error is silently swallowed +// into a Result.Error by the generated try/catch, and dependent +// queries (e.g. /authz/permissions) return empty data. +// +// We disable generateInsert for these tables in DataProvider.json and +// provide drop-in replacements here so existing call sites continue +// to compile against the same `Insertgk_user_roleAsync` / +// `Insertgk_role_permissionAsync` extension method names. + +#nullable enable + +using System.Data; + +namespace Generated; + +/// <summary> +/// Hand-written extension methods for inserting into <c>gk_user_role</c>. +/// Replaces the broken DataProvider-generated version. +/// </summary> +public static class gk_user_roleExtensions +{ + private const string Sql = + @"INSERT INTO public.gk_user_role (user_id, role_id, granted_at, granted_by, expires_at) + VALUES (@user_id, @role_id, @granted_at, @granted_by, @expires_at) + ON CONFLICT DO NOTHING"; + + /// <summary>Inserts a row into <c>gk_user_role</c>.</summary> + public static async Task<Result<Guid?, SqlError>> Insertgk_user_roleAsync( + this NpgsqlConnection conn, + string user_id, + string role_id, + string? granted_at, + string? granted_by, + string? expires_at + ) + { + try + { + await using var cmd = new NpgsqlCommand(Sql, conn); + BindParameters(cmd, user_id, role_id, granted_at, granted_by, expires_at); + _ = await cmd.ExecuteNonQueryAsync().ConfigureAwait(false); + return new Result<Guid?, SqlError>.Ok<Guid?, SqlError>(null); + } + catch (Exception ex) + { + return new Result<Guid?, SqlError>.Error<Guid?, SqlError>(SqlError.FromException(ex)); + } + } + + /// <summary>Transaction overload of <see cref="Insertgk_user_roleAsync(NpgsqlConnection, string, string, string?, string?, string?)"/>.</summary> + public static async Task<Result<Guid?, SqlError>> Insertgk_user_roleAsync( + this IDbTransaction transaction, + string user_id, + string role_id, + string? granted_at, + string? granted_by, + string? expires_at + ) + { + if (transaction.Connection is not NpgsqlConnection conn) + { + return new Result<Guid?, SqlError>.Error<Guid?, SqlError>( + new SqlError("Transaction.Connection must be NpgsqlConnection") + ); + } + + try + { + await using var cmd = new NpgsqlCommand(Sql, conn, (NpgsqlTransaction)transaction); + BindParameters(cmd, user_id, role_id, granted_at, granted_by, expires_at); + _ = await cmd.ExecuteNonQueryAsync().ConfigureAwait(false); + return new Result<Guid?, SqlError>.Ok<Guid?, SqlError>(null); + } + catch (Exception ex) + { + return new Result<Guid?, SqlError>.Error<Guid?, SqlError>(SqlError.FromException(ex)); + } + } + + private static void BindParameters( + NpgsqlCommand cmd, + string user_id, + string role_id, + string? granted_at, + string? granted_by, + string? expires_at + ) + { + cmd.Parameters.AddWithValue("user_id", user_id); + cmd.Parameters.AddWithValue("role_id", role_id); + cmd.Parameters.AddWithValue("granted_at", (object?)granted_at ?? DBNull.Value); + cmd.Parameters.AddWithValue("granted_by", (object?)granted_by ?? DBNull.Value); + cmd.Parameters.AddWithValue("expires_at", (object?)expires_at ?? DBNull.Value); + } +} + +/// <summary> +/// Hand-written extension methods for inserting into <c>gk_role_permission</c>. +/// Replaces the broken DataProvider-generated version. +/// </summary> +public static class gk_role_permissionExtensions +{ + private const string Sql = + @"INSERT INTO public.gk_role_permission (role_id, permission_id, granted_at) + VALUES (@role_id, @permission_id, @granted_at) + ON CONFLICT DO NOTHING"; + + /// <summary>Inserts a row into <c>gk_role_permission</c>.</summary> + public static async Task<Result<Guid?, SqlError>> Insertgk_role_permissionAsync( + this NpgsqlConnection conn, + string role_id, + string permission_id, + string? granted_at + ) + { + try + { + await using var cmd = new NpgsqlCommand(Sql, conn); + BindParameters(cmd, role_id, permission_id, granted_at); + _ = await cmd.ExecuteNonQueryAsync().ConfigureAwait(false); + return new Result<Guid?, SqlError>.Ok<Guid?, SqlError>(null); + } + catch (Exception ex) + { + return new Result<Guid?, SqlError>.Error<Guid?, SqlError>(SqlError.FromException(ex)); + } + } + + /// <summary>Transaction overload of <see cref="Insertgk_role_permissionAsync(NpgsqlConnection, string, string, string?)"/>.</summary> + public static async Task<Result<Guid?, SqlError>> Insertgk_role_permissionAsync( + this IDbTransaction transaction, + string role_id, + string permission_id, + string? granted_at + ) + { + if (transaction.Connection is not NpgsqlConnection conn) + { + return new Result<Guid?, SqlError>.Error<Guid?, SqlError>( + new SqlError("Transaction.Connection must be NpgsqlConnection") + ); + } + + try + { + await using var cmd = new NpgsqlCommand(Sql, conn, (NpgsqlTransaction)transaction); + BindParameters(cmd, role_id, permission_id, granted_at); + _ = await cmd.ExecuteNonQueryAsync().ConfigureAwait(false); + return new Result<Guid?, SqlError>.Ok<Guid?, SqlError>(null); + } + catch (Exception ex) + { + return new Result<Guid?, SqlError>.Error<Guid?, SqlError>(SqlError.FromException(ex)); + } + } + + private static void BindParameters( + NpgsqlCommand cmd, + string role_id, + string permission_id, + string? granted_at + ) + { + cmd.Parameters.AddWithValue("role_id", role_id); + cmd.Parameters.AddWithValue("permission_id", permission_id); + cmd.Parameters.AddWithValue("granted_at", (object?)granted_at ?? DBNull.Value); + } +} diff --git a/ICD10/ICD10.Api/ICD10.Api.csproj b/ICD10/ICD10.Api/ICD10.Api.csproj index 08e0add..8712e67 100644 --- a/ICD10/ICD10.Api/ICD10.Api.csproj +++ b/ICD10/ICD10.Api/ICD10.Api.csproj @@ -14,8 +14,8 @@ <PackageReference Include="Npgsql" Version="9.0.2" /> <PackageReference Include="Nimblesite.DataProvider.Core" Version="0.2.0-beta" /> <PackageReference Include="Nimblesite.Lql.Postgres" Version="0.2.0-beta" /> - <PackageReference Include="Nimblesite.DataProvider.Migration.Core" Version="0.2.0-beta" /> - <PackageReference Include="Nimblesite.DataProvider.Migration.Postgres" Version="0.2.0-beta" /> + <PackageReference Include="Nimblesite.DataProvider.Migration.Core" Version="0.3.0-beta" /> + <PackageReference Include="Nimblesite.DataProvider.Migration.Postgres" Version="0.3.0-beta" /> </ItemGroup> <ItemGroup> @@ -58,6 +58,14 @@ StandardOutputImportance="High" StandardErrorImportance="High" /> + <!-- Strip generator's quoted PascalCase identifiers and rewrite IS NULL + parameter checks. See Clinical.Api.csproj for explanation. --> + <Exec + Command="sed -i.bak -E -e 's/""([A-Za-z_][A-Za-z0-9_]*)""/\1/g' -e 's/@active IS NULL/@active = -1/g' -e "s/@([A-Za-z_][A-Za-z0-9_]*) IS NULL/@\1 = ''/g" $(MSBuildProjectDirectory)/Generated/Get*.g.cs $(MSBuildProjectDirectory)/Generated/Search*.g.cs && rm -f $(MSBuildProjectDirectory)/Generated/*.g.cs.bak" + WorkingDirectory="$(MSBuildProjectDirectory)" + StandardOutputImportance="High" + StandardErrorImportance="High" + /> <Touch Files="$(MSBuildProjectDirectory)/Generated/.timestamp" AlwaysCreate="true" /> <ItemGroup> <Compile Include="$(MSBuildProjectDirectory)/Generated/**/*.g.cs" /> diff --git a/ICD10/ICD10.TestSupport/ICD10.TestSupport.csproj b/ICD10/ICD10.TestSupport/ICD10.TestSupport.csproj index 904f5f6..866290a 100644 --- a/ICD10/ICD10.TestSupport/ICD10.TestSupport.csproj +++ b/ICD10/ICD10.TestSupport/ICD10.TestSupport.csproj @@ -6,7 +6,7 @@ <ItemGroup> <PackageReference Include="Npgsql" Version="9.0.2" /> - <PackageReference Include="Nimblesite.DataProvider.Migration.Core" Version="0.2.0-beta" /> - <PackageReference Include="Nimblesite.DataProvider.Migration.Postgres" Version="0.2.0-beta" /> + <PackageReference Include="Nimblesite.DataProvider.Migration.Core" Version="0.3.0-beta" /> + <PackageReference Include="Nimblesite.DataProvider.Migration.Postgres" Version="0.3.0-beta" /> </ItemGroup> </Project> diff --git a/Scheduling/Scheduling.Api/Scheduling.Api.csproj b/Scheduling/Scheduling.Api/Scheduling.Api.csproj index b5287db..92cc2a6 100644 --- a/Scheduling/Scheduling.Api/Scheduling.Api.csproj +++ b/Scheduling/Scheduling.Api/Scheduling.Api.csproj @@ -15,8 +15,8 @@ <PackageReference Include="Nimblesite.DataProvider.Core" Version="0.2.0-beta" /> <PackageReference Include="Nimblesite.Lql.Postgres" Version="0.2.0-beta" /> <PackageReference Include="Nimblesite.Sync.Postgres" Version="0.2.0-beta" /> - <PackageReference Include="Nimblesite.DataProvider.Migration.Core" Version="0.2.0-beta" /> - <PackageReference Include="Nimblesite.DataProvider.Migration.Postgres" Version="0.2.0-beta" /> + <PackageReference Include="Nimblesite.DataProvider.Migration.Core" Version="0.3.0-beta" /> + <PackageReference Include="Nimblesite.DataProvider.Migration.Postgres" Version="0.3.0-beta" /> </ItemGroup> <ItemGroup> @@ -60,6 +60,18 @@ StandardOutputImportance="High" StandardErrorImportance="High" /> + <!-- The dataprovider-postgres generator emits quoted PascalCase identifiers + in generated SELECT SQL while PostgresDdlGenerator (used by DatabaseSetup) + creates the underlying tables with lowercase identifiers. Strip quoting + so Postgres folds identifiers to lowercase, matching the actual tables. + Also rewrite IS NULL parameter checks to sentinel-value comparisons, + since the generated client passes non-nullable types. --> + <Exec + Command="sed -i.bak -E -e 's/""([A-Za-z_][A-Za-z0-9_]*)""/\1/g' -e 's/@active IS NULL/@active = -1/g' -e "s/@([A-Za-z_][A-Za-z0-9_]*) IS NULL/@\1 = ''/g" $(MSBuildProjectDirectory)/Generated/Get*.g.cs $(MSBuildProjectDirectory)/Generated/Search*.g.cs && rm -f $(MSBuildProjectDirectory)/Generated/*.g.cs.bak" + WorkingDirectory="$(MSBuildProjectDirectory)" + StandardOutputImportance="High" + StandardErrorImportance="High" + /> <Touch Files="$(MSBuildProjectDirectory)/Generated/.timestamp" AlwaysCreate="true" /> <ItemGroup> <Compile Include="$(MSBuildProjectDirectory)/Generated/**/*.g.cs" /> From 69fa0eb8c5bfc71c28bea154eba3aa8b93a1f486 Mon Sep 17 00:00:00 2001 From: Christian Findlay <16697547+MelbourneDeveloper@users.noreply.github.com> Date: Wed, 8 Apr 2026 11:09:08 +1000 Subject: [PATCH 12/59] Fixes --- CLAUDE.md | 6 +- Clinical/Clinical.Api/Clinical.Api.csproj | 1 - Clinical/Clinical.Api/DatabaseSetup.cs | 12 +- Gatekeeper/Gatekeeper.Api/DatabaseSetup.cs | 15 +- .../Gatekeeper.Api/Gatekeeper.Api.csproj | 5 +- ICD10/ICD10.Api.Tests/ICD10.Api.Tests.csproj | 1 + ICD10/ICD10.Api/DatabaseSetup.cs | 12 +- ICD10/ICD10.Api/ICD10.Api.csproj | 1 - .../ICD10.TestSupport.csproj | 5 +- ICD10/ICD10.TestSupport/Icd10TestDatabase.cs | 12 +- NuGet.config | 2 +- Scheduling/Scheduling.Api/DatabaseSetup.cs | 12 +- .../Scheduling.Api/Scheduling.Api.csproj | 1 - Shared/Authorization/Authorization.csproj | 1 + Shared/Authorization/LowercaseDdl.cs | 170 ++++++++++++++++++ 15 files changed, 218 insertions(+), 38 deletions(-) create mode 100644 Shared/Authorization/LowercaseDdl.cs diff --git a/CLAUDE.md b/CLAUDE.md index b8213a3..d827b51 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,10 +1,12 @@ -<!-- agent-pmo:29b9dcf --> - # HealthcareSamples -- Agent Instructions +⚠️ CRITICAL: **Reduce token usage.** Check file size before loading. Write less. Delete fluff and dead code. Alert user when context is loaded with pointless files. ⚠️ + > Read this entire file before writing any code. > These rules are NON-NEGOTIABLE. Violations will be rejected in review. +<!-- agent-pmo:29b9dcf --> + ## Project Overview HealthcareSamples is a comprehensive demonstration of the DataProvider .NET toolkit. It contains three FHIR-compliant microservices (Clinical API, Scheduling API, ICD-10 API) with bidirectional sync workers, semantic search via pgvector embeddings, a React dashboard (H5 transpiler), and Docker configuration. All medical data follows the FHIR R5 specification. diff --git a/Clinical/Clinical.Api/Clinical.Api.csproj b/Clinical/Clinical.Api/Clinical.Api.csproj index 3428a56..c137c22 100644 --- a/Clinical/Clinical.Api/Clinical.Api.csproj +++ b/Clinical/Clinical.Api/Clinical.Api.csproj @@ -16,7 +16,6 @@ <PackageReference Include="Nimblesite.Lql.Postgres" Version="0.2.0-beta" /> <PackageReference Include="Nimblesite.Sync.Postgres" Version="0.2.0-beta" /> <PackageReference Include="Nimblesite.DataProvider.Migration.Core" Version="0.3.0-beta" /> - <PackageReference Include="Nimblesite.DataProvider.Migration.Postgres" Version="0.3.0-beta" /> </ItemGroup> <ItemGroup> diff --git a/Clinical/Clinical.Api/DatabaseSetup.cs b/Clinical/Clinical.Api/DatabaseSetup.cs index 63e6c57..c2c220a 100644 --- a/Clinical/Clinical.Api/DatabaseSetup.cs +++ b/Clinical/Clinical.Api/DatabaseSetup.cs @@ -1,5 +1,5 @@ using Nimblesite.DataProvider.Migration.Core; -using Nimblesite.DataProvider.Migration.Postgres; +using Samples.Authorization; using InitError = Outcome.Result<bool, string>.Error<bool, string>; using InitOk = Outcome.Result<bool, string>.Ok<bool, string>; using InitResult = Outcome.Result<bool, string>; @@ -41,10 +41,12 @@ public static InitResult Initialize(NpgsqlConnection connection, ILogger logger) foreach (var table in schema.Tables) { - var ddl = PostgresDdlGenerator.Generate(new CreateTableOperation(table)); - using var cmd = connection.CreateCommand(); - cmd.CommandText = ddl; - cmd.ExecuteNonQuery(); + foreach (var statement in LowercaseDdl.GenerateStatements(table)) + { + using var cmd = connection.CreateCommand(); + cmd.CommandText = statement; + cmd.ExecuteNonQuery(); + } logger.Log(LogLevel.Debug, "Created table {TableName}", table.Name); } diff --git a/Gatekeeper/Gatekeeper.Api/DatabaseSetup.cs b/Gatekeeper/Gatekeeper.Api/DatabaseSetup.cs index dde1471..ad511c3 100644 --- a/Gatekeeper/Gatekeeper.Api/DatabaseSetup.cs +++ b/Gatekeeper/Gatekeeper.Api/DatabaseSetup.cs @@ -1,5 +1,5 @@ using Nimblesite.DataProvider.Migration.Core; -using Nimblesite.DataProvider.Migration.Postgres; +using Samples.Authorization; using InitError = Outcome.Result<bool, string>.Error<bool, string>; using InitOk = Outcome.Result<bool, string>.Ok<bool, string>; using InitResult = Outcome.Result<bool, string>; @@ -35,19 +35,8 @@ private static InitResult CreateSchemaFromMigration(NpgsqlConnection conn, ILogg foreach (var table in schema.Tables) { - var ddl = PostgresDdlGenerator.Generate(new CreateTableOperation(table)); - // DDL may contain multiple statements (CREATE TABLE + CREATE INDEX) - foreach ( - var statement in ddl.Split( - ';', - StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries - ) - ) + foreach (var statement in LowercaseDdl.GenerateStatements(table)) { - if (string.IsNullOrWhiteSpace(statement)) - { - continue; - } using var cmd = conn.CreateCommand(); cmd.CommandText = statement; cmd.ExecuteNonQuery(); diff --git a/Gatekeeper/Gatekeeper.Api/Gatekeeper.Api.csproj b/Gatekeeper/Gatekeeper.Api/Gatekeeper.Api.csproj index 39e28ff..e852d08 100644 --- a/Gatekeeper/Gatekeeper.Api/Gatekeeper.Api.csproj +++ b/Gatekeeper/Gatekeeper.Api/Gatekeeper.Api.csproj @@ -16,10 +16,13 @@ <PackageReference Include="Npgsql" Version="9.0.2" /> <PackageReference Include="Nimblesite.DataProvider.Core" Version="0.2.0-beta" /> <PackageReference Include="Nimblesite.DataProvider.Migration.Core" Version="0.3.0-beta" /> - <PackageReference Include="Nimblesite.DataProvider.Migration.Postgres" Version="0.3.0-beta" /> <PackageReference Include="Nimblesite.Sync.Postgres" Version="0.2.0-beta" /> </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\..\Shared\Authorization\Authorization.csproj" /> + </ItemGroup> + <ItemGroup> <AdditionalFiles Include="Sql/*.sql" /> <AdditionalFiles Include="DataProvider.json" /> diff --git a/ICD10/ICD10.Api.Tests/ICD10.Api.Tests.csproj b/ICD10/ICD10.Api.Tests/ICD10.Api.Tests.csproj index e680c03..cdef0b2 100644 --- a/ICD10/ICD10.Api.Tests/ICD10.Api.Tests.csproj +++ b/ICD10/ICD10.Api.Tests/ICD10.Api.Tests.csproj @@ -15,6 +15,7 @@ </PackageReference> <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="10.0.3" /> <PackageReference Include="Npgsql" Version="9.0.2" /> + <PackageReference Include="Nimblesite.DataProvider.Migration.Postgres" Version="0.3.0-beta" /> <PackageReference Include="coverlet.collector" Version="6.0.4"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> diff --git a/ICD10/ICD10.Api/DatabaseSetup.cs b/ICD10/ICD10.Api/DatabaseSetup.cs index 739dd70..d158886 100644 --- a/ICD10/ICD10.Api/DatabaseSetup.cs +++ b/ICD10/ICD10.Api/DatabaseSetup.cs @@ -1,5 +1,5 @@ using Nimblesite.DataProvider.Migration.Core; -using Nimblesite.DataProvider.Migration.Postgres; +using Samples.Authorization; using InitError = Outcome.Result<bool, string>.Error<bool, string>; using InitOk = Outcome.Result<bool, string>.Ok<bool, string>; using InitResult = Outcome.Result<bool, string>; @@ -53,10 +53,12 @@ public static InitResult Initialize(NpgsqlConnection connection, ILogger logger) foreach (var table in schema.Tables) { - var ddl = PostgresDdlGenerator.Generate(new CreateTableOperation(table)); - using var cmd = connection.CreateCommand(); - cmd.CommandText = ddl; - cmd.ExecuteNonQuery(); + foreach (var statement in LowercaseDdl.GenerateStatements(table)) + { + using var cmd = connection.CreateCommand(); + cmd.CommandText = statement; + cmd.ExecuteNonQuery(); + } logger.Log(LogLevel.Debug, "Created table {TableName}", table.Name); } diff --git a/ICD10/ICD10.Api/ICD10.Api.csproj b/ICD10/ICD10.Api/ICD10.Api.csproj index 8712e67..1994da8 100644 --- a/ICD10/ICD10.Api/ICD10.Api.csproj +++ b/ICD10/ICD10.Api/ICD10.Api.csproj @@ -15,7 +15,6 @@ <PackageReference Include="Nimblesite.DataProvider.Core" Version="0.2.0-beta" /> <PackageReference Include="Nimblesite.Lql.Postgres" Version="0.2.0-beta" /> <PackageReference Include="Nimblesite.DataProvider.Migration.Core" Version="0.3.0-beta" /> - <PackageReference Include="Nimblesite.DataProvider.Migration.Postgres" Version="0.3.0-beta" /> </ItemGroup> <ItemGroup> diff --git a/ICD10/ICD10.TestSupport/ICD10.TestSupport.csproj b/ICD10/ICD10.TestSupport/ICD10.TestSupport.csproj index 866290a..a21345f 100644 --- a/ICD10/ICD10.TestSupport/ICD10.TestSupport.csproj +++ b/ICD10/ICD10.TestSupport/ICD10.TestSupport.csproj @@ -7,6 +7,9 @@ <ItemGroup> <PackageReference Include="Npgsql" Version="9.0.2" /> <PackageReference Include="Nimblesite.DataProvider.Migration.Core" Version="0.3.0-beta" /> - <PackageReference Include="Nimblesite.DataProvider.Migration.Postgres" Version="0.3.0-beta" /> + </ItemGroup> + + <ItemGroup> + <ProjectReference Include="..\..\Shared\Authorization\Authorization.csproj" /> </ItemGroup> </Project> diff --git a/ICD10/ICD10.TestSupport/Icd10TestDatabase.cs b/ICD10/ICD10.TestSupport/Icd10TestDatabase.cs index f0497e3..0ec8a8c 100644 --- a/ICD10/ICD10.TestSupport/Icd10TestDatabase.cs +++ b/ICD10/ICD10.TestSupport/Icd10TestDatabase.cs @@ -1,6 +1,6 @@ using Nimblesite.DataProvider.Migration.Core; -using Nimblesite.DataProvider.Migration.Postgres; using Npgsql; +using Samples.Authorization; namespace ICD10.TestSupport; @@ -37,7 +37,15 @@ public static void Initialize(string connectionString, string schemaYamlPath) } var schema = SchemaYamlSerializer.FromYamlFile(schemaYamlPath); - PostgresDdlGenerator.MigrateSchema(conn, schema); + foreach (var table in schema.Tables) + { + foreach (var statement in LowercaseDdl.GenerateStatements(table)) + { + using var cmd = conn.CreateCommand(); + cmd.CommandText = statement; + cmd.ExecuteNonQuery(); + } + } TestDataSeeder.Seed(conn); TestDataSeeder.SeedEmbeddings(conn); diff --git a/NuGet.config b/NuGet.config index 30bd234..4d736c1 100644 --- a/NuGet.config +++ b/NuGet.config @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8"?> <configuration> <packageSources> + <clear /> <add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" /> - <add key="local-tools" value="./nupkgs" /> </packageSources> </configuration> diff --git a/Scheduling/Scheduling.Api/DatabaseSetup.cs b/Scheduling/Scheduling.Api/DatabaseSetup.cs index fccdae2..80cc479 100644 --- a/Scheduling/Scheduling.Api/DatabaseSetup.cs +++ b/Scheduling/Scheduling.Api/DatabaseSetup.cs @@ -1,5 +1,5 @@ using Nimblesite.DataProvider.Migration.Core; -using Nimblesite.DataProvider.Migration.Postgres; +using Samples.Authorization; using InitError = Outcome.Result<bool, string>.Error<bool, string>; using InitOk = Outcome.Result<bool, string>.Ok<bool, string>; using InitResult = Outcome.Result<bool, string>; @@ -38,10 +38,12 @@ public static InitResult Initialize(NpgsqlConnection connection, ILogger logger) foreach (var table in schema.Tables) { - var ddl = PostgresDdlGenerator.Generate(new CreateTableOperation(table)); - using var cmd = connection.CreateCommand(); - cmd.CommandText = ddl; - cmd.ExecuteNonQuery(); + foreach (var statement in LowercaseDdl.GenerateStatements(table)) + { + using var cmd = connection.CreateCommand(); + cmd.CommandText = statement; + cmd.ExecuteNonQuery(); + } logger.Log(LogLevel.Debug, "Created table {TableName}", table.Name); } diff --git a/Scheduling/Scheduling.Api/Scheduling.Api.csproj b/Scheduling/Scheduling.Api/Scheduling.Api.csproj index 92cc2a6..c9abde4 100644 --- a/Scheduling/Scheduling.Api/Scheduling.Api.csproj +++ b/Scheduling/Scheduling.Api/Scheduling.Api.csproj @@ -16,7 +16,6 @@ <PackageReference Include="Nimblesite.Lql.Postgres" Version="0.2.0-beta" /> <PackageReference Include="Nimblesite.Sync.Postgres" Version="0.2.0-beta" /> <PackageReference Include="Nimblesite.DataProvider.Migration.Core" Version="0.3.0-beta" /> - <PackageReference Include="Nimblesite.DataProvider.Migration.Postgres" Version="0.3.0-beta" /> </ItemGroup> <ItemGroup> diff --git a/Shared/Authorization/Authorization.csproj b/Shared/Authorization/Authorization.csproj index 7608f91..beeebb2 100644 --- a/Shared/Authorization/Authorization.csproj +++ b/Shared/Authorization/Authorization.csproj @@ -8,5 +8,6 @@ <ItemGroup> <FrameworkReference Include="Microsoft.AspNetCore.App" /> + <PackageReference Include="Nimblesite.DataProvider.Migration.Core" Version="0.3.0-beta" /> </ItemGroup> </Project> diff --git a/Shared/Authorization/LowercaseDdl.cs b/Shared/Authorization/LowercaseDdl.cs new file mode 100644 index 0000000..6d94ebd --- /dev/null +++ b/Shared/Authorization/LowercaseDdl.cs @@ -0,0 +1,170 @@ +// PostgreSQL DDL emitter that produces lowercase identifiers, matching the +// case-folding behaviour of unquoted identifiers in dataprovider-postgres +// generated INSERT/SELECT SQL. +// +// This intentionally does NOT depend on +// Nimblesite.DataProvider.Migration.Postgres.PostgresDdlGenerator: that +// type's public surface has shifted across recent beta releases and was +// causing compile failures in some build environments. Owning the DDL +// here keeps DatabaseSetup.cs files in every API project free of that +// version risk while preserving the lowercase identifier convention the +// generated SQL relies on. + +using System.Text; +using Nimblesite.DataProvider.Migration.Core; + +namespace Samples.Authorization; + +/// <summary> +/// Generates <c>CREATE TABLE</c> / <c>CREATE INDEX</c> statements with +/// lowercase identifiers from a <see cref="TableDefinition"/>. +/// </summary> +public static class LowercaseDdl +{ + /// <summary>Returns the DDL statements needed to create the table and its indexes.</summary> + public static IEnumerable<string> GenerateStatements(TableDefinition table) + { + yield return BuildCreateTable(table); + if (table.Indexes is { } indexes) + { + foreach (var idx in indexes) + { + yield return BuildCreateIndex(table, idx); + } + } + } + + private static string BuildCreateTable(TableDefinition table) + { + var sb = new StringBuilder(); + sb.Append("CREATE TABLE IF NOT EXISTS "); + sb.Append(QualifiedName(table)); + sb.Append(" ("); + var clauses = new List<string>(); + foreach (var col in table.Columns) + { + clauses.Add(BuildColumnClause(col)); + } + if (table.PrimaryKey is { } pk) + { + clauses.Add(BuildPrimaryKey(pk)); + } + if (table.UniqueConstraints is { Count: > 0 } uniques) + { + clauses.AddRange(uniques.Select(BuildUnique)); + } + if (table.ForeignKeys is { Count: > 0 } fks) + { + clauses.AddRange(fks.Select(BuildForeignKey)); + } + sb.Append(string.Join(", ", clauses)); + sb.Append(')'); + return sb.ToString(); + } + + private static string BuildColumnClause(ColumnDefinition col) + { + var sb = new StringBuilder(); + sb.Append(Quote(col.Name)); + sb.Append(' '); + sb.Append(MapType(col.Type)); + if (col.IsNullable == false) + { + sb.Append(" NOT NULL"); + } + if (!string.IsNullOrEmpty(col.DefaultValue)) + { + sb.Append(" DEFAULT "); + sb.Append(col.DefaultValue); + } + if (!string.IsNullOrEmpty(col.CheckConstraint)) + { + sb.Append(" CHECK ("); + sb.Append(col.CheckConstraint); + sb.Append(')'); + } + return sb.ToString(); + } + + private static string BuildPrimaryKey(PrimaryKeyDefinition pk) + { + var name = string.IsNullOrEmpty(pk.Name) ? "pk" : pk.Name; + var cols = string.Join(", ", pk.Columns.Select(Quote)); + return $"CONSTRAINT {Quote(name)} PRIMARY KEY ({cols})"; + } + + private static string BuildUnique(UniqueConstraintDefinition uq) + { + var name = string.IsNullOrEmpty(uq.Name) ? "uq" : uq.Name; + var cols = string.Join(", ", uq.Columns.Select(Quote)); + return $"CONSTRAINT {Quote(name)} UNIQUE ({cols})"; + } + + private static string BuildForeignKey(ForeignKeyDefinition fk) + { + var name = string.IsNullOrEmpty(fk.Name) ? "fk" : fk.Name; + var cols = string.Join(", ", fk.Columns.Select(Quote)); + var refSchema = string.IsNullOrEmpty(fk.ReferencedSchema) ? "public" : fk.ReferencedSchema; + var refTable = $"{Quote(refSchema)}.{Quote(fk.ReferencedTable)}"; + var refCols = string.Join(", ", fk.ReferencedColumns.Select(Quote)); + var sb = new StringBuilder(); + sb.Append( + $"CONSTRAINT {Quote(name)} FOREIGN KEY ({cols}) REFERENCES {refTable} ({refCols})" + ); + if (fk.OnDelete != ForeignKeyAction.NoAction) + { + sb.Append(" ON DELETE "); + sb.Append(MapAction(fk.OnDelete)); + } + return sb.ToString(); + } + + private static string BuildCreateIndex(TableDefinition table, IndexDefinition idx) + { + var unique = idx.IsUnique ? "UNIQUE " : string.Empty; + var cols = string.Join(", ", idx.Columns.Select(Quote)); + return $"CREATE {unique}INDEX IF NOT EXISTS {Quote(idx.Name)} ON {QualifiedName(table)} ({cols})"; + } + + private static string QualifiedName(TableDefinition table) + { + var schema = string.IsNullOrEmpty(table.Schema) ? "public" : table.Schema; + return $"{Quote(schema)}.{Quote(table.Name)}"; + } + + private static string Quote(string identifier) => + "\"" + identifier.ToLowerInvariant().Replace("\"", "\"\"", StringComparison.Ordinal) + "\""; + + private static string MapType(PortableType type) => + type switch + { + TextType => "TEXT", + IntType => "INTEGER", + BigIntType => "BIGINT", + SmallIntType => "SMALLINT", + TinyIntType => "SMALLINT", + DoubleType => "DOUBLE PRECISION", + FloatType => "REAL", + BooleanType => "BOOLEAN", + DateTimeType => "TIMESTAMP", + DateType => "DATE", + DateTimeOffsetType => "TIMESTAMPTZ", + UuidType => "UUID", + BlobType => "BYTEA", + VarBinaryType => "BYTEA", + JsonType => "JSONB", + _ => throw new NotSupportedException( + $"Column type {type.GetType().Name} is not supported" + ), + }; + + private static string MapAction(ForeignKeyAction action) => + action switch + { + ForeignKeyAction.Cascade => "CASCADE", + ForeignKeyAction.SetNull => "SET NULL", + ForeignKeyAction.SetDefault => "SET DEFAULT", + ForeignKeyAction.Restrict => "RESTRICT", + _ => "NO ACTION", + }; +} From 85e6b2cbae8780f37381743fadd6f453f92d1f38 Mon Sep 17 00:00:00 2001 From: Christian Findlay <16697547+MelbourneDeveloper@users.noreply.github.com> Date: Wed, 8 Apr 2026 11:15:42 +1000 Subject: [PATCH 13/59] format --- Gatekeeper/Gatekeeper.Api/Program.cs | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/Gatekeeper/Gatekeeper.Api/Program.cs b/Gatekeeper/Gatekeeper.Api/Program.cs index 4b6f7a2..50ef2e4 100644 --- a/Gatekeeper/Gatekeeper.Api/Program.cs +++ b/Gatekeeper/Gatekeeper.Api/Program.cs @@ -307,7 +307,11 @@ ILogger<Program> logger var rolesResult = await conn.GetUserRolesAsync(storedChallenge.user_id, now) .ConfigureAwait(false); var roles = rolesResult is GetUserRolesOk rolesOk - ? rolesOk.Value.Select(r => r.name).Where(n => n is not null).Select(n => n!).ToList() + ? rolesOk + .Value.Select(r => r.name) + .Where(n => n is not null) + .Select(n => n!) + .ToList() : new List<string>(); // Generate JWT @@ -412,11 +416,15 @@ UPDATE gk_credential using var userUpdateCmd = conn.CreateCommand(); userUpdateCmd.CommandText = "UPDATE gk_user SET last_login_at = @now WHERE id = @id"; userUpdateCmd.Parameters.AddWithValue("@now", now); - userUpdateCmd.Parameters.AddWithValue("@id", (object?)storedCred.user_id ?? DBNull.Value); + userUpdateCmd.Parameters.AddWithValue( + "@id", + (object?)storedCred.user_id ?? DBNull.Value + ); await userUpdateCmd.ExecuteNonQueryAsync().ConfigureAwait(false); // Get user info for token - var userResult = await conn.GetUserByIdAsync(storedCred.user_id ?? string.Empty).ConfigureAwait(false); + var userResult = await conn.GetUserByIdAsync(storedCred.user_id ?? string.Empty) + .ConfigureAwait(false); var user = userResult is GetUserByIdOk { Value.Count: > 0 } userOk ? userOk.Value[0] : null; @@ -425,7 +433,11 @@ UPDATE gk_credential var rolesResult = await conn.GetUserRolesAsync(storedCred.user_id ?? string.Empty, now) .ConfigureAwait(false); var roles = rolesResult is GetUserRolesOk rolesOk - ? rolesOk.Value.Select(r => r.name).Where(n => n is not null).Select(n => n!).ToList() + ? rolesOk + .Value.Select(r => r.name) + .Where(n => n is not null) + .Select(n => n!) + .ToList() : new List<string>(); // Generate JWT From 294559420b8b87336f5cb0bae7bd48b0c67dcc9a Mon Sep 17 00:00:00 2001 From: Christian Findlay <16697547+MelbourneDeveloper@users.noreply.github.com> Date: Wed, 8 Apr 2026 17:33:20 +1000 Subject: [PATCH 14/59] stuff --- .github/workflows/ci.yml | 31 ++++++---- .../Dashboard.Integration.Tests.csproj | 4 ++ Makefile | 60 ++++++++++++++----- coverage-thresholds.json | 23 +++++++ 4 files changed, 92 insertions(+), 26 deletions(-) create mode 100644 coverage-thresholds.json diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e5a3bac..e760fac 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,9 +27,27 @@ jobs: with: dotnet-version: '10.0.x' + - run: dotnet restore + - run: dotnet tool restore + + # csharpier needs no DB -- run it first so format issues fail + # before paying the cost of docker, codegen, or Playwright. + - name: Format check + run: make fmt-check + - name: Start Postgres (pgvector) via docker compose run: make db-up + - name: Migrate Postgres schemas + run: make db-migrate + + # `make lint` runs the full Release build, which triggers + # dataprovider-postgres codegen against the live database, so it + # has to come after db-up + db-migrate. Still kept ahead of the + # embedding service / Playwright steps to fail fast on warnings. + - name: Lint + run: make lint + - name: Start embedding service run: | cd ICD10/embedding-service @@ -46,12 +64,6 @@ jobs: docker compose logs exit 1 - - run: dotnet restore - - run: dotnet tool restore - - - name: Migrate Postgres schemas - run: make db-migrate - - name: Install Playwright browsers run: | dotnet build Dashboard/Dashboard.Integration.Tests/Dashboard.Integration.Tests.csproj --configuration Release @@ -59,15 +71,12 @@ jobs: export PATH="$PATH:$HOME/.dotnet/tools" playwright install --with-deps chromium - - name: Lint - run: make lint - - name: Test run: make test + # Per-project thresholds live in coverage-thresholds.json (default 80%). + # Bump entries by floor(measured) - 1 whenever real coverage improves. - name: Coverage check - env: - COVERAGE_THRESHOLD: ${{ vars.COVERAGE_THRESHOLD_DOTNET || '80' }} run: make coverage-check - name: Upload coverage diff --git a/Dashboard/Dashboard.Integration.Tests/Dashboard.Integration.Tests.csproj b/Dashboard/Dashboard.Integration.Tests/Dashboard.Integration.Tests.csproj index 21ecd4b..beaec13 100644 --- a/Dashboard/Dashboard.Integration.Tests/Dashboard.Integration.Tests.csproj +++ b/Dashboard/Dashboard.Integration.Tests/Dashboard.Integration.Tests.csproj @@ -21,6 +21,10 @@ <PackageReference Include="Npgsql" Version="9.0.2" /> <PackageReference Include="Testcontainers.PostgreSql" Version="4.3.0" /> <PackageReference Include="Microsoft.Bcl.Memory" Version="10.0.5" /> + <PackageReference Include="coverlet.collector" Version="6.0.4"> + <PrivateAssets>all</PrivateAssets> + <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> + </PackageReference> </ItemGroup> <ItemGroup> diff --git a/Makefile b/Makefile index fc8cc6c..78839d7 100644 --- a/Makefile +++ b/Makefile @@ -20,8 +20,10 @@ else MKDIR = mkdir -p endif -# Coverage threshold (override in CI via env var or per-repo) -COVERAGE_THRESHOLD ?= 80 +# Per-project coverage thresholds live in this JSON file. Each test +# project gets its own minimum line-rate; bump them via `make coverage-check` +# output minus 1 percentage point (rounding margin). +COVERAGE_THRESHOLDS_FILE ?= coverage-thresholds.json # Postgres dev database (docker compose). Override in CI via env vars. DB_COMPOSE_FILE ?= docker/docker-compose.db.yml @@ -52,16 +54,20 @@ TEST_PROJECTS = \ ## test: Run full test suite with coverage (FAIL FAST) ## - Stops at the first failing test inside an assembly (xunit stopOnFail) ## - Stops at the first failing assembly across the suite (set -e) +## - Each project's coverage lands under TestResults/<project-dir>/ so +## `make coverage-check` can attribute results back to a project. test: db-migrate @echo "==> Testing (fail-fast)..." @set -e; \ + rm -rf TestResults; \ for proj in $(TEST_PROJECTS); do \ + proj_dir=$$(dirname "$$proj"); \ echo ""; \ echo "==> Testing $$proj"; \ dotnet test "$$proj" --configuration Release \ --settings coverlet.runsettings \ --collect:"XPlat Code Coverage" \ - --results-directory TestResults \ + --results-directory "TestResults/$$proj_dir" \ --verbosity normal \ || { echo ""; echo "FAIL: $$proj failed -- aborting remaining test projects"; exit 1; }; \ done @@ -107,20 +113,44 @@ coverage: -reporttypes:Html @echo "==> HTML report: coverage/html/index.html" -## coverage-check: Assert thresholds (exits non-zero if below) +## coverage-check: Assert per-project line-rate >= threshold from $(COVERAGE_THRESHOLDS_FILE) +## The JSON file declares { "default_threshold": N, "projects": { "<dir>": { "threshold": N } } }. +## A project that is missing from the file inherits "default_threshold". +## When coverage actually goes UP, edit the file: floor(measured) - 1 to leave a rounding cushion. coverage-check: - @echo "==> Checking coverage thresholds..." - @COBERTURA=$$(find TestResults -name 'coverage.cobertura.xml' | head -1); \ - if [ -z "$$COBERTURA" ]; then echo "FAIL: No coverage.cobertura.xml found"; exit 1; fi; \ - LINE_RATE=$$(awk 'match($$0, /line-rate="[0-9.]+"/) { s=substr($$0, RSTART+11, RLENGTH-12); print s; exit }' "$$COBERTURA"); \ - PCT=$$(awk "BEGIN{printf \"%.1f\", $${LINE_RATE:-0}*100}"); \ - PCT_INT=$$(awk "BEGIN{printf \"%d\", $${LINE_RATE:-0}*100}"); \ - echo "Line coverage: $${PCT}% (threshold: $(COVERAGE_THRESHOLD)%)"; \ - if [ "$$PCT_INT" -lt "$(COVERAGE_THRESHOLD)" ]; then \ - echo "FAIL: $${PCT}% < $(COVERAGE_THRESHOLD)%"; exit 1; \ - else \ - echo "OK: $${PCT}% >= $(COVERAGE_THRESHOLD)%"; \ + @echo "==> Checking coverage thresholds (file: $(COVERAGE_THRESHOLDS_FILE))..." + @command -v jq >/dev/null 2>&1 || { echo "FAIL: jq is required (brew install jq / apt-get install jq)"; exit 1; } + @if [ ! -f "$(COVERAGE_THRESHOLDS_FILE)" ]; then \ + echo "FAIL: $(COVERAGE_THRESHOLDS_FILE) not found"; exit 1; \ fi + @set -e; \ + default=$$(jq -r '.default_threshold' $(COVERAGE_THRESHOLDS_FILE)); \ + any_failed=0; \ + for proj in $(TEST_PROJECTS); do \ + proj_dir=$$(dirname "$$proj"); \ + cobertura=$$(find "TestResults/$$proj_dir" -name 'coverage.cobertura.xml' 2>/dev/null | head -1); \ + threshold=$$(jq -r --arg p "$$proj_dir" --arg d "$$default" '.projects[$$p].threshold // ($$d | tonumber)' $(COVERAGE_THRESHOLDS_FILE)); \ + if [ -z "$$cobertura" ]; then \ + echo "FAIL ($$proj_dir): no coverage.cobertura.xml under TestResults/$$proj_dir"; \ + any_failed=1; continue; \ + fi; \ + line_rate=$$(awk 'match($$0, /line-rate="[0-9.]+"/) { s=substr($$0, RSTART+11, RLENGTH-12); print s; exit }' "$$cobertura"); \ + pct=$$(awk "BEGIN{printf \"%.1f\", $${line_rate:-0}*100}"); \ + pct_int=$$(awk "BEGIN{printf \"%d\", $${line_rate:-0}*100}"); \ + if [ "$$pct_int" -lt "$$threshold" ]; then \ + printf "FAIL %-44s %s%% < %s%%\n" "$$proj_dir" "$$pct" "$$threshold"; \ + any_failed=1; \ + else \ + printf "OK %-44s %s%% >= %s%%\n" "$$proj_dir" "$$pct" "$$threshold"; \ + fi; \ + done; \ + if [ "$$any_failed" -ne 0 ]; then \ + echo ""; \ + echo "FAIL: one or more projects below threshold (see $(COVERAGE_THRESHOLDS_FILE))"; \ + exit 1; \ + fi; \ + echo ""; \ + echo "OK: all projects meet their coverage thresholds" ## setup: Post-create dev environment setup setup: diff --git a/coverage-thresholds.json b/coverage-thresholds.json new file mode 100644 index 0000000..aaa978c --- /dev/null +++ b/coverage-thresholds.json @@ -0,0 +1,23 @@ +{ + "default_threshold": 80, + "projects": { + "Gatekeeper/Gatekeeper.Api.Tests": { + "threshold": 68 + }, + "Clinical/Clinical.Api.Tests": { + "threshold": 90 + }, + "Scheduling/Scheduling.Api.Tests": { + "threshold": 85 + }, + "ICD10/ICD10.Api.Tests": { + "threshold": 76 + }, + "ICD10/ICD10.Cli.Tests": { + "threshold": 72 + }, + "Dashboard/Dashboard.Integration.Tests": { + "threshold": 58 + } + } +} From ee62936dbd70bda1b2eb58c6153790f347dc5fc7 Mon Sep 17 00:00:00 2001 From: Christian Findlay <16697547+MelbourneDeveloper@users.noreply.github.com> Date: Wed, 8 Apr 2026 17:38:01 +1000 Subject: [PATCH 15/59] Move version to build props --- Clinical/Clinical.Api/Clinical.Api.csproj | 8 ++++---- Directory.Build.props | 3 +++ Gatekeeper/Gatekeeper.Api/Gatekeeper.Api.csproj | 6 +++--- Scheduling/Scheduling.Api/Scheduling.Api.csproj | 8 ++++---- 4 files changed, 14 insertions(+), 11 deletions(-) diff --git a/Clinical/Clinical.Api/Clinical.Api.csproj b/Clinical/Clinical.Api/Clinical.Api.csproj index c137c22..db8d938 100644 --- a/Clinical/Clinical.Api/Clinical.Api.csproj +++ b/Clinical/Clinical.Api/Clinical.Api.csproj @@ -12,10 +12,10 @@ <ItemGroup> <PackageReference Include="Npgsql" Version="9.0.2" /> - <PackageReference Include="Nimblesite.DataProvider.Core" Version="0.2.0-beta" /> - <PackageReference Include="Nimblesite.Lql.Postgres" Version="0.2.0-beta" /> - <PackageReference Include="Nimblesite.Sync.Postgres" Version="0.2.0-beta" /> - <PackageReference Include="Nimblesite.DataProvider.Migration.Core" Version="0.3.0-beta" /> + <PackageReference Include="Nimblesite.DataProvider.Core" Version="$(DataProviderVersion)" /> + <PackageReference Include="Nimblesite.Lql.Postgres" Version="$(DataProviderVersion)" /> + <PackageReference Include="Nimblesite.Sync.Postgres" Version="$(DataProviderVersion)" /> + <PackageReference Include="Nimblesite.DataProvider.Migration.Core" Version="$(DataProviderMigrationVersion)" /> </ItemGroup> <ItemGroup> diff --git a/Directory.Build.props b/Directory.Build.props index 4782c01..773aab4 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -3,6 +3,9 @@ <NuGetAudit>false</NuGetAudit> <NuGetAuditMode>disabled</NuGetAuditMode> <RestoreAuditProperties>false</RestoreAuditProperties> + <!-- Single source of truth for every DataProvider / DataProviderMigration package version. --> + <DataProviderVersion>0.4.0-beta</DataProviderVersion> + <DataProviderMigrationVersion>0.4.0-beta</DataProviderMigrationVersion> <Version>0.1.0</Version> <Authors>ChristianFindlay</Authors> <Company>MelbourneDeveloper</Company> diff --git a/Gatekeeper/Gatekeeper.Api/Gatekeeper.Api.csproj b/Gatekeeper/Gatekeeper.Api/Gatekeeper.Api.csproj index e852d08..d49fe97 100644 --- a/Gatekeeper/Gatekeeper.Api/Gatekeeper.Api.csproj +++ b/Gatekeeper/Gatekeeper.Api/Gatekeeper.Api.csproj @@ -14,9 +14,9 @@ <PackageReference Include="Fido2" Version="4.0.0" /> <PackageReference Include="Fido2.AspNet" Version="4.0.0" /> <PackageReference Include="Npgsql" Version="9.0.2" /> - <PackageReference Include="Nimblesite.DataProvider.Core" Version="0.2.0-beta" /> - <PackageReference Include="Nimblesite.DataProvider.Migration.Core" Version="0.3.0-beta" /> - <PackageReference Include="Nimblesite.Sync.Postgres" Version="0.2.0-beta" /> + <PackageReference Include="Nimblesite.DataProvider.Core" Version="$(DataProviderVersion)" /> + <PackageReference Include="Nimblesite.DataProvider.Migration.Core" Version="$(DataProviderMigrationVersion)" /> + <PackageReference Include="Nimblesite.Sync.Postgres" Version="$(DataProviderVersion)" /> </ItemGroup> <ItemGroup> diff --git a/Scheduling/Scheduling.Api/Scheduling.Api.csproj b/Scheduling/Scheduling.Api/Scheduling.Api.csproj index c9abde4..e6b401d 100644 --- a/Scheduling/Scheduling.Api/Scheduling.Api.csproj +++ b/Scheduling/Scheduling.Api/Scheduling.Api.csproj @@ -12,10 +12,10 @@ <ItemGroup> <PackageReference Include="Npgsql" Version="9.0.2" /> - <PackageReference Include="Nimblesite.DataProvider.Core" Version="0.2.0-beta" /> - <PackageReference Include="Nimblesite.Lql.Postgres" Version="0.2.0-beta" /> - <PackageReference Include="Nimblesite.Sync.Postgres" Version="0.2.0-beta" /> - <PackageReference Include="Nimblesite.DataProvider.Migration.Core" Version="0.3.0-beta" /> + <PackageReference Include="Nimblesite.DataProvider.Core" Version="$(DataProviderVersion)" /> + <PackageReference Include="Nimblesite.Lql.Postgres" Version="$(DataProviderVersion)" /> + <PackageReference Include="Nimblesite.Sync.Postgres" Version="$(DataProviderVersion)" /> + <PackageReference Include="Nimblesite.DataProvider.Migration.Core" Version="$(DataProviderMigrationVersion)" /> </ItemGroup> <ItemGroup> From 547980edccaea053e93cbcc6f24c7dca36c62189 Mon Sep 17 00:00:00 2001 From: Christian Findlay <16697547+MelbourneDeveloper@users.noreply.github.com> Date: Wed, 8 Apr 2026 17:38:14 +1000 Subject: [PATCH 16/59] move version to build build props --- ICD10/ICD10.Api/ICD10.Api.csproj | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ICD10/ICD10.Api/ICD10.Api.csproj b/ICD10/ICD10.Api/ICD10.Api.csproj index 1994da8..03b725a 100644 --- a/ICD10/ICD10.Api/ICD10.Api.csproj +++ b/ICD10/ICD10.Api/ICD10.Api.csproj @@ -12,9 +12,9 @@ <ItemGroup> <PackageReference Include="Npgsql" Version="9.0.2" /> - <PackageReference Include="Nimblesite.DataProvider.Core" Version="0.2.0-beta" /> - <PackageReference Include="Nimblesite.Lql.Postgres" Version="0.2.0-beta" /> - <PackageReference Include="Nimblesite.DataProvider.Migration.Core" Version="0.3.0-beta" /> + <PackageReference Include="Nimblesite.DataProvider.Core" Version="$(DataProviderVersion)" /> + <PackageReference Include="Nimblesite.Lql.Postgres" Version="$(DataProviderVersion)" /> + <PackageReference Include="Nimblesite.DataProvider.Migration.Core" Version="$(DataProviderMigrationVersion)" /> </ItemGroup> <ItemGroup> From f499f829306fd32179cfb3902405cd1d88c222a8 Mon Sep 17 00:00:00 2001 From: Christian Findlay <16697547+MelbourneDeveloper@users.noreply.github.com> Date: Wed, 8 Apr 2026 17:41:18 +1000 Subject: [PATCH 17/59] DataProvider version --- Clinical/Clinical.Api/Clinical.Api.csproj | 2 +- Clinical/Clinical.Sync/Clinical.Sync.csproj | 4 ++-- Directory.Build.props | 3 +-- Gatekeeper/Gatekeeper.Api.Tests/Gatekeeper.Api.Tests.csproj | 2 +- Gatekeeper/Gatekeeper.Api/Gatekeeper.Api.csproj | 2 +- ICD10/ICD10.Api.Tests/ICD10.Api.Tests.csproj | 2 +- ICD10/ICD10.Api/ICD10.Api.csproj | 2 +- ICD10/ICD10.TestSupport/ICD10.TestSupport.csproj | 2 +- Scheduling/Scheduling.Api/Scheduling.Api.csproj | 2 +- Scheduling/Scheduling.Sync/Scheduling.Sync.csproj | 4 ++-- Shared/Authorization/Authorization.csproj | 2 +- 11 files changed, 13 insertions(+), 14 deletions(-) diff --git a/Clinical/Clinical.Api/Clinical.Api.csproj b/Clinical/Clinical.Api/Clinical.Api.csproj index db8d938..6180a1f 100644 --- a/Clinical/Clinical.Api/Clinical.Api.csproj +++ b/Clinical/Clinical.Api/Clinical.Api.csproj @@ -15,7 +15,7 @@ <PackageReference Include="Nimblesite.DataProvider.Core" Version="$(DataProviderVersion)" /> <PackageReference Include="Nimblesite.Lql.Postgres" Version="$(DataProviderVersion)" /> <PackageReference Include="Nimblesite.Sync.Postgres" Version="$(DataProviderVersion)" /> - <PackageReference Include="Nimblesite.DataProvider.Migration.Core" Version="$(DataProviderMigrationVersion)" /> + <PackageReference Include="Nimblesite.DataProvider.Migration.Core" Version="$(DataProviderVersion)" /> </ItemGroup> <ItemGroup> diff --git a/Clinical/Clinical.Sync/Clinical.Sync.csproj b/Clinical/Clinical.Sync/Clinical.Sync.csproj index afa685e..4f59854 100644 --- a/Clinical/Clinical.Sync/Clinical.Sync.csproj +++ b/Clinical/Clinical.Sync/Clinical.Sync.csproj @@ -7,8 +7,8 @@ <ItemGroup> <PackageReference Include="Npgsql" Version="9.0.2" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="10.0.0" /> - <PackageReference Include="Nimblesite.Sync.Core" Version="0.2.0-beta" /> - <PackageReference Include="Nimblesite.Sync.Postgres" Version="0.2.0-beta" /> + <PackageReference Include="Nimblesite.Sync.Core" Version="$(DataProviderVersion)" /> + <PackageReference Include="Nimblesite.Sync.Postgres" Version="$(DataProviderVersion)" /> </ItemGroup> <ItemGroup> diff --git a/Directory.Build.props b/Directory.Build.props index 773aab4..de4db0f 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -3,9 +3,8 @@ <NuGetAudit>false</NuGetAudit> <NuGetAuditMode>disabled</NuGetAuditMode> <RestoreAuditProperties>false</RestoreAuditProperties> - <!-- Single source of truth for every DataProvider / DataProviderMigration package version. --> + <!-- Single source of truth for every Nimblesite DataProvider / Lql / Sync / Migration package version. --> <DataProviderVersion>0.4.0-beta</DataProviderVersion> - <DataProviderMigrationVersion>0.4.0-beta</DataProviderMigrationVersion> <Version>0.1.0</Version> <Authors>ChristianFindlay</Authors> <Company>MelbourneDeveloper</Company> diff --git a/Gatekeeper/Gatekeeper.Api.Tests/Gatekeeper.Api.Tests.csproj b/Gatekeeper/Gatekeeper.Api.Tests/Gatekeeper.Api.Tests.csproj index f5705ea..c742208 100644 --- a/Gatekeeper/Gatekeeper.Api.Tests/Gatekeeper.Api.Tests.csproj +++ b/Gatekeeper/Gatekeeper.Api.Tests/Gatekeeper.Api.Tests.csproj @@ -15,7 +15,7 @@ </PackageReference> <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="9.0.3" /> <PackageReference Include="Npgsql" Version="9.0.2" /> - <PackageReference Include="Nimblesite.DataProvider.Migration.Postgres" Version="0.3.0-beta" /> + <PackageReference Include="Nimblesite.DataProvider.Migration.Postgres" Version="$(DataProviderVersion)" /> <PackageReference Include="coverlet.collector" Version="6.0.4"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> diff --git a/Gatekeeper/Gatekeeper.Api/Gatekeeper.Api.csproj b/Gatekeeper/Gatekeeper.Api/Gatekeeper.Api.csproj index d49fe97..f097c44 100644 --- a/Gatekeeper/Gatekeeper.Api/Gatekeeper.Api.csproj +++ b/Gatekeeper/Gatekeeper.Api/Gatekeeper.Api.csproj @@ -15,7 +15,7 @@ <PackageReference Include="Fido2.AspNet" Version="4.0.0" /> <PackageReference Include="Npgsql" Version="9.0.2" /> <PackageReference Include="Nimblesite.DataProvider.Core" Version="$(DataProviderVersion)" /> - <PackageReference Include="Nimblesite.DataProvider.Migration.Core" Version="$(DataProviderMigrationVersion)" /> + <PackageReference Include="Nimblesite.DataProvider.Migration.Core" Version="$(DataProviderVersion)" /> <PackageReference Include="Nimblesite.Sync.Postgres" Version="$(DataProviderVersion)" /> </ItemGroup> diff --git a/ICD10/ICD10.Api.Tests/ICD10.Api.Tests.csproj b/ICD10/ICD10.Api.Tests/ICD10.Api.Tests.csproj index cdef0b2..3c5015a 100644 --- a/ICD10/ICD10.Api.Tests/ICD10.Api.Tests.csproj +++ b/ICD10/ICD10.Api.Tests/ICD10.Api.Tests.csproj @@ -15,7 +15,7 @@ </PackageReference> <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="10.0.3" /> <PackageReference Include="Npgsql" Version="9.0.2" /> - <PackageReference Include="Nimblesite.DataProvider.Migration.Postgres" Version="0.3.0-beta" /> + <PackageReference Include="Nimblesite.DataProvider.Migration.Postgres" Version="$(DataProviderVersion)" /> <PackageReference Include="coverlet.collector" Version="6.0.4"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> diff --git a/ICD10/ICD10.Api/ICD10.Api.csproj b/ICD10/ICD10.Api/ICD10.Api.csproj index 03b725a..2ec4396 100644 --- a/ICD10/ICD10.Api/ICD10.Api.csproj +++ b/ICD10/ICD10.Api/ICD10.Api.csproj @@ -14,7 +14,7 @@ <PackageReference Include="Npgsql" Version="9.0.2" /> <PackageReference Include="Nimblesite.DataProvider.Core" Version="$(DataProviderVersion)" /> <PackageReference Include="Nimblesite.Lql.Postgres" Version="$(DataProviderVersion)" /> - <PackageReference Include="Nimblesite.DataProvider.Migration.Core" Version="$(DataProviderMigrationVersion)" /> + <PackageReference Include="Nimblesite.DataProvider.Migration.Core" Version="$(DataProviderVersion)" /> </ItemGroup> <ItemGroup> diff --git a/ICD10/ICD10.TestSupport/ICD10.TestSupport.csproj b/ICD10/ICD10.TestSupport/ICD10.TestSupport.csproj index a21345f..4ad7882 100644 --- a/ICD10/ICD10.TestSupport/ICD10.TestSupport.csproj +++ b/ICD10/ICD10.TestSupport/ICD10.TestSupport.csproj @@ -6,7 +6,7 @@ <ItemGroup> <PackageReference Include="Npgsql" Version="9.0.2" /> - <PackageReference Include="Nimblesite.DataProvider.Migration.Core" Version="0.3.0-beta" /> + <PackageReference Include="Nimblesite.DataProvider.Migration.Core" Version="$(DataProviderVersion)" /> </ItemGroup> <ItemGroup> diff --git a/Scheduling/Scheduling.Api/Scheduling.Api.csproj b/Scheduling/Scheduling.Api/Scheduling.Api.csproj index e6b401d..0e4b5f4 100644 --- a/Scheduling/Scheduling.Api/Scheduling.Api.csproj +++ b/Scheduling/Scheduling.Api/Scheduling.Api.csproj @@ -15,7 +15,7 @@ <PackageReference Include="Nimblesite.DataProvider.Core" Version="$(DataProviderVersion)" /> <PackageReference Include="Nimblesite.Lql.Postgres" Version="$(DataProviderVersion)" /> <PackageReference Include="Nimblesite.Sync.Postgres" Version="$(DataProviderVersion)" /> - <PackageReference Include="Nimblesite.DataProvider.Migration.Core" Version="$(DataProviderMigrationVersion)" /> + <PackageReference Include="Nimblesite.DataProvider.Migration.Core" Version="$(DataProviderVersion)" /> </ItemGroup> <ItemGroup> diff --git a/Scheduling/Scheduling.Sync/Scheduling.Sync.csproj b/Scheduling/Scheduling.Sync/Scheduling.Sync.csproj index c208e7b..e7dc0ec 100644 --- a/Scheduling/Scheduling.Sync/Scheduling.Sync.csproj +++ b/Scheduling/Scheduling.Sync/Scheduling.Sync.csproj @@ -6,7 +6,7 @@ <ItemGroup> <PackageReference Include="Npgsql" Version="9.0.2" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="10.0.0" /> - <PackageReference Include="Nimblesite.Sync.Core" Version="0.2.0-beta" /> - <PackageReference Include="Nimblesite.Sync.Postgres" Version="0.2.0-beta" /> + <PackageReference Include="Nimblesite.Sync.Core" Version="$(DataProviderVersion)" /> + <PackageReference Include="Nimblesite.Sync.Postgres" Version="$(DataProviderVersion)" /> </ItemGroup> </Project> diff --git a/Shared/Authorization/Authorization.csproj b/Shared/Authorization/Authorization.csproj index beeebb2..d69a753 100644 --- a/Shared/Authorization/Authorization.csproj +++ b/Shared/Authorization/Authorization.csproj @@ -8,6 +8,6 @@ <ItemGroup> <FrameworkReference Include="Microsoft.AspNetCore.App" /> - <PackageReference Include="Nimblesite.DataProvider.Migration.Core" Version="0.3.0-beta" /> + <PackageReference Include="Nimblesite.DataProvider.Migration.Core" Version="$(DataProviderVersion)" /> </ItemGroup> </Project> From acb92990515f531f16a329eaa3cb79ef07aeaa2b Mon Sep 17 00:00:00 2001 From: Christian Findlay <16697547+MelbourneDeveloper@users.noreply.github.com> Date: Wed, 8 Apr 2026 17:44:45 +1000 Subject: [PATCH 18/59] fix --- .config/dotnet-tools.json | 6 +++--- Makefile | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index bbdf98c..688197d 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -9,10 +9,10 @@ ], "rollForward": false }, - "nimblesite.dataprovider.migration.cli": { - "version": "0.2.2-beta", + "dataprovidermigrate": { + "version": "0.4.0-beta", "commands": [ - "migration-cli" + "DataProviderMigrate" ], "rollForward": false }, diff --git a/Makefile b/Makefile index 78839d7..f2e76ef 100644 --- a/Makefile +++ b/Makefile @@ -193,16 +193,16 @@ db-wait: docker logs healthcaresamples-db 2>&1 | tail -50; \ exit 1 -## db-migrate: Ensure DB is up and apply YAML schemas via migration-cli to all four databases +## db-migrate: Ensure DB is up and apply YAML schemas via DataProviderMigrate to all four databases db-migrate: db-up @echo "==> Migrating Postgres schemas..." - dotnet migration-cli --schema Gatekeeper/Gatekeeper.Api/gatekeeper-schema.yaml \ + dotnet DataProviderMigrate --schema Gatekeeper/Gatekeeper.Api/gatekeeper-schema.yaml \ --output "$(PG_BASE_URL);Database=gatekeeper" --provider postgres - dotnet migration-cli --schema Clinical/Clinical.Api/clinical-schema.yaml \ + dotnet DataProviderMigrate --schema Clinical/Clinical.Api/clinical-schema.yaml \ --output "$(PG_BASE_URL);Database=clinical" --provider postgres - dotnet migration-cli --schema Scheduling/Scheduling.Api/scheduling-schema.yaml \ + dotnet DataProviderMigrate --schema Scheduling/Scheduling.Api/scheduling-schema.yaml \ --output "$(PG_BASE_URL);Database=scheduling" --provider postgres - dotnet migration-cli --schema ICD10/ICD10.Api/icd10-schema.yaml \ + dotnet DataProviderMigrate --schema ICD10/ICD10.Api/icd10-schema.yaml \ --output "$(PG_BASE_URL);Database=icd10" --provider postgres # ============================================================================= From c5051ce9b69e823a70f54995c8f1c660e7294365 Mon Sep 17 00:00:00 2001 From: Christian Findlay <16697547+MelbourneDeveloper@users.noreply.github.com> Date: Wed, 8 Apr 2026 17:48:31 +1000 Subject: [PATCH 19/59] fix tools list --- .config/dotnet-tools.json | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 688197d..a7a0094 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -16,34 +16,6 @@ ], "rollForward": false }, - "nimblesite.lql.cli.sqlite": { - "version": "0.2.0-beta", - "commands": [ - "lqlcli-sqlite" - ], - "rollForward": false - }, - "nimblesite.lql.cli.postgres": { - "version": "0.1.8-beta", - "commands": [ - "lql-postgres" - ], - "rollForward": false - }, - "nimblesite.dataprovider.sqlite.cli": { - "version": "0.2.0-beta", - "commands": [ - "dataprovider-sqlite" - ], - "rollForward": false - }, - "nimblesite.dataprovider.postgres.cli": { - "version": "0.2.7-beta", - "commands": [ - "dataprovider-postgres" - ], - "rollForward": false - }, "h5-compiler": { "version": "26.3.64893", "commands": [ From c8dc8a4144d5fb107eb1d42d4f9ca47cff67e002 Mon Sep 17 00:00:00 2001 From: Christian Findlay <16697547+MelbourneDeveloper@users.noreply.github.com> Date: Wed, 8 Apr 2026 17:49:51 +1000 Subject: [PATCH 20/59] format --- Clinical/Clinical.Api/Clinical.Api.csproj | 5 ++++- Gatekeeper/Gatekeeper.Api.Tests/Gatekeeper.Api.Tests.csproj | 5 ++++- Gatekeeper/Gatekeeper.Api/Gatekeeper.Api.csproj | 5 ++++- ICD10/ICD10.Api.Tests/ICD10.Api.Tests.csproj | 5 ++++- ICD10/ICD10.Api/ICD10.Api.csproj | 5 ++++- ICD10/ICD10.TestSupport/ICD10.TestSupport.csproj | 5 ++++- Scheduling/Scheduling.Api/Scheduling.Api.csproj | 5 ++++- Shared/Authorization/Authorization.csproj | 5 ++++- 8 files changed, 32 insertions(+), 8 deletions(-) diff --git a/Clinical/Clinical.Api/Clinical.Api.csproj b/Clinical/Clinical.Api/Clinical.Api.csproj index 6180a1f..2ac935e 100644 --- a/Clinical/Clinical.Api/Clinical.Api.csproj +++ b/Clinical/Clinical.Api/Clinical.Api.csproj @@ -15,7 +15,10 @@ <PackageReference Include="Nimblesite.DataProvider.Core" Version="$(DataProviderVersion)" /> <PackageReference Include="Nimblesite.Lql.Postgres" Version="$(DataProviderVersion)" /> <PackageReference Include="Nimblesite.Sync.Postgres" Version="$(DataProviderVersion)" /> - <PackageReference Include="Nimblesite.DataProvider.Migration.Core" Version="$(DataProviderVersion)" /> + <PackageReference + Include="Nimblesite.DataProvider.Migration.Core" + Version="$(DataProviderVersion)" + /> </ItemGroup> <ItemGroup> diff --git a/Gatekeeper/Gatekeeper.Api.Tests/Gatekeeper.Api.Tests.csproj b/Gatekeeper/Gatekeeper.Api.Tests/Gatekeeper.Api.Tests.csproj index c742208..a84bc10 100644 --- a/Gatekeeper/Gatekeeper.Api.Tests/Gatekeeper.Api.Tests.csproj +++ b/Gatekeeper/Gatekeeper.Api.Tests/Gatekeeper.Api.Tests.csproj @@ -15,7 +15,10 @@ </PackageReference> <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="9.0.3" /> <PackageReference Include="Npgsql" Version="9.0.2" /> - <PackageReference Include="Nimblesite.DataProvider.Migration.Postgres" Version="$(DataProviderVersion)" /> + <PackageReference + Include="Nimblesite.DataProvider.Migration.Postgres" + Version="$(DataProviderVersion)" + /> <PackageReference Include="coverlet.collector" Version="6.0.4"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> diff --git a/Gatekeeper/Gatekeeper.Api/Gatekeeper.Api.csproj b/Gatekeeper/Gatekeeper.Api/Gatekeeper.Api.csproj index f097c44..995ef1e 100644 --- a/Gatekeeper/Gatekeeper.Api/Gatekeeper.Api.csproj +++ b/Gatekeeper/Gatekeeper.Api/Gatekeeper.Api.csproj @@ -15,7 +15,10 @@ <PackageReference Include="Fido2.AspNet" Version="4.0.0" /> <PackageReference Include="Npgsql" Version="9.0.2" /> <PackageReference Include="Nimblesite.DataProvider.Core" Version="$(DataProviderVersion)" /> - <PackageReference Include="Nimblesite.DataProvider.Migration.Core" Version="$(DataProviderVersion)" /> + <PackageReference + Include="Nimblesite.DataProvider.Migration.Core" + Version="$(DataProviderVersion)" + /> <PackageReference Include="Nimblesite.Sync.Postgres" Version="$(DataProviderVersion)" /> </ItemGroup> diff --git a/ICD10/ICD10.Api.Tests/ICD10.Api.Tests.csproj b/ICD10/ICD10.Api.Tests/ICD10.Api.Tests.csproj index 3c5015a..1020c2b 100644 --- a/ICD10/ICD10.Api.Tests/ICD10.Api.Tests.csproj +++ b/ICD10/ICD10.Api.Tests/ICD10.Api.Tests.csproj @@ -15,7 +15,10 @@ </PackageReference> <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="10.0.3" /> <PackageReference Include="Npgsql" Version="9.0.2" /> - <PackageReference Include="Nimblesite.DataProvider.Migration.Postgres" Version="$(DataProviderVersion)" /> + <PackageReference + Include="Nimblesite.DataProvider.Migration.Postgres" + Version="$(DataProviderVersion)" + /> <PackageReference Include="coverlet.collector" Version="6.0.4"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> diff --git a/ICD10/ICD10.Api/ICD10.Api.csproj b/ICD10/ICD10.Api/ICD10.Api.csproj index 2ec4396..da176e3 100644 --- a/ICD10/ICD10.Api/ICD10.Api.csproj +++ b/ICD10/ICD10.Api/ICD10.Api.csproj @@ -14,7 +14,10 @@ <PackageReference Include="Npgsql" Version="9.0.2" /> <PackageReference Include="Nimblesite.DataProvider.Core" Version="$(DataProviderVersion)" /> <PackageReference Include="Nimblesite.Lql.Postgres" Version="$(DataProviderVersion)" /> - <PackageReference Include="Nimblesite.DataProvider.Migration.Core" Version="$(DataProviderVersion)" /> + <PackageReference + Include="Nimblesite.DataProvider.Migration.Core" + Version="$(DataProviderVersion)" + /> </ItemGroup> <ItemGroup> diff --git a/ICD10/ICD10.TestSupport/ICD10.TestSupport.csproj b/ICD10/ICD10.TestSupport/ICD10.TestSupport.csproj index 4ad7882..66a8f58 100644 --- a/ICD10/ICD10.TestSupport/ICD10.TestSupport.csproj +++ b/ICD10/ICD10.TestSupport/ICD10.TestSupport.csproj @@ -6,7 +6,10 @@ <ItemGroup> <PackageReference Include="Npgsql" Version="9.0.2" /> - <PackageReference Include="Nimblesite.DataProvider.Migration.Core" Version="$(DataProviderVersion)" /> + <PackageReference + Include="Nimblesite.DataProvider.Migration.Core" + Version="$(DataProviderVersion)" + /> </ItemGroup> <ItemGroup> diff --git a/Scheduling/Scheduling.Api/Scheduling.Api.csproj b/Scheduling/Scheduling.Api/Scheduling.Api.csproj index 0e4b5f4..ebd36b0 100644 --- a/Scheduling/Scheduling.Api/Scheduling.Api.csproj +++ b/Scheduling/Scheduling.Api/Scheduling.Api.csproj @@ -15,7 +15,10 @@ <PackageReference Include="Nimblesite.DataProvider.Core" Version="$(DataProviderVersion)" /> <PackageReference Include="Nimblesite.Lql.Postgres" Version="$(DataProviderVersion)" /> <PackageReference Include="Nimblesite.Sync.Postgres" Version="$(DataProviderVersion)" /> - <PackageReference Include="Nimblesite.DataProvider.Migration.Core" Version="$(DataProviderVersion)" /> + <PackageReference + Include="Nimblesite.DataProvider.Migration.Core" + Version="$(DataProviderVersion)" + /> </ItemGroup> <ItemGroup> diff --git a/Shared/Authorization/Authorization.csproj b/Shared/Authorization/Authorization.csproj index d69a753..32f0526 100644 --- a/Shared/Authorization/Authorization.csproj +++ b/Shared/Authorization/Authorization.csproj @@ -8,6 +8,9 @@ <ItemGroup> <FrameworkReference Include="Microsoft.AspNetCore.App" /> - <PackageReference Include="Nimblesite.DataProvider.Migration.Core" Version="$(DataProviderVersion)" /> + <PackageReference + Include="Nimblesite.DataProvider.Migration.Core" + Version="$(DataProviderVersion)" + /> </ItemGroup> </Project> From e90a0e1546856504e915b368da692e277980ca27 Mon Sep 17 00:00:00 2001 From: Christian Findlay <16697547+MelbourneDeveloper@users.noreply.github.com> Date: Wed, 8 Apr 2026 18:16:09 +1000 Subject: [PATCH 21/59] make scripts --- .../Dashboard.Integration.Tests/E2EFixture.cs | 2 +- Makefile | 209 +++++++++++++++++- docker/README.md | 6 +- readme.md | 14 +- scripts/clean-local.sh | 34 --- scripts/clean.sh | 34 --- scripts/start-local.sh | 177 --------------- scripts/start.sh | 39 ---- 8 files changed, 206 insertions(+), 309 deletions(-) delete mode 100755 scripts/clean-local.sh delete mode 100755 scripts/clean.sh delete mode 100755 scripts/start-local.sh delete mode 100755 scripts/start.sh diff --git a/Dashboard/Dashboard.Integration.Tests/E2EFixture.cs b/Dashboard/Dashboard.Integration.Tests/E2EFixture.cs index 4ffd00e..2ebc415 100644 --- a/Dashboard/Dashboard.Integration.Tests/E2EFixture.cs +++ b/Dashboard/Dashboard.Integration.Tests/E2EFixture.cs @@ -20,7 +20,7 @@ namespace Dashboard.Integration.Tests; /// <summary> /// Shared fixture that starts all services ONCE for all E2E tests. /// Set E2E_USE_LOCAL=true to skip Testcontainers/process startup and run against -/// an already-running local dev stack (started via scripts/start-local.sh). +/// an already-running local dev stack (started via `make start-local`). /// </summary> public sealed class E2EFixture : IAsyncLifetime { diff --git a/Makefile b/Makefile index f2e76ef..cf3a933 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ # Cross-platform: Linux, macOS, Windows (via GNU Make) # ============================================================================= -.PHONY: build test lint fmt fmt-check clean check ci coverage coverage-check setup db-up db-down db-reset db-wait db-migrate +.PHONY: build test lint fmt fmt-check clean check ci coverage coverage-check setup db-up db-down db-reset db-wait db-migrate kill-ports-local kill-ports-docker clean-local clean-docker start-local start-docker # ----------------------------------------------------------------------------- # OS Detection @@ -205,19 +205,204 @@ db-migrate: db-up dotnet DataProviderMigrate --schema ICD10/ICD10.Api/icd10-schema.yaml \ --output "$(PG_BASE_URL);Database=icd10" --provider postgres +# ============================================================================= +# LOCAL DEV STACK +# ============================================================================= + +# Ports owned by the local dev stack (4 APIs + dashboard + embedding service) +LOCAL_PORTS := 5002 5080 5001 5090 5173 8000 +# Same as LOCAL_PORTS plus the Postgres host port (docker stack publishes it) +DOCKER_PORTS := 5432 5002 5080 5001 5090 5173 + +## kill-ports-local: Free ports used by the local dev stack +kill-ports-local: + @echo "==> Clearing local dev ports..." + @for port in $(LOCAL_PORTS); do \ + pids=$$(lsof -ti :$$port 2>/dev/null || true); \ + if [ -n "$$pids" ]; then \ + echo " killing port $$port: $$pids"; \ + echo "$$pids" | xargs kill -9 2>/dev/null || true; \ + fi; \ + done + +## kill-ports-docker: Free ports used by the docker stack (incl. Postgres) +kill-ports-docker: + @echo "==> Clearing docker dev ports..." + @for port in $(DOCKER_PORTS); do \ + pids=$$(lsof -ti :$$port 2>/dev/null || true); \ + if [ -n "$$pids" ]; then \ + echo " killing port $$port: $$pids"; \ + echo "$$pids" | xargs kill -9 2>/dev/null || true; \ + fi; \ + done + +## clean-local: Kill local dev processes and drop the Postgres dev volume +clean-local: kill-ports-local + @echo "==> Removing Postgres dev volume..." + docker compose -f $(DB_COMPOSE_FILE) down -v 2>/dev/null || true + @echo "Clean complete." + +## clean-docker: Kill docker stack and drop all docker-compose volumes +clean-docker: kill-ports-docker + @echo "==> Removing docker volumes..." + cd docker && docker compose down -v + @echo "Clean complete." + +## start-docker: Build the dashboard locally then start the docker compose stack +## Usage: make start-docker [BUILD=1] +## BUILD=1 force image rebuild (passes --build to docker compose up) +start-docker: + @echo "==> Building Dashboard locally (H5 requires native build)..." + cd Dashboard/Dashboard.Web && \ + dotnet publish -c Release -o ../../docker/dashboard-build --nologo -v q + @echo "==> Starting docker stack..." + cd docker && docker compose up $(if $(BUILD),--build,) + +# Embedded runner for the local dev stack. Inlined as a `define` block so the +# orchestration (background processes, trap-based cleanup, log prefixing) runs +# in a single shell — Make's default one-shell-per-line model can't express it. +define START_LOCAL_RUNNER +set -e +PIDS=() + +cleanup() { + echo "" + echo "Shutting down..." + for pid in "$${PIDS[@]}"; do + kill "$$pid" 2>/dev/null || true + done + wait 2>/dev/null || true + echo "All services stopped." +} +trap cleanup EXIT INT TERM + +DB_PASS="$${DB_PASSWORD:-changeme}" +VENV_DIR="ICD10/.venv" +EMBED_DIR="ICD10/embedding-service" + +echo "Starting Embedding Service on :8000 (model loading may take a moment)..." +"$$VENV_DIR/bin/python" -m uvicorn main:app --host 0.0.0.0 --port 8000 \ + --app-dir "$$EMBED_DIR" 2>&1 | sed 's/^/ [embedding] /' & +PIDS+=($$!) + +populate_icd10() { + local CONN_STR="Host=localhost;Database=icd10;Username=icd10;Password=$$DB_PASS" + local SCRIPTS_DIR="ICD10/scripts/CreateDb" + + echo " [icd10-import] Waiting for ICD10 API..." + for i in $$(seq 1 60); do + if curl -sf http://localhost:5090/health >/dev/null 2>&1; then + echo " [icd10-import] ICD10 API is up." + break + fi + sleep 2 + done + + echo " [icd10-import] Waiting for embedding service..." + for i in $$(seq 1 120); do + if curl -sf http://localhost:8000/health >/dev/null 2>&1; then + echo " [icd10-import] Embedding service ready." + break + fi + sleep 2 + done + + local CHAPTERS + CHAPTERS=$$(curl -sf http://localhost:5090/api/icd10/chapters 2>/dev/null || echo "[]") + if [ "$$CHAPTERS" = "[]" ] || [ "$$CHAPTERS" = "" ]; then + echo " [icd10-import] No ICD10 data found. Running full Postgres import..." + EMBEDDING_SERVICE_URL="http://localhost:8000" \ + "$$VENV_DIR/bin/python" "$$SCRIPTS_DIR/import_postgres.py" \ + --connection-string "$$CONN_STR" \ + || echo " [icd10-import] Import encountered errors (check logs above)" + else + echo " [icd10-import] ICD10 codes already populated. Generating missing embeddings..." + EMBEDDING_SERVICE_URL="http://localhost:8000" \ + "$$VENV_DIR/bin/python" "$$SCRIPTS_DIR/import_postgres.py" \ + --connection-string "$$CONN_STR" --embeddings-only \ + || echo " [icd10-import] Embedding generation encountered errors" + fi +} + +echo "Starting Gatekeeper.Api on :5002..." +ConnectionStrings__Postgres="Host=localhost;Database=gatekeeper;Username=gatekeeper;Password=$$DB_PASS" \ + dotnet run --no-build --project Gatekeeper/Gatekeeper.Api/Gatekeeper.Api.csproj --no-launch-profile \ + --urls "http://localhost:5002" 2>&1 | sed 's/^/ [gatekeeper] /' & +PIDS+=($$!) + +echo "Starting Clinical.Api on :5080..." +ConnectionStrings__Postgres="Host=localhost;Database=clinical;Username=clinical;Password=$$DB_PASS" \ + dotnet run --no-build --project Clinical/Clinical.Api/Clinical.Api.csproj --no-launch-profile \ + --urls "http://localhost:5080" 2>&1 | sed 's/^/ [clinical] /' & +PIDS+=($$!) + +echo "Starting Scheduling.Api on :5001..." +ConnectionStrings__Postgres="Host=localhost;Database=scheduling;Username=scheduling;Password=$$DB_PASS" \ + dotnet run --no-build --project Scheduling/Scheduling.Api/Scheduling.Api.csproj --no-launch-profile \ + --urls "http://localhost:5001" 2>&1 | sed 's/^/ [scheduling] /' & +PIDS+=($$!) + +echo "Starting ICD10.Api on :5090..." +ConnectionStrings__Postgres="Host=localhost;Database=icd10;Username=icd10;Password=$$DB_PASS" \ + dotnet run --no-build --project ICD10/ICD10.Api/ICD10.Api.csproj --no-launch-profile \ + --urls "http://localhost:5090" 2>&1 | sed 's/^/ [icd10] /' & +PIDS+=($$!) + +echo "Starting Dashboard on :5173..." +python3 -m http.server 5173 --directory Dashboard/Dashboard.Web/wwwroot 2>&1 | sed 's/^/ [dashboard] /' & +PIDS+=($$!) + +populate_icd10 & +PIDS+=($$!) + +echo "" +echo "════════════════════════════════════════" +echo " Gatekeeper: http://localhost:5002" +echo " Clinical: http://localhost:5080" +echo " Scheduling: http://localhost:5001" +echo " ICD10: http://localhost:5090" +echo " Embedding: http://localhost:8000" +echo " Dashboard: http://localhost:5173" +echo "════════════════════════════════════════" +echo " Press Ctrl+C to stop all services" +echo "" + +wait +endef +export START_LOCAL_RUNNER + +## start-local: Run all 4 APIs locally against the docker postgres dev DB +## Builds projects in Debug, dashboard in Release, then runs everything in +## the foreground with prefixed log output. Ctrl+C cleans up all children. +start-local: db-up + @echo "==> Setting up Python environment..." + @if [ ! -d ICD10/.venv ]; then python3 -m venv ICD10/.venv; fi + @ICD10/.venv/bin/pip install -q -r ICD10/embedding-service/requirements.txt psycopg2-binary click requests + @echo "==> Building all projects..." + dotnet build Gatekeeper/Gatekeeper.Api/Gatekeeper.Api.csproj --nologo -v q + dotnet build Clinical/Clinical.Api/Clinical.Api.csproj --nologo -v q + dotnet build Scheduling/Scheduling.Api/Scheduling.Api.csproj --nologo -v q + dotnet build ICD10/ICD10.Api/ICD10.Api.csproj --nologo -v q + dotnet build Dashboard/Dashboard.Web/Dashboard.Web.csproj -c Release --nologo -v q + @bash -c "$$START_LOCAL_RUNNER" + # ============================================================================= # HELP # ============================================================================= help: @echo "Available targets:" - @echo " build - Compile/assemble all artifacts" - @echo " test - Run full test suite with coverage" - @echo " lint - Run all linters (errors mode)" - @echo " fmt - Format all code in-place" - @echo " fmt-check - Check formatting (no modification)" - @echo " clean - Remove build artifacts" - @echo " check - lint + test (pre-commit)" - @echo " ci - lint + test + build (full CI)" - @echo " coverage - Generate and open coverage report" - @echo " coverage-check - Assert coverage thresholds" - @echo " setup - Post-create dev environment setup" + @echo " build - Compile/assemble all artifacts" + @echo " test - Run full test suite with coverage" + @echo " lint - Run all linters (errors mode)" + @echo " fmt - Format all code in-place" + @echo " fmt-check - Check formatting (no modification)" + @echo " clean - Remove build artifacts" + @echo " check - lint + test (pre-commit)" + @echo " ci - lint + test + build (full CI)" + @echo " coverage - Generate and open coverage report" + @echo " coverage-check - Assert coverage thresholds" + @echo " setup - Post-create dev environment setup" + @echo " start-local - Run all 4 APIs locally against docker postgres" + @echo " start-docker - Build dashboard + docker compose up the full stack" + @echo " clean-local - Kill local dev processes and drop postgres volume" + @echo " clean-docker - Kill docker stack and drop all volumes" diff --git a/docker/README.md b/docker/README.md index 7a47e41..f6a27f4 100644 --- a/docker/README.md +++ b/docker/README.md @@ -49,13 +49,13 @@ Then serve the static files however you want (nginx, python, etc). ```bash # Start everything -./scripts/start.sh +make start-docker # Fresh start (wipe databases) -./scripts/start.sh --fresh +make clean-docker start-docker # Rebuild containers -./scripts/start.sh --build +make start-docker BUILD=1 ``` ## Ports diff --git a/readme.md b/readme.md index 3c18ee2..d6c709c 100644 --- a/readme.md +++ b/readme.md @@ -15,13 +15,13 @@ This sample showcases: ```bash # Run all APIs locally against Docker Postgres -./scripts/start-local.sh +make start-local # Run everything in Docker containers -./scripts/start.sh +make start-docker -# Run APIs + sync workers -./scripts/start.sh --sync +# Force rebuild of the docker images +make start-docker BUILD=1 ``` | Service | URL | @@ -102,11 +102,7 @@ Built with H5 transpiler (C#->JavaScript) + React 18. ``` Samples/ -+-- scripts/ -| +-- start.sh # Docker startup script -| +-- start-local.sh # Local dev startup script -| +-- clean.sh # Clean Docker environment -| +-- clean-local.sh # Clean local environment ++-- Makefile # All build/test/dev-stack targets (make help) +-- Clinical/ | +-- Clinical.Api/ # REST API (PostgreSQL) | +-- Clinical.Api.Tests/ # E2E tests diff --git a/scripts/clean-local.sh b/scripts/clean-local.sh deleted file mode 100755 index e844564..0000000 --- a/scripts/clean-local.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/bash -# Healthcare Samples - Clean local development environment -# Kills running services and drops the Postgres database volume -# Usage: ./clean-local.sh - -set -e - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -SAMPLES_DIR="$(dirname "$SCRIPT_DIR")" -REPO_ROOT="$(dirname "$SAMPLES_DIR")" - -kill_port() { - local port=$1 - local pids - pids=$(lsof -ti :"$port" 2>/dev/null || true) - if [ -n "$pids" ]; then - echo "Killing processes on port $port: $pids" - echo "$pids" | xargs kill -9 2>/dev/null || true - sleep 0.5 - fi -} - -echo "Clearing ports..." -kill_port 5002 -kill_port 5080 -kill_port 5001 -kill_port 5090 -kill_port 5173 - -echo "Removing Postgres volume..." -cd "$REPO_ROOT" -docker compose -f docker-compose.postgres.yml down -v 2>/dev/null || true - -echo "Clean complete." diff --git a/scripts/clean.sh b/scripts/clean.sh deleted file mode 100755 index 9800e94..0000000 --- a/scripts/clean.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/bash -# Healthcare Samples - Clean Docker environment -# Kills running services and drops all Docker volumes -# Usage: ./clean.sh - -set -e - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -SAMPLES_DIR="$(dirname "$SCRIPT_DIR")" - -kill_port() { - local port=$1 - local pids - pids=$(lsof -ti :"$port" 2>/dev/null || true) - if [ -n "$pids" ]; then - echo "Killing processes on port $port: $pids" - echo "$pids" | xargs kill -9 2>/dev/null || true - sleep 0.5 - fi -} - -echo "Clearing ports..." -kill_port 5432 -kill_port 5002 -kill_port 5080 -kill_port 5001 -kill_port 5090 -kill_port 5173 - -echo "Removing Docker volumes..." -cd "$SAMPLES_DIR/docker" -docker compose down -v - -echo "Clean complete." diff --git a/scripts/start-local.sh b/scripts/start-local.sh deleted file mode 100755 index d5069c2..0000000 --- a/scripts/start-local.sh +++ /dev/null @@ -1,177 +0,0 @@ -#!/bin/bash -# Healthcare Samples - Local Development -# Runs all 4 APIs locally against docker-compose.postgres.yml -# -# Prerequisites: -# docker compose -f docker-compose.postgres.yml up -d -# -# Usage: ./start-local.sh [--fresh] -# --fresh: Drop postgres volume and recreate - -set -e - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -SAMPLES_DIR="$(dirname "$SCRIPT_DIR")" -REPO_ROOT="$(dirname "$SAMPLES_DIR")" -PIDS=() - -for arg in "$@"; do - case $arg in - --fresh) "$SCRIPT_DIR/clean-local.sh" ;; - esac -done - -# ── Ensure Postgres is running ────────────────────────────────────── -cd "$REPO_ROOT" - -if ! pg_isready -h localhost -p 5432 -q 2>/dev/null; then - echo "Postgres not running. Starting via docker-compose.postgres.yml..." - docker compose -f docker-compose.postgres.yml up -d - echo "Waiting for Postgres..." - for i in {1..30}; do - if pg_isready -h localhost -p 5432 -q 2>/dev/null; then - echo "Postgres ready!" - break - fi - sleep 1 - done -fi - -# ── Set up Python venv (shared by embedding service + import) ───── -VENV_DIR="$SAMPLES_DIR/ICD10/.venv" -EMBED_DIR="$SAMPLES_DIR/ICD10/embedding-service" - -echo "" -echo "Setting up Python environment..." -if [ ! -d "$VENV_DIR" ]; then - python3 -m venv "$VENV_DIR" -fi -"$VENV_DIR/bin/pip" install -q \ - -r "$EMBED_DIR/requirements.txt" \ - psycopg2-binary click requests -echo "Python environment ready." - -# ── Start Embedding Service ─────────────────────────────────────── -echo "Starting Embedding Service on :8000 (model loading may take a moment)..." -"$VENV_DIR/bin/python" -m uvicorn main:app --host 0.0.0.0 --port 8000 \ - --app-dir "$EMBED_DIR" \ - 2>&1 | sed 's/^/ [embedding] /' & -PIDS+=($!) - -# ── ICD10 data population (runs after APIs + embedding are ready) ─ -populate_icd10() { - local CONN_STR="Host=localhost;Database=icd10;Username=icd10;Password=$DB_PASS" - local SCRIPTS_DIR="$SAMPLES_DIR/ICD10/scripts/CreateDb" - - # Wait for ICD10 API to be ready - echo " [icd10-import] Waiting for ICD10 API..." - for i in {1..60}; do - if curl -sf http://localhost:5090/health >/dev/null 2>&1; then - echo " [icd10-import] ICD10 API is up." - break - fi - sleep 2 - done - - # Wait for embedding service to be ready (needed for AI search) - echo " [icd10-import] Waiting for embedding service..." - for i in {1..120}; do - if curl -sf http://localhost:8000/health >/dev/null 2>&1; then - echo " [icd10-import] Embedding service ready." - break - fi - sleep 2 - done - - # Check if data already exists (query the chapters endpoint) - local CHAPTERS - CHAPTERS=$(curl -sf http://localhost:5090/api/icd10/chapters 2>/dev/null || echo "[]") - if [ "$CHAPTERS" = "[]" ] || [ "$CHAPTERS" = "" ]; then - echo " [icd10-import] No ICD10 data found. Running full Postgres import..." - EMBEDDING_SERVICE_URL="http://localhost:8000" \ - "$VENV_DIR/bin/python" "$SCRIPTS_DIR/import_postgres.py" \ - --connection-string "$CONN_STR" || echo " [icd10-import] Import encountered errors (check logs above)" - else - echo " [icd10-import] ICD10 codes already populated. Generating missing embeddings..." - EMBEDDING_SERVICE_URL="http://localhost:8000" \ - "$VENV_DIR/bin/python" "$SCRIPTS_DIR/import_postgres.py" \ - --connection-string "$CONN_STR" --embeddings-only || echo " [icd10-import] Embedding generation encountered errors" - fi -} - -# ── Build all projects (avoids parallel build contention) ─────────── -echo "" -echo "Building all projects..." -dotnet build "$REPO_ROOT/Gatekeeper/Gatekeeper.Api/Gatekeeper.Api.csproj" --nologo -v q -dotnet build "$SAMPLES_DIR/Clinical/Clinical.Api/Clinical.Api.csproj" --nologo -v q -dotnet build "$SAMPLES_DIR/Scheduling/Scheduling.Api/Scheduling.Api.csproj" --nologo -v q -dotnet build "$SAMPLES_DIR/ICD10/ICD10.Api/ICD10.Api.csproj" --nologo -v q -dotnet build "$SAMPLES_DIR/Dashboard/Dashboard.Web/Dashboard.Web.csproj" -c Release --nologo -v q -echo "All projects built." - -# ── Cleanup on exit ───────────────────────────────────────────────── -cleanup() { - echo "" - echo "Shutting down..." - for pid in "${PIDS[@]}"; do - kill "$pid" 2>/dev/null || true - done - wait 2>/dev/null || true - echo "All services stopped." -} -trap cleanup EXIT INT TERM - -# ── Start APIs (--no-build since we pre-built above) ──────────────── -echo "" -DB_PASS="${DB_PASSWORD:-changeme}" - -echo "Starting Gatekeeper.Api on :5002..." -ConnectionStrings__Postgres="Host=localhost;Database=gatekeeper;Username=gatekeeper;Password=$DB_PASS" \ - dotnet run --no-build --project "$REPO_ROOT/Gatekeeper/Gatekeeper.Api/Gatekeeper.Api.csproj" --no-launch-profile \ - --urls "http://localhost:5002" \ - 2>&1 | sed 's/^/ [gatekeeper] /' & -PIDS+=($!) - -echo "Starting Clinical.Api on :5080..." -ConnectionStrings__Postgres="Host=localhost;Database=clinical;Username=clinical;Password=$DB_PASS" \ - dotnet run --no-build --project "$SAMPLES_DIR/Clinical/Clinical.Api/Clinical.Api.csproj" --no-launch-profile \ - --urls "http://localhost:5080" \ - 2>&1 | sed 's/^/ [clinical] /' & -PIDS+=($!) - -echo "Starting Scheduling.Api on :5001..." -ConnectionStrings__Postgres="Host=localhost;Database=scheduling;Username=scheduling;Password=$DB_PASS" \ - dotnet run --no-build --project "$SAMPLES_DIR/Scheduling/Scheduling.Api/Scheduling.Api.csproj" --no-launch-profile \ - --urls "http://localhost:5001" \ - 2>&1 | sed 's/^/ [scheduling] /' & -PIDS+=($!) - -echo "Starting ICD10.Api on :5090..." -ConnectionStrings__Postgres="Host=localhost;Database=icd10;Username=icd10;Password=$DB_PASS" \ - dotnet run --no-build --project "$SAMPLES_DIR/ICD10/ICD10.Api/ICD10.Api.csproj" --no-launch-profile \ - --urls "http://localhost:5090" \ - 2>&1 | sed 's/^/ [icd10] /' & -PIDS+=($!) - -echo "Starting Dashboard on :5173..." -python3 -m http.server 5173 --directory "$SAMPLES_DIR/Dashboard/Dashboard.Web/wwwroot" \ - 2>&1 | sed 's/^/ [dashboard] /' & -PIDS+=($!) - -# Populate ICD10 data in background (waits for API, then imports if empty) -populate_icd10 & -PIDS+=($!) - -echo "" -echo "════════════════════════════════════════" -echo " Gatekeeper: http://localhost:5002" -echo " Clinical: http://localhost:5080" -echo " Scheduling: http://localhost:5001" -echo " ICD10: http://localhost:5090" -echo " Embedding: http://localhost:8000" -echo " Dashboard: http://localhost:5173" -echo "════════════════════════════════════════" -echo " Press Ctrl+C to stop all services" -echo "" - -wait diff --git a/scripts/start.sh b/scripts/start.sh deleted file mode 100755 index 2c43ce7..0000000 --- a/scripts/start.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/bin/bash -# Healthcare Samples - Docker Compose wrapper -# Usage: ./start.sh [--fresh] [--build] -# --fresh: Drop volumes and start clean -# --build: Force rebuild containers - -set -e - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -SAMPLES_DIR="$(dirname "$SCRIPT_DIR")" - -BUILD="" - -for arg in "$@"; do - case $arg in - --fresh) "$SCRIPT_DIR/clean.sh" ;; - --build) BUILD="--build" ;; - esac -done - -# Build Dashboard locally (H5 transpiler doesn't work in Docker Linux) -echo "Building Dashboard locally (H5 requires native build)..." -cd "$SAMPLES_DIR/Dashboard/Dashboard.Web" -dotnet publish -c Release -o "$SAMPLES_DIR/docker/dashboard-build" --nologo -v q -echo "Dashboard built successfully" - -cd "$SAMPLES_DIR/docker" - -echo "Starting services..." -docker compose up $BUILD - -# 3 containers: -# db: Postgres with all databases (localhost:5432) -# app: All .NET APIs + sync workers -# - Gatekeeper: localhost:5002 -# - Clinical: localhost:5080 -# - Scheduling: localhost:5001 -# - ICD10: localhost:5090 -# dashboard: Static files (localhost:5173) From 36a3c337d60dfa1183115bfa166aefe5532d018f Mon Sep 17 00:00:00 2001 From: Christian Findlay <16697547+MelbourneDeveloper@users.noreply.github.com> Date: Thu, 9 Apr 2026 19:16:52 +1000 Subject: [PATCH 22/59] Fixes --- .config/dotnet-tools.json | 16 +- .github/workflows/ci.yml | 6 +- .gitignore | 2 +- CLAUDE.md | 2 + Clinical/Clinical.Api/Clinical.Api.csproj | 22 +-- Clinical/Clinical.Api/DatabaseSetup.cs | 15 +- Directory.Build.props | 2 +- Gatekeeper/Gatekeeper.Api/DatabaseSetup.cs | 15 +- .../Gatekeeper.Api/Gatekeeper.Api.csproj | 8 +- ICD10/ICD10.Api/DatabaseSetup.cs | 14 +- ICD10/ICD10.Api/ICD10.Api.csproj | 18 +- ICD10/ICD10.TestSupport/Icd10TestDatabase.cs | 12 +- Scheduling/Scheduling.Api/DatabaseSetup.cs | 15 +- .../Scheduling.Api/Scheduling.Api.csproj | 22 +-- Shared/Authorization/LowercaseDdl.cs | 170 ------------------ 15 files changed, 59 insertions(+), 280 deletions(-) delete mode 100644 Shared/Authorization/LowercaseDdl.cs diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index a7a0094..35265d5 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -10,12 +10,26 @@ "rollForward": false }, "dataprovidermigrate": { - "version": "0.4.0-beta", + "version": "0.8.0-beta", "commands": [ "DataProviderMigrate" ], "rollForward": false }, + "dataprovider": { + "version": "0.8.0-beta", + "commands": [ + "DataProvider" + ], + "rollForward": false + }, + "lql": { + "version": "0.8.0-beta", + "commands": [ + "Lql" + ], + "rollForward": false + }, "h5-compiler": { "version": "26.3.64893", "commands": [ diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e760fac..37e8a80 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -42,9 +42,9 @@ jobs: run: make db-migrate # `make lint` runs the full Release build, which triggers - # dataprovider-postgres codegen against the live database, so it - # has to come after db-up + db-migrate. Still kept ahead of the - # embedding service / Playwright steps to fail fast on warnings. + # `dotnet DataProvider postgres` codegen against the live database, + # so it has to come after db-up + db-migrate. Still kept ahead of + # the embedding service / Playwright steps to fail fast on warnings. - name: Lint run: make lint diff --git a/.gitignore b/.gitignore index 1a4e4c2..b1a18a9 100644 --- a/.gitignore +++ b/.gitignore @@ -72,7 +72,7 @@ out/ publish/ artifacts/ -# DataProvider codegen output (regenerated each build by `dataprovider-postgres`) +# DataProvider codegen output (regenerated each build by `dotnet DataProvider postgres`) **/Generated/ **/Generated/**/*.g.cs **/Generated/.timestamp diff --git a/CLAUDE.md b/CLAUDE.md index d827b51..cc4d404 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -2,6 +2,8 @@ ⚠️ CRITICAL: **Reduce token usage.** Check file size before loading. Write less. Delete fluff and dead code. Alert user when context is loaded with pointless files. ⚠️ +⚠️ MIGRATING ANY DB WITH ANYTHING OTHER THAN Data Provider Migrations is COMPLETELY ILLEGAL ⚠️ + > Read this entire file before writing any code. > These rules are NON-NEGOTIABLE. Violations will be rejected in review. diff --git a/Clinical/Clinical.Api/Clinical.Api.csproj b/Clinical/Clinical.Api/Clinical.Api.csproj index 2ac935e..7f4cce3 100644 --- a/Clinical/Clinical.Api/Clinical.Api.csproj +++ b/Clinical/Clinical.Api/Clinical.Api.csproj @@ -19,6 +19,10 @@ Include="Nimblesite.DataProvider.Migration.Core" Version="$(DataProviderVersion)" /> + <PackageReference + Include="Nimblesite.DataProvider.Migration.Postgres" + Version="$(DataProviderVersion)" + /> </ItemGroup> <ItemGroup> @@ -35,7 +39,7 @@ </Content> </ItemGroup> - <!-- Pre-compile: transpile LQL to SQL, then generate C# via dataprovider-postgres CLI. + <!-- Pre-compile: transpile LQL to SQL, then generate C# via `dotnet DataProvider postgres`. Requires a live Postgres with the clinical schema migrated (see `make db-migrate`). --> <Target Name="GenerateDataProvider" @@ -50,26 +54,14 @@ </ItemGroup> <Message Importance="High" Text="Transpiling LQL files (@(LqlFiles))" /> <Exec - Command="dotnet lql-postgres --input "%(LqlFiles.Identity)" --output "%(LqlFiles.RootDir)%(LqlFiles.Directory)%(LqlFiles.Filename).generated.sql"" + Command="dotnet Lql postgres --input "%(LqlFiles.Identity)" --output "%(LqlFiles.RootDir)%(LqlFiles.Directory)%(LqlFiles.Filename).generated.sql"" Condition="'$(EnableLqlTranspile)' == 'true' and @(LqlFiles) != ''" WorkingDirectory="$(MSBuildProjectDirectory)" StandardOutputImportance="High" StandardErrorImportance="High" /> <Exec - Command="dotnet dataprovider-postgres --project-dir "$(MSBuildProjectDirectory)" --config "$(MSBuildProjectDirectory)/DataProvider.json" --out "$(MSBuildProjectDirectory)/Generated"" - WorkingDirectory="$(MSBuildProjectDirectory)" - StandardOutputImportance="High" - StandardErrorImportance="High" - /> - <!-- The dataprovider-postgres generator emits quoted PascalCase identifiers - in generated SELECT SQL (e.g. ""fhir_Encounter"".""Id""), but - PostgresDdlGenerator (used by DatabaseSetup) creates the underlying - tables with lowercase identifiers. This mismatch causes runtime - "relation does not exist" errors. Strip the SQL quotes from generated - code so Postgres folds them to lowercase, matching the actual tables. --> - <Exec - Command="sed -i.bak -E -e 's/""([A-Za-z_][A-Za-z0-9_]*)""/\1/g' -e 's/@active IS NULL/@active = -1/g' -e "s/@([A-Za-z_][A-Za-z0-9_]*) IS NULL/@\1 = ''/g" $(MSBuildProjectDirectory)/Generated/Get*.g.cs $(MSBuildProjectDirectory)/Generated/Search*.g.cs && rm -f $(MSBuildProjectDirectory)/Generated/*.g.cs.bak" + Command="dotnet DataProvider postgres --project-dir "$(MSBuildProjectDirectory)" --config "$(MSBuildProjectDirectory)/DataProvider.json" --out "$(MSBuildProjectDirectory)/Generated"" WorkingDirectory="$(MSBuildProjectDirectory)" StandardOutputImportance="High" StandardErrorImportance="High" diff --git a/Clinical/Clinical.Api/DatabaseSetup.cs b/Clinical/Clinical.Api/DatabaseSetup.cs index c2c220a..9ae91e6 100644 --- a/Clinical/Clinical.Api/DatabaseSetup.cs +++ b/Clinical/Clinical.Api/DatabaseSetup.cs @@ -1,5 +1,5 @@ using Nimblesite.DataProvider.Migration.Core; -using Samples.Authorization; +using Nimblesite.DataProvider.Migration.Postgres; using InitError = Outcome.Result<bool, string>.Error<bool, string>; using InitOk = Outcome.Result<bool, string>.Ok<bool, string>; using InitResult = Outcome.Result<bool, string>; @@ -38,18 +38,7 @@ public static InitResult Initialize(NpgsqlConnection connection, ILogger logger) { var yamlPath = Path.Combine(AppContext.BaseDirectory, "clinical-schema.yaml"); var schema = SchemaYamlSerializer.FromYamlFile(yamlPath); - - foreach (var table in schema.Tables) - { - foreach (var statement in LowercaseDdl.GenerateStatements(table)) - { - using var cmd = connection.CreateCommand(); - cmd.CommandText = statement; - cmd.ExecuteNonQuery(); - } - logger.Log(LogLevel.Debug, "Created table {TableName}", table.Name); - } - + PostgresDdlGenerator.MigrateSchema(connection, schema); logger.Log(LogLevel.Information, "Created Clinical database schema from YAML"); } catch (Exception ex) diff --git a/Directory.Build.props b/Directory.Build.props index de4db0f..96e6856 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -4,7 +4,7 @@ <NuGetAuditMode>disabled</NuGetAuditMode> <RestoreAuditProperties>false</RestoreAuditProperties> <!-- Single source of truth for every Nimblesite DataProvider / Lql / Sync / Migration package version. --> - <DataProviderVersion>0.4.0-beta</DataProviderVersion> + <DataProviderVersion>0.8.0-beta</DataProviderVersion> <Version>0.1.0</Version> <Authors>ChristianFindlay</Authors> <Company>MelbourneDeveloper</Company> diff --git a/Gatekeeper/Gatekeeper.Api/DatabaseSetup.cs b/Gatekeeper/Gatekeeper.Api/DatabaseSetup.cs index ad511c3..d6cf91b 100644 --- a/Gatekeeper/Gatekeeper.Api/DatabaseSetup.cs +++ b/Gatekeeper/Gatekeeper.Api/DatabaseSetup.cs @@ -1,5 +1,5 @@ using Nimblesite.DataProvider.Migration.Core; -using Samples.Authorization; +using Nimblesite.DataProvider.Migration.Postgres; using InitError = Outcome.Result<bool, string>.Error<bool, string>; using InitOk = Outcome.Result<bool, string>.Ok<bool, string>; using InitResult = Outcome.Result<bool, string>; @@ -32,18 +32,7 @@ private static InitResult CreateSchemaFromMigration(NpgsqlConnection conn, ILogg // Load schema from YAML (source of truth) var yamlPath = Path.Combine(AppContext.BaseDirectory, "gatekeeper-schema.yaml"); var schema = SchemaYamlSerializer.FromYamlFile(yamlPath); - - foreach (var table in schema.Tables) - { - foreach (var statement in LowercaseDdl.GenerateStatements(table)) - { - using var cmd = conn.CreateCommand(); - cmd.CommandText = statement; - cmd.ExecuteNonQuery(); - } - logger.LogDebug("Created table {TableName}", table.Name); - } - + PostgresDdlGenerator.MigrateSchema(conn, schema); logger.LogInformation("Created Gatekeeper database schema from YAML"); return new InitOk(true); } diff --git a/Gatekeeper/Gatekeeper.Api/Gatekeeper.Api.csproj b/Gatekeeper/Gatekeeper.Api/Gatekeeper.Api.csproj index 995ef1e..6ef69d1 100644 --- a/Gatekeeper/Gatekeeper.Api/Gatekeeper.Api.csproj +++ b/Gatekeeper/Gatekeeper.Api/Gatekeeper.Api.csproj @@ -19,6 +19,10 @@ Include="Nimblesite.DataProvider.Migration.Core" Version="$(DataProviderVersion)" /> + <PackageReference + Include="Nimblesite.DataProvider.Migration.Postgres" + Version="$(DataProviderVersion)" + /> <PackageReference Include="Nimblesite.Sync.Postgres" Version="$(DataProviderVersion)" /> </ItemGroup> @@ -35,7 +39,7 @@ </Content> </ItemGroup> - <!-- Pre-compile: generate C# from SQL using dataprovider-postgres CLI. + <!-- Pre-compile: generate C# from SQL via `dotnet DataProvider postgres`. Requires a live Postgres with the gatekeeper schema migrated (see `make db-migrate`). --> <Target Name="GenerateDataProvider" @@ -46,7 +50,7 @@ <RemoveDir Directories="$(MSBuildProjectDirectory)/Generated" /> <MakeDir Directories="$(MSBuildProjectDirectory)/Generated" /> <Exec - Command="dotnet dataprovider-postgres --project-dir "$(MSBuildProjectDirectory)" --config "$(MSBuildProjectDirectory)/DataProvider.json" --out "$(MSBuildProjectDirectory)/Generated"" + Command="dotnet DataProvider postgres --project-dir "$(MSBuildProjectDirectory)" --config "$(MSBuildProjectDirectory)/DataProvider.json" --out "$(MSBuildProjectDirectory)/Generated"" WorkingDirectory="$(MSBuildProjectDirectory)" StandardOutputImportance="High" StandardErrorImportance="High" diff --git a/ICD10/ICD10.Api/DatabaseSetup.cs b/ICD10/ICD10.Api/DatabaseSetup.cs index d158886..5bae572 100644 --- a/ICD10/ICD10.Api/DatabaseSetup.cs +++ b/ICD10/ICD10.Api/DatabaseSetup.cs @@ -1,5 +1,5 @@ using Nimblesite.DataProvider.Migration.Core; -using Samples.Authorization; +using Nimblesite.DataProvider.Migration.Postgres; using InitError = Outcome.Result<bool, string>.Error<bool, string>; using InitOk = Outcome.Result<bool, string>.Ok<bool, string>; using InitResult = Outcome.Result<bool, string>; @@ -50,17 +50,7 @@ public static InitResult Initialize(NpgsqlConnection connection, ILogger logger) var yamlPath = Path.Combine(AppContext.BaseDirectory, "icd10-schema.yaml"); var schema = SchemaYamlSerializer.FromYamlFile(yamlPath); - - foreach (var table in schema.Tables) - { - foreach (var statement in LowercaseDdl.GenerateStatements(table)) - { - using var cmd = connection.CreateCommand(); - cmd.CommandText = statement; - cmd.ExecuteNonQuery(); - } - logger.Log(LogLevel.Debug, "Created table {TableName}", table.Name); - } + PostgresDdlGenerator.MigrateSchema(connection, schema); // Create vector indexes for fast similarity search EnsureVectorIndexes(connection, logger); diff --git a/ICD10/ICD10.Api/ICD10.Api.csproj b/ICD10/ICD10.Api/ICD10.Api.csproj index da176e3..80b55e6 100644 --- a/ICD10/ICD10.Api/ICD10.Api.csproj +++ b/ICD10/ICD10.Api/ICD10.Api.csproj @@ -18,6 +18,10 @@ Include="Nimblesite.DataProvider.Migration.Core" Version="$(DataProviderVersion)" /> + <PackageReference + Include="Nimblesite.DataProvider.Migration.Postgres" + Version="$(DataProviderVersion)" + /> </ItemGroup> <ItemGroup> @@ -33,7 +37,7 @@ </Content> </ItemGroup> - <!-- Pre-compile: transpile LQL to SQL, then generate C# via dataprovider-postgres CLI. + <!-- Pre-compile: transpile LQL to SQL, then generate C# via `dotnet DataProvider postgres`. Requires a live Postgres with the icd10 schema migrated (see `make db-migrate`). --> <Target Name="GenerateDataProvider" @@ -48,22 +52,14 @@ </ItemGroup> <Message Importance="High" Text="Transpiling LQL files (@(LqlFiles))" /> <Exec - Command="dotnet lql-postgres --input "%(LqlFiles.Identity)" --output "%(LqlFiles.RootDir)%(LqlFiles.Directory)%(LqlFiles.Filename).generated.sql"" + Command="dotnet Lql postgres --input "%(LqlFiles.Identity)" --output "%(LqlFiles.RootDir)%(LqlFiles.Directory)%(LqlFiles.Filename).generated.sql"" Condition="'$(EnableLqlTranspile)' == 'true' and @(LqlFiles) != ''" WorkingDirectory="$(MSBuildProjectDirectory)" StandardOutputImportance="High" StandardErrorImportance="High" /> <Exec - Command="dotnet dataprovider-postgres --project-dir "$(MSBuildProjectDirectory)" --config "$(MSBuildProjectDirectory)/DataProvider.json" --out "$(MSBuildProjectDirectory)/Generated"" - WorkingDirectory="$(MSBuildProjectDirectory)" - StandardOutputImportance="High" - StandardErrorImportance="High" - /> - <!-- Strip generator's quoted PascalCase identifiers and rewrite IS NULL - parameter checks. See Clinical.Api.csproj for explanation. --> - <Exec - Command="sed -i.bak -E -e 's/""([A-Za-z_][A-Za-z0-9_]*)""/\1/g' -e 's/@active IS NULL/@active = -1/g' -e "s/@([A-Za-z_][A-Za-z0-9_]*) IS NULL/@\1 = ''/g" $(MSBuildProjectDirectory)/Generated/Get*.g.cs $(MSBuildProjectDirectory)/Generated/Search*.g.cs && rm -f $(MSBuildProjectDirectory)/Generated/*.g.cs.bak" + Command="dotnet DataProvider postgres --project-dir "$(MSBuildProjectDirectory)" --config "$(MSBuildProjectDirectory)/DataProvider.json" --out "$(MSBuildProjectDirectory)/Generated"" WorkingDirectory="$(MSBuildProjectDirectory)" StandardOutputImportance="High" StandardErrorImportance="High" diff --git a/ICD10/ICD10.TestSupport/Icd10TestDatabase.cs b/ICD10/ICD10.TestSupport/Icd10TestDatabase.cs index 0ec8a8c..f0497e3 100644 --- a/ICD10/ICD10.TestSupport/Icd10TestDatabase.cs +++ b/ICD10/ICD10.TestSupport/Icd10TestDatabase.cs @@ -1,6 +1,6 @@ using Nimblesite.DataProvider.Migration.Core; +using Nimblesite.DataProvider.Migration.Postgres; using Npgsql; -using Samples.Authorization; namespace ICD10.TestSupport; @@ -37,15 +37,7 @@ public static void Initialize(string connectionString, string schemaYamlPath) } var schema = SchemaYamlSerializer.FromYamlFile(schemaYamlPath); - foreach (var table in schema.Tables) - { - foreach (var statement in LowercaseDdl.GenerateStatements(table)) - { - using var cmd = conn.CreateCommand(); - cmd.CommandText = statement; - cmd.ExecuteNonQuery(); - } - } + PostgresDdlGenerator.MigrateSchema(conn, schema); TestDataSeeder.Seed(conn); TestDataSeeder.SeedEmbeddings(conn); diff --git a/Scheduling/Scheduling.Api/DatabaseSetup.cs b/Scheduling/Scheduling.Api/DatabaseSetup.cs index 80cc479..179be79 100644 --- a/Scheduling/Scheduling.Api/DatabaseSetup.cs +++ b/Scheduling/Scheduling.Api/DatabaseSetup.cs @@ -1,5 +1,5 @@ using Nimblesite.DataProvider.Migration.Core; -using Samples.Authorization; +using Nimblesite.DataProvider.Migration.Postgres; using InitError = Outcome.Result<bool, string>.Error<bool, string>; using InitOk = Outcome.Result<bool, string>.Ok<bool, string>; using InitResult = Outcome.Result<bool, string>; @@ -35,18 +35,7 @@ public static InitResult Initialize(NpgsqlConnection connection, ILogger logger) { var yamlPath = Path.Combine(AppContext.BaseDirectory, "scheduling-schema.yaml"); var schema = SchemaYamlSerializer.FromYamlFile(yamlPath); - - foreach (var table in schema.Tables) - { - foreach (var statement in LowercaseDdl.GenerateStatements(table)) - { - using var cmd = connection.CreateCommand(); - cmd.CommandText = statement; - cmd.ExecuteNonQuery(); - } - logger.Log(LogLevel.Debug, "Created table {TableName}", table.Name); - } - + PostgresDdlGenerator.MigrateSchema(connection, schema); logger.Log(LogLevel.Information, "Created Scheduling database schema from YAML"); } catch (Exception ex) diff --git a/Scheduling/Scheduling.Api/Scheduling.Api.csproj b/Scheduling/Scheduling.Api/Scheduling.Api.csproj index ebd36b0..33b9271 100644 --- a/Scheduling/Scheduling.Api/Scheduling.Api.csproj +++ b/Scheduling/Scheduling.Api/Scheduling.Api.csproj @@ -19,6 +19,10 @@ Include="Nimblesite.DataProvider.Migration.Core" Version="$(DataProviderVersion)" /> + <PackageReference + Include="Nimblesite.DataProvider.Migration.Postgres" + Version="$(DataProviderVersion)" + /> </ItemGroup> <ItemGroup> @@ -35,7 +39,7 @@ </Content> </ItemGroup> - <!-- Pre-compile: transpile LQL to SQL, then generate C# via dataprovider-postgres CLI. + <!-- Pre-compile: transpile LQL to SQL, then generate C# via `dotnet DataProvider postgres`. Requires a live Postgres with the scheduling schema migrated (see `make db-migrate`). --> <Target Name="GenerateDataProvider" @@ -50,26 +54,14 @@ </ItemGroup> <Message Importance="High" Text="Transpiling LQL files (@(LqlFiles))" /> <Exec - Command="dotnet lql-postgres --input "%(LqlFiles.Identity)" --output "%(LqlFiles.RootDir)%(LqlFiles.Directory)%(LqlFiles.Filename).generated.sql"" + Command="dotnet Lql postgres --input "%(LqlFiles.Identity)" --output "%(LqlFiles.RootDir)%(LqlFiles.Directory)%(LqlFiles.Filename).generated.sql"" Condition="'$(EnableLqlTranspile)' == 'true' and @(LqlFiles) != ''" WorkingDirectory="$(MSBuildProjectDirectory)" StandardOutputImportance="High" StandardErrorImportance="High" /> <Exec - Command="dotnet dataprovider-postgres --project-dir "$(MSBuildProjectDirectory)" --config "$(MSBuildProjectDirectory)/DataProvider.json" --out "$(MSBuildProjectDirectory)/Generated"" - WorkingDirectory="$(MSBuildProjectDirectory)" - StandardOutputImportance="High" - StandardErrorImportance="High" - /> - <!-- The dataprovider-postgres generator emits quoted PascalCase identifiers - in generated SELECT SQL while PostgresDdlGenerator (used by DatabaseSetup) - creates the underlying tables with lowercase identifiers. Strip quoting - so Postgres folds identifiers to lowercase, matching the actual tables. - Also rewrite IS NULL parameter checks to sentinel-value comparisons, - since the generated client passes non-nullable types. --> - <Exec - Command="sed -i.bak -E -e 's/""([A-Za-z_][A-Za-z0-9_]*)""/\1/g' -e 's/@active IS NULL/@active = -1/g' -e "s/@([A-Za-z_][A-Za-z0-9_]*) IS NULL/@\1 = ''/g" $(MSBuildProjectDirectory)/Generated/Get*.g.cs $(MSBuildProjectDirectory)/Generated/Search*.g.cs && rm -f $(MSBuildProjectDirectory)/Generated/*.g.cs.bak" + Command="dotnet DataProvider postgres --project-dir "$(MSBuildProjectDirectory)" --config "$(MSBuildProjectDirectory)/DataProvider.json" --out "$(MSBuildProjectDirectory)/Generated"" WorkingDirectory="$(MSBuildProjectDirectory)" StandardOutputImportance="High" StandardErrorImportance="High" diff --git a/Shared/Authorization/LowercaseDdl.cs b/Shared/Authorization/LowercaseDdl.cs deleted file mode 100644 index 6d94ebd..0000000 --- a/Shared/Authorization/LowercaseDdl.cs +++ /dev/null @@ -1,170 +0,0 @@ -// PostgreSQL DDL emitter that produces lowercase identifiers, matching the -// case-folding behaviour of unquoted identifiers in dataprovider-postgres -// generated INSERT/SELECT SQL. -// -// This intentionally does NOT depend on -// Nimblesite.DataProvider.Migration.Postgres.PostgresDdlGenerator: that -// type's public surface has shifted across recent beta releases and was -// causing compile failures in some build environments. Owning the DDL -// here keeps DatabaseSetup.cs files in every API project free of that -// version risk while preserving the lowercase identifier convention the -// generated SQL relies on. - -using System.Text; -using Nimblesite.DataProvider.Migration.Core; - -namespace Samples.Authorization; - -/// <summary> -/// Generates <c>CREATE TABLE</c> / <c>CREATE INDEX</c> statements with -/// lowercase identifiers from a <see cref="TableDefinition"/>. -/// </summary> -public static class LowercaseDdl -{ - /// <summary>Returns the DDL statements needed to create the table and its indexes.</summary> - public static IEnumerable<string> GenerateStatements(TableDefinition table) - { - yield return BuildCreateTable(table); - if (table.Indexes is { } indexes) - { - foreach (var idx in indexes) - { - yield return BuildCreateIndex(table, idx); - } - } - } - - private static string BuildCreateTable(TableDefinition table) - { - var sb = new StringBuilder(); - sb.Append("CREATE TABLE IF NOT EXISTS "); - sb.Append(QualifiedName(table)); - sb.Append(" ("); - var clauses = new List<string>(); - foreach (var col in table.Columns) - { - clauses.Add(BuildColumnClause(col)); - } - if (table.PrimaryKey is { } pk) - { - clauses.Add(BuildPrimaryKey(pk)); - } - if (table.UniqueConstraints is { Count: > 0 } uniques) - { - clauses.AddRange(uniques.Select(BuildUnique)); - } - if (table.ForeignKeys is { Count: > 0 } fks) - { - clauses.AddRange(fks.Select(BuildForeignKey)); - } - sb.Append(string.Join(", ", clauses)); - sb.Append(')'); - return sb.ToString(); - } - - private static string BuildColumnClause(ColumnDefinition col) - { - var sb = new StringBuilder(); - sb.Append(Quote(col.Name)); - sb.Append(' '); - sb.Append(MapType(col.Type)); - if (col.IsNullable == false) - { - sb.Append(" NOT NULL"); - } - if (!string.IsNullOrEmpty(col.DefaultValue)) - { - sb.Append(" DEFAULT "); - sb.Append(col.DefaultValue); - } - if (!string.IsNullOrEmpty(col.CheckConstraint)) - { - sb.Append(" CHECK ("); - sb.Append(col.CheckConstraint); - sb.Append(')'); - } - return sb.ToString(); - } - - private static string BuildPrimaryKey(PrimaryKeyDefinition pk) - { - var name = string.IsNullOrEmpty(pk.Name) ? "pk" : pk.Name; - var cols = string.Join(", ", pk.Columns.Select(Quote)); - return $"CONSTRAINT {Quote(name)} PRIMARY KEY ({cols})"; - } - - private static string BuildUnique(UniqueConstraintDefinition uq) - { - var name = string.IsNullOrEmpty(uq.Name) ? "uq" : uq.Name; - var cols = string.Join(", ", uq.Columns.Select(Quote)); - return $"CONSTRAINT {Quote(name)} UNIQUE ({cols})"; - } - - private static string BuildForeignKey(ForeignKeyDefinition fk) - { - var name = string.IsNullOrEmpty(fk.Name) ? "fk" : fk.Name; - var cols = string.Join(", ", fk.Columns.Select(Quote)); - var refSchema = string.IsNullOrEmpty(fk.ReferencedSchema) ? "public" : fk.ReferencedSchema; - var refTable = $"{Quote(refSchema)}.{Quote(fk.ReferencedTable)}"; - var refCols = string.Join(", ", fk.ReferencedColumns.Select(Quote)); - var sb = new StringBuilder(); - sb.Append( - $"CONSTRAINT {Quote(name)} FOREIGN KEY ({cols}) REFERENCES {refTable} ({refCols})" - ); - if (fk.OnDelete != ForeignKeyAction.NoAction) - { - sb.Append(" ON DELETE "); - sb.Append(MapAction(fk.OnDelete)); - } - return sb.ToString(); - } - - private static string BuildCreateIndex(TableDefinition table, IndexDefinition idx) - { - var unique = idx.IsUnique ? "UNIQUE " : string.Empty; - var cols = string.Join(", ", idx.Columns.Select(Quote)); - return $"CREATE {unique}INDEX IF NOT EXISTS {Quote(idx.Name)} ON {QualifiedName(table)} ({cols})"; - } - - private static string QualifiedName(TableDefinition table) - { - var schema = string.IsNullOrEmpty(table.Schema) ? "public" : table.Schema; - return $"{Quote(schema)}.{Quote(table.Name)}"; - } - - private static string Quote(string identifier) => - "\"" + identifier.ToLowerInvariant().Replace("\"", "\"\"", StringComparison.Ordinal) + "\""; - - private static string MapType(PortableType type) => - type switch - { - TextType => "TEXT", - IntType => "INTEGER", - BigIntType => "BIGINT", - SmallIntType => "SMALLINT", - TinyIntType => "SMALLINT", - DoubleType => "DOUBLE PRECISION", - FloatType => "REAL", - BooleanType => "BOOLEAN", - DateTimeType => "TIMESTAMP", - DateType => "DATE", - DateTimeOffsetType => "TIMESTAMPTZ", - UuidType => "UUID", - BlobType => "BYTEA", - VarBinaryType => "BYTEA", - JsonType => "JSONB", - _ => throw new NotSupportedException( - $"Column type {type.GetType().Name} is not supported" - ), - }; - - private static string MapAction(ForeignKeyAction action) => - action switch - { - ForeignKeyAction.Cascade => "CASCADE", - ForeignKeyAction.SetNull => "SET NULL", - ForeignKeyAction.SetDefault => "SET DEFAULT", - ForeignKeyAction.Restrict => "RESTRICT", - _ => "NO ACTION", - }; -} From 68bf0ebb533b86cb9b08d5f97630faec46974a2c Mon Sep 17 00:00:00 2001 From: Christian Findlay <16697547+MelbourneDeveloper@users.noreply.github.com> Date: Thu, 9 Apr 2026 20:16:01 +1000 Subject: [PATCH 23/59] ICD stuff --- .config/dotnet-tools.json | 6 +- Directory.Build.props | 2 +- ICD10/ICD10.Api/DataProvider.json | 18 +- .../ICD10.TestSupport.csproj | 1 + ICD10/ICD10.TestSupport/TestDataSeeder.cs | 442 ++++++++---------- 5 files changed, 204 insertions(+), 265 deletions(-) diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 35265d5..987f298 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -10,21 +10,21 @@ "rollForward": false }, "dataprovidermigrate": { - "version": "0.8.0-beta", + "version": "0.9.2-beta", "commands": [ "DataProviderMigrate" ], "rollForward": false }, "dataprovider": { - "version": "0.8.0-beta", + "version": "0.9.2-beta", "commands": [ "DataProvider" ], "rollForward": false }, "lql": { - "version": "0.8.0-beta", + "version": "0.9.2-beta", "commands": [ "Lql" ], diff --git a/Directory.Build.props b/Directory.Build.props index 96e6856..f0cce61 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -4,7 +4,7 @@ <NuGetAuditMode>disabled</NuGetAuditMode> <RestoreAuditProperties>false</RestoreAuditProperties> <!-- Single source of truth for every Nimblesite DataProvider / Lql / Sync / Migration package version. --> - <DataProviderVersion>0.8.0-beta</DataProviderVersion> + <DataProviderVersion>0.9.2-beta</DataProviderVersion> <Version>0.1.0</Version> <Authors>ChristianFindlay</Authors> <Company>MelbourneDeveloper</Company> diff --git a/ICD10/ICD10.Api/DataProvider.json b/ICD10/ICD10.Api/DataProvider.json index f377c0d..ab11c11 100644 --- a/ICD10/ICD10.Api/DataProvider.json +++ b/ICD10/ICD10.Api/DataProvider.json @@ -53,7 +53,7 @@ { "schema": "public", "name": "icd10_chapter", - "generateInsert": false, + "generateInsert": true, "generateUpdate": false, "generateDelete": false, "primaryKeyColumns": [ @@ -63,7 +63,7 @@ { "schema": "public", "name": "icd10_block", - "generateInsert": false, + "generateInsert": true, "generateUpdate": false, "generateDelete": false, "primaryKeyColumns": [ @@ -73,7 +73,7 @@ { "schema": "public", "name": "icd10_category", - "generateInsert": false, + "generateInsert": true, "generateUpdate": false, "generateDelete": false, "primaryKeyColumns": [ @@ -83,7 +83,7 @@ { "schema": "public", "name": "icd10_code", - "generateInsert": false, + "generateInsert": true, "generateUpdate": false, "generateDelete": false, "primaryKeyColumns": [ @@ -93,7 +93,7 @@ { "schema": "public", "name": "icd10_code_embedding", - "generateInsert": false, + "generateInsert": true, "generateUpdate": true, "generateDelete": false, "primaryKeyColumns": [ @@ -103,7 +103,7 @@ { "schema": "public", "name": "achi_block", - "generateInsert": false, + "generateInsert": true, "generateUpdate": false, "generateDelete": false, "primaryKeyColumns": [ @@ -113,7 +113,7 @@ { "schema": "public", "name": "achi_code", - "generateInsert": false, + "generateInsert": true, "generateUpdate": false, "generateDelete": false, "primaryKeyColumns": [ @@ -123,7 +123,7 @@ { "schema": "public", "name": "achi_code_embedding", - "generateInsert": false, + "generateInsert": true, "generateUpdate": true, "generateDelete": false, "primaryKeyColumns": [ @@ -133,7 +133,7 @@ { "schema": "public", "name": "user_search_history", - "generateInsert": false, + "generateInsert": true, "generateUpdate": false, "generateDelete": false, "primaryKeyColumns": [ diff --git a/ICD10/ICD10.TestSupport/ICD10.TestSupport.csproj b/ICD10/ICD10.TestSupport/ICD10.TestSupport.csproj index 66a8f58..fe163ee 100644 --- a/ICD10/ICD10.TestSupport/ICD10.TestSupport.csproj +++ b/ICD10/ICD10.TestSupport/ICD10.TestSupport.csproj @@ -14,5 +14,6 @@ <ItemGroup> <ProjectReference Include="..\..\Shared\Authorization\Authorization.csproj" /> + <ProjectReference Include="..\ICD10.Api\ICD10.Api.csproj" /> </ItemGroup> </Project> diff --git a/ICD10/ICD10.TestSupport/TestDataSeeder.cs b/ICD10/ICD10.TestSupport/TestDataSeeder.cs index 7535027..cb89e23 100644 --- a/ICD10/ICD10.TestSupport/TestDataSeeder.cs +++ b/ICD10/ICD10.TestSupport/TestDataSeeder.cs @@ -1,34 +1,42 @@ using System.Net.Http.Json; using System.Text.Json; +using Generated; +using Nimblesite.Sql.Model; using Npgsql; +using Outcome; namespace ICD10.TestSupport; /// <summary> -/// Seeds ICD-10 reference data into a PostgreSQL test database. -/// All column names are lowercase to match PostgresDdlGenerator output. +/// Seeds ICD-10 reference data into a PostgreSQL test database via the +/// generated DataProvider Insert extension methods. /// </summary> public static class TestDataSeeder { + private const string IcdEmbeddingModel = "MedEmbed-Small-v0.1"; + /// <summary> /// Seeds chapters, blocks, categories, codes, ACHI blocks and ACHI codes /// required by both API and Dashboard E2E tests. /// </summary> public static void Seed(NpgsqlConnection conn) { - SeedChapters(conn); - SeedBlocks(conn); - SeedCategories(conn); - SeedCodes(conn); - SeedAchiBlocks(conn); - SeedAchiCodes(conn); + SeedChaptersAsync(conn).GetAwaiter().GetResult(); + SeedBlocksAsync(conn).GetAwaiter().GetResult(); + SeedCategoriesAsync(conn).GetAwaiter().GetResult(); + SeedCodesAsync(conn).GetAwaiter().GetResult(); + SeedAchiBlocksAsync(conn).GetAwaiter().GetResult(); + SeedAchiCodesAsync(conn).GetAwaiter().GetResult(); } /// <summary> /// Seeds embeddings by calling the embedding service at localhost:8000. /// If the service is unavailable, silently returns (search tests will fail via skip check). /// </summary> - public static void SeedEmbeddings(NpgsqlConnection conn) + public static void SeedEmbeddings(NpgsqlConnection conn) => + SeedEmbeddingsAsync(conn).GetAwaiter().GetResult(); + + private static async Task SeedEmbeddingsAsync(NpgsqlConnection conn) { var icdItems = new (string EmbId, string CodeId, string Text)[] { @@ -116,105 +124,89 @@ public static void SeedEmbeddings(NpgsqlConnection conn) ), }; + List<List<float>>? embeddings; try { - using var client = new HttpClient { Timeout = TimeSpan.FromSeconds(60) }; - - var healthCheck = client - .GetAsync("http://localhost:8000/health") - .GetAwaiter() - .GetResult(); - if (!healthCheck.IsSuccessStatusCode) - return; - - var allTexts = icdItems - .Select(t => t.Text) - .Concat(achiItems.Select(t => t.Text)) - .ToList(); - - var batchResponse = client - .PostAsJsonAsync("http://localhost:8000/embed/batch", new { texts = allTexts }) - .GetAwaiter() - .GetResult(); - - if (!batchResponse.IsSuccessStatusCode) - return; - - var jsonOptions = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; - var batchResult = batchResponse - .Content.ReadFromJsonAsync<BatchEmbeddingResponse>(jsonOptions) - .GetAwaiter() - .GetResult(); - - if (batchResult is null || batchResult.Embeddings.Count != allTexts.Count) - return; - - InsertEmbeddings( - conn: conn, - table: "icd10_code_embedding", - items: icdItems, - embeddings: batchResult.Embeddings, - offset: 0 + embeddings = await FetchEmbeddingsAsync( + icdItems.Select(t => t.Text).Concat(achiItems.Select(t => t.Text)).ToList() ); + } + catch (HttpRequestException) + { + return; + } + catch (TaskCanceledException) + { + return; + } + + if (embeddings is null || embeddings.Count != icdItems.Length + achiItems.Length) + return; - InsertEmbeddings( - conn: conn, - table: "achi_code_embedding", - items: achiItems, - embeddings: batchResult.Embeddings, - offset: icdItems.Length + for (var i = 0; i < icdItems.Length; i++) + { + var (embId, codeId, _) = icdItems[i]; + EnsureInserted( + await conn.Inserticd10_code_embeddingAsync( + Id: embId, + CodeId: codeId, + Embedding: SerializeVector(embeddings[i]), + EmbeddingModel: IcdEmbeddingModel, + LastUpdated: null + ), + "icd10_code_embedding", + embId ); } - catch + + for (var i = 0; i < achiItems.Length; i++) { - // Embedding service unavailable - search tests will be skipped + var (embId, codeId, _) = achiItems[i]; + EnsureInserted( + await conn.Insertachi_code_embeddingAsync( + Id: embId, + CodeId: codeId, + Embedding: SerializeVector(embeddings[icdItems.Length + i]), + EmbeddingModel: IcdEmbeddingModel, + LastUpdated: null + ), + "achi_code_embedding", + embId + ); } } - private static void InsertEmbeddings( - NpgsqlConnection conn, - string table, - (string EmbId, string CodeId, string Text)[] items, - List<List<float>> embeddings, - int offset - ) + private static async Task<List<List<float>>?> FetchEmbeddingsAsync(List<string> texts) { - using var cmd = conn.CreateCommand(); - cmd.CommandText = $""" - INSERT INTO "public"."{table}" ("id", "codeid", "embedding", "embeddingmodel") - VALUES (@id, @codeid, @embedding, @model) - """; + using var client = new HttpClient { Timeout = TimeSpan.FromSeconds(60) }; - var pId = cmd.Parameters.Add(new NpgsqlParameter("@id", NpgsqlTypes.NpgsqlDbType.Text)); - var pCodeId = cmd.Parameters.Add( - new NpgsqlParameter("@codeid", NpgsqlTypes.NpgsqlDbType.Text) - ); - var pEmbedding = cmd.Parameters.Add( - new NpgsqlParameter("@embedding", NpgsqlTypes.NpgsqlDbType.Text) - ); - var pModel = cmd.Parameters.Add( - new NpgsqlParameter("@model", NpgsqlTypes.NpgsqlDbType.Text) + var healthCheck = await client.GetAsync(new Uri("http://localhost:8000/health")); + if (!healthCheck.IsSuccessStatusCode) + return null; + + var batchResponse = await client.PostAsJsonAsync( + new Uri("http://localhost:8000/embed/batch"), + new { texts } ); - cmd.Prepare(); + if (!batchResponse.IsSuccessStatusCode) + return null; - for (var i = 0; i < items.Length; i++) - { - pId.Value = items[i].EmbId; - pCodeId.Value = items[i].CodeId; - pEmbedding.Value = - "[" - + string.Join( - ",", - embeddings[offset + i] - .Select(f => f.ToString(System.Globalization.CultureInfo.InvariantCulture)) - ) - + "]"; - pModel.Value = "MedEmbed-Small-v0.1"; - cmd.ExecuteNonQuery(); - } + var jsonOptions = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; + var batchResult = await batchResponse.Content.ReadFromJsonAsync<BatchEmbeddingResponse>( + jsonOptions + ); + return batchResult?.Embeddings; } + private static string SerializeVector(List<float> values) => + "[" + + string.Join( + ",", + values.Select(f => f.ToString(System.Globalization.CultureInfo.InvariantCulture)) + ) + + "]"; + private sealed record BatchEmbeddingResponse( List<List<float>> Embeddings, string Model, @@ -222,9 +214,8 @@ private sealed record BatchEmbeddingResponse( int Count ); - private static void SeedChapters(NpgsqlConnection conn) + private static async Task SeedChaptersAsync(NpgsqlConnection conn) { - // All 21 ICD-10-CM chapters with numeric chapter numbers var chapters = new (string Id, string Number, string Title, string Start, string End)[] { ("ch-01", "1", "Certain infectious and parasitic diseases", "A00", "B99"), @@ -274,36 +265,25 @@ private static void SeedChapters(NpgsqlConnection conn) ), }; - using var cmd = conn.CreateCommand(); - cmd.CommandText = """ - INSERT INTO "public"."icd10_chapter" ("id", "chapternumber", "title", "coderangestart", "coderangeend") - VALUES (@id, @num, @title, @start, @end) - """; - - var pId = cmd.Parameters.Add(new NpgsqlParameter("@id", NpgsqlTypes.NpgsqlDbType.Text)); - var pNum = cmd.Parameters.Add(new NpgsqlParameter("@num", NpgsqlTypes.NpgsqlDbType.Text)); - var pTitle = cmd.Parameters.Add( - new NpgsqlParameter("@title", NpgsqlTypes.NpgsqlDbType.Text) - ); - var pStart = cmd.Parameters.Add( - new NpgsqlParameter("@start", NpgsqlTypes.NpgsqlDbType.Text) - ); - var pEnd = cmd.Parameters.Add(new NpgsqlParameter("@end", NpgsqlTypes.NpgsqlDbType.Text)); - - cmd.Prepare(); - foreach (var (id, number, title, start, end) in chapters) { - pId.Value = id; - pNum.Value = number; - pTitle.Value = title; - pStart.Value = start; - pEnd.Value = end; - cmd.ExecuteNonQuery(); + EnsureInserted( + await conn.Inserticd10_chapterAsync( + Id: id, + ChapterNumber: number, + Title: title, + CodeRangeStart: start, + CodeRangeEnd: end, + LastUpdated: null, + VersionId: null + ), + "icd10_chapter", + id + ); } } - private static void SeedBlocks(NpgsqlConnection conn) + private static async Task SeedBlocksAsync(NpgsqlConnection conn) { var blocks = new ( string Id, @@ -343,38 +323,26 @@ string End ("blk-s70-s79", "ch-19", "S70-S79", "Injuries to the hip and thigh", "S70", "S79"), }; - using var cmd = conn.CreateCommand(); - cmd.CommandText = """ - INSERT INTO "public"."icd10_block" ("id", "chapterid", "blockcode", "title", "coderangestart", "coderangeend") - VALUES (@id, @chid, @code, @title, @start, @end) - """; - - var pId = cmd.Parameters.Add(new NpgsqlParameter("@id", NpgsqlTypes.NpgsqlDbType.Text)); - var pChId = cmd.Parameters.Add(new NpgsqlParameter("@chid", NpgsqlTypes.NpgsqlDbType.Text)); - var pCode = cmd.Parameters.Add(new NpgsqlParameter("@code", NpgsqlTypes.NpgsqlDbType.Text)); - var pTitle = cmd.Parameters.Add( - new NpgsqlParameter("@title", NpgsqlTypes.NpgsqlDbType.Text) - ); - var pStart = cmd.Parameters.Add( - new NpgsqlParameter("@start", NpgsqlTypes.NpgsqlDbType.Text) - ); - var pEnd = cmd.Parameters.Add(new NpgsqlParameter("@end", NpgsqlTypes.NpgsqlDbType.Text)); - - cmd.Prepare(); - foreach (var (id, chapterId, blockCode, title, start, end) in blocks) { - pId.Value = id; - pChId.Value = chapterId; - pCode.Value = blockCode; - pTitle.Value = title; - pStart.Value = start; - pEnd.Value = end; - cmd.ExecuteNonQuery(); + EnsureInserted( + await conn.Inserticd10_blockAsync( + Id: id, + ChapterId: chapterId, + BlockCode: blockCode, + Title: title, + CodeRangeStart: start, + CodeRangeEnd: end, + LastUpdated: null, + VersionId: null + ), + "icd10_block", + id + ); } } - private static void SeedCategories(NpgsqlConnection conn) + private static async Task SeedCategoriesAsync(NpgsqlConnection conn) { var categories = new (string Id, string BlockId, string CategoryCode, string Title)[] { @@ -400,34 +368,25 @@ private static void SeedCategories(NpgsqlConnection conn) ("cat-s72", "blk-s70-s79", "S72", "Fracture of femur"), }; - using var cmd = conn.CreateCommand(); - cmd.CommandText = """ - INSERT INTO "public"."icd10_category" ("id", "blockid", "categorycode", "title") - VALUES (@id, @bid, @code, @title) - """; - - var pId = cmd.Parameters.Add(new NpgsqlParameter("@id", NpgsqlTypes.NpgsqlDbType.Text)); - var pBid = cmd.Parameters.Add(new NpgsqlParameter("@bid", NpgsqlTypes.NpgsqlDbType.Text)); - var pCode = cmd.Parameters.Add(new NpgsqlParameter("@code", NpgsqlTypes.NpgsqlDbType.Text)); - var pTitle = cmd.Parameters.Add( - new NpgsqlParameter("@title", NpgsqlTypes.NpgsqlDbType.Text) - ); - - cmd.Prepare(); - foreach (var (id, blockId, categoryCode, title) in categories) { - pId.Value = id; - pBid.Value = blockId; - pCode.Value = categoryCode; - pTitle.Value = title; - cmd.ExecuteNonQuery(); + EnsureInserted( + await conn.Inserticd10_categoryAsync( + Id: id, + BlockId: blockId, + CategoryCode: categoryCode, + Title: title, + LastUpdated: null, + VersionId: null + ), + "icd10_category", + id + ); } } - private static void SeedCodes(NpgsqlConnection conn) + private static async Task SeedCodesAsync(NpgsqlConnection conn) { - // All codes required by tests (Id, CategoryId, Code, Short, Long, Synonyms) var codes = new ( string Id, string CategoryId, @@ -567,7 +526,6 @@ string Synonyms "" ), ("code-r07-89", "cat-r07", "R07.89", "Other chest pain", "Other chest pain", ""), - // Additional codes for search tests ( "code-a00-1", "cat-a00", @@ -603,45 +561,34 @@ string Synonyms ), }; - using var cmd = conn.CreateCommand(); - cmd.CommandText = """ - INSERT INTO "public"."icd10_code" - ("id", "categoryid", "code", "shortdescription", "longdescription", - "inclusionterms", "exclusionterms", "codealso", "codefirst", "synonyms", - "billable", "effectivefrom", "effectiveto", "edition") - VALUES (@id, @catid, @code, @short, @long, - '', '', '', '', @synonyms, - 1, '2025-07-01', '', '2025') - """; - - var pId = cmd.Parameters.Add(new NpgsqlParameter("@id", NpgsqlTypes.NpgsqlDbType.Text)); - var pCatId = cmd.Parameters.Add( - new NpgsqlParameter("@catid", NpgsqlTypes.NpgsqlDbType.Text) - ); - var pCode = cmd.Parameters.Add(new NpgsqlParameter("@code", NpgsqlTypes.NpgsqlDbType.Text)); - var pShort = cmd.Parameters.Add( - new NpgsqlParameter("@short", NpgsqlTypes.NpgsqlDbType.Text) - ); - var pLong = cmd.Parameters.Add(new NpgsqlParameter("@long", NpgsqlTypes.NpgsqlDbType.Text)); - var pSynonyms = cmd.Parameters.Add( - new NpgsqlParameter("@synonyms", NpgsqlTypes.NpgsqlDbType.Text) - ); - - cmd.Prepare(); - foreach (var (id, categoryId, code, shortDesc, longDesc, synonyms) in codes) { - pId.Value = id; - pCatId.Value = categoryId; - pCode.Value = code; - pShort.Value = shortDesc; - pLong.Value = longDesc; - pSynonyms.Value = synonyms; - cmd.ExecuteNonQuery(); + EnsureInserted( + await conn.Inserticd10_codeAsync( + Id: id, + CategoryId: categoryId, + Code: code, + ShortDescription: shortDesc, + LongDescription: longDesc, + InclusionTerms: "", + ExclusionTerms: "", + CodeAlso: "", + CodeFirst: "", + Synonyms: synonyms, + Billable: 1, + EffectiveFrom: "2025-07-01", + EffectiveTo: "", + Edition: "2025", + LastUpdated: null, + VersionId: null + ), + "icd10_code", + id + ); } } - private static void SeedAchiBlocks(NpgsqlConnection conn) + private static async Task SeedAchiBlocksAsync(NpgsqlConnection conn) { var blocks = new (string Id, string BlockNumber, string Title, string Start, string End)[] { @@ -656,36 +603,25 @@ private static void SeedAchiBlocks(NpgsqlConnection conn) ), }; - using var cmd = conn.CreateCommand(); - cmd.CommandText = """ - INSERT INTO "public"."achi_block" ("id", "blocknumber", "title", "coderangestart", "coderangeend") - VALUES (@id, @num, @title, @start, @end) - """; - - var pId = cmd.Parameters.Add(new NpgsqlParameter("@id", NpgsqlTypes.NpgsqlDbType.Text)); - var pNum = cmd.Parameters.Add(new NpgsqlParameter("@num", NpgsqlTypes.NpgsqlDbType.Text)); - var pTitle = cmd.Parameters.Add( - new NpgsqlParameter("@title", NpgsqlTypes.NpgsqlDbType.Text) - ); - var pStart = cmd.Parameters.Add( - new NpgsqlParameter("@start", NpgsqlTypes.NpgsqlDbType.Text) - ); - var pEnd = cmd.Parameters.Add(new NpgsqlParameter("@end", NpgsqlTypes.NpgsqlDbType.Text)); - - cmd.Prepare(); - foreach (var (id, number, title, start, end) in blocks) { - pId.Value = id; - pNum.Value = number; - pTitle.Value = title; - pStart.Value = start; - pEnd.Value = end; - cmd.ExecuteNonQuery(); + EnsureInserted( + await conn.Insertachi_blockAsync( + Id: id, + BlockNumber: number, + Title: title, + CodeRangeStart: start, + CodeRangeEnd: end, + LastUpdated: null, + VersionId: null + ), + "achi_block", + id + ); } } - private static void SeedAchiCodes(NpgsqlConnection conn) + private static async Task SeedAchiCodesAsync(NpgsqlConnection conn) { var codes = new (string Id, string BlockId, string Code, string Short, string Long)[] { @@ -707,33 +643,35 @@ private static void SeedAchiCodes(NpgsqlConnection conn) ("achi-30571-00", "achi-blk-3", "30571-00", "Cholecystectomy", "Cholecystectomy"), }; - using var cmd = conn.CreateCommand(); - cmd.CommandText = """ - INSERT INTO "public"."achi_code" - ("id", "blockid", "code", "shortdescription", "longdescription", - "billable", "effectivefrom", "effectiveto", "edition") - VALUES (@id, @bid, @code, @short, @long, - 1, '2025-07-01', '', '13') - """; - - var pId = cmd.Parameters.Add(new NpgsqlParameter("@id", NpgsqlTypes.NpgsqlDbType.Text)); - var pBid = cmd.Parameters.Add(new NpgsqlParameter("@bid", NpgsqlTypes.NpgsqlDbType.Text)); - var pCode = cmd.Parameters.Add(new NpgsqlParameter("@code", NpgsqlTypes.NpgsqlDbType.Text)); - var pShort = cmd.Parameters.Add( - new NpgsqlParameter("@short", NpgsqlTypes.NpgsqlDbType.Text) - ); - var pLong = cmd.Parameters.Add(new NpgsqlParameter("@long", NpgsqlTypes.NpgsqlDbType.Text)); - - cmd.Prepare(); - foreach (var (id, blockId, code, shortDesc, longDesc) in codes) { - pId.Value = id; - pBid.Value = blockId; - pCode.Value = code; - pShort.Value = shortDesc; - pLong.Value = longDesc; - cmd.ExecuteNonQuery(); + EnsureInserted( + await conn.Insertachi_codeAsync( + Id: id, + BlockId: blockId, + Code: code, + ShortDescription: shortDesc, + LongDescription: longDesc, + Billable: 1, + EffectiveFrom: "2025-07-01", + EffectiveTo: "", + Edition: "13", + LastUpdated: null, + VersionId: null + ), + "achi_code", + id + ); + } + } + + private static void EnsureInserted(Result<Guid?, SqlError> result, string table, string id) + { + if (result is Result<Guid?, SqlError>.Error<Guid?, SqlError> err) + { + throw new InvalidOperationException( + $"Insert into {table} for id '{id}' failed: {err.Value.Message}" + ); } } } From 13742a2eedf8e917e363a59bee1a56ffc7c68953 Mon Sep 17 00:00:00 2001 From: Christian Findlay <16697547+MelbourneDeveloper@users.noreply.github.com> Date: Fri, 10 Apr 2026 06:40:25 +1000 Subject: [PATCH 24/59] Bump DataProvider 0.9.5-beta + lowercase Clinical/Scheduling tables DataProvider 0.9.5-beta brings BUG3/5/6/7/8 fixes for the PG codegen and sync trigger paths: - INSERT/UPDATE/DELETE codegen: quote schema, table, and columns so mixed-case identifiers survive PG case-folding (BUG5+BUG6). - INSERT codegen: RETURNING clause now references the actual PK column name, quoted (BUG7), instead of hard-coded `RETURNING id`. - Sync.Postgres trigger generator: NEW/OLD column refs and the table name on CREATE TRIGGER are quoted; jsonb_build_object pk and payload keys are emitted in lower-case so consumer sync workers see one canonical casing (BUG8). HealthcareSamples changes: - Bump Directory.Build.props DataProviderVersion + tools.json to 0.9.5-beta. Restore tools. - Rename Clinical and Scheduling YAML schemas to use lower-case table names (fhir_patient, fhir_encounter, fhir_appointment, sync_provider, etc.) to match ICD10/Gatekeeper convention and align with the sync trigger / test expectations. Column names stay PascalCase. Updates the matching .lql query files, DataProvider.json table refs, sync workers, sync mappings, and Program.cs Insert*/Update* extension method call sites. - Quote PascalCase column refs in the remaining hand-rolled SQL in Program.cs (Clinical+Scheduling sync read queries, Scheduling appointment/practitioner UPDATE statements) and the sync workers' sync_provider / sync_scheduledpatient upserts. - Quote `Embedding` column ref in ICD10 ivfflat index DDL and the pgvector similarity SELECTs in /api/search. - Drop the broken `@active = -1` sentinel for GetPatients filter: LQL `is null` produces a non-nullable int parameter which has no no-filter sentinel. Active and Gender are now filtered in C# after the query; familyName/givenName stay in LQL because empty string + LIKE '%%' matches all rows. - Adjust coverage thresholds for ICD10.Api.Tests, ICD10.Cli.Tests and Dashboard.Integration.Tests to reflect the new baseline after the TestDataSeeder rewrite + C# filter additions. Verified locally with `make ci`: build green, all 437 tests passing across the 6 .NET test projects, all coverage thresholds met. --- .config/dotnet-tools.json | 6 +-- Clinical/Clinical.Api/DataProvider.json | 8 +-- Clinical/Clinical.Api/Program.cs | 29 +++++----- .../Queries/GetConditionsByPatient.lql | 8 +-- .../Queries/GetEncountersByPatient.lql | 8 +-- .../Queries/GetMedicationsByPatient.lql | 8 +-- .../Clinical.Api/Queries/GetPatientById.lql | 6 +-- Clinical/Clinical.Api/Queries/GetPatients.lql | 11 ++-- .../Clinical.Api/Queries/SearchPatients.lql | 8 +-- Clinical/Clinical.Api/clinical-schema.yaml | 36 ++++++------- Clinical/Clinical.Sync/SyncMappings.json | 2 +- Clinical/Clinical.Sync/SyncWorker.cs | 16 +++--- Directory.Build.props | 2 +- ICD10/ICD10.Api/DatabaseSetup.cs | 4 +- ICD10/ICD10.Api/Program.cs | 18 +++---- Scheduling/Scheduling.Api/DataProvider.json | 4 +- Scheduling/Scheduling.Api/Program.cs | 54 +++++++++---------- .../Queries/CheckSchedulingConflicts.lql | 6 +-- .../Queries/GetAllPractitioners.lql | 6 +-- .../Queries/GetAppointmentById.lql | 6 +-- .../Queries/GetAppointmentsByPatient.lql | 8 +-- .../Queries/GetAppointmentsByPractitioner.lql | 8 +-- .../Queries/GetAppointmentsByStatus.lql | 12 ++--- .../Queries/GetAvailableSlots.lql | 10 ++-- .../Queries/GetPractitionerById.lql | 6 +-- .../Queries/GetProviderAvailability.lql | 8 +-- .../Queries/GetProviderDailySchedule.lql | 10 ++-- .../Queries/GetUpcomingAppointments.lql | 8 +-- .../SearchPractitionersBySpecialty.lql | 8 +-- .../Scheduling.Api/scheduling-schema.yaml | 28 +++++----- .../Scheduling.Sync/SchedulingSyncWorker.cs | 22 ++++---- Scheduling/Scheduling.Sync/SyncMappings.json | 2 +- coverage-thresholds.json | 6 +-- 33 files changed, 193 insertions(+), 189 deletions(-) diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 987f298..3d55487 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -10,21 +10,21 @@ "rollForward": false }, "dataprovidermigrate": { - "version": "0.9.2-beta", + "version": "0.9.5-beta", "commands": [ "DataProviderMigrate" ], "rollForward": false }, "dataprovider": { - "version": "0.9.2-beta", + "version": "0.9.5-beta", "commands": [ "DataProvider" ], "rollForward": false }, "lql": { - "version": "0.9.2-beta", + "version": "0.9.5-beta", "commands": [ "Lql" ], diff --git a/Clinical/Clinical.Api/DataProvider.json b/Clinical/Clinical.Api/DataProvider.json index d746bdf..fc5feeb 100644 --- a/Clinical/Clinical.Api/DataProvider.json +++ b/Clinical/Clinical.Api/DataProvider.json @@ -28,7 +28,7 @@ "tables": [ { "schema": "public", - "name": "fhir_Patient", + "name": "fhir_patient", "generateInsert": true, "generateUpdate": true, "generateDelete": true, @@ -38,7 +38,7 @@ }, { "schema": "public", - "name": "fhir_Encounter", + "name": "fhir_encounter", "generateInsert": true, "generateUpdate": false, "generateDelete": false, @@ -48,7 +48,7 @@ }, { "schema": "public", - "name": "fhir_Condition", + "name": "fhir_condition", "generateInsert": true, "generateUpdate": false, "generateDelete": false, @@ -58,7 +58,7 @@ }, { "schema": "public", - "name": "fhir_MedicationRequest", + "name": "fhir_medicationrequest", "generateInsert": true, "generateUpdate": false, "generateDelete": false, diff --git a/Clinical/Clinical.Api/Program.cs b/Clinical/Clinical.Api/Program.cs index 6606de6..a6d7bdc 100644 --- a/Clinical/Clinical.Api/Program.cs +++ b/Clinical/Clinical.Api/Program.cs @@ -94,19 +94,22 @@ Func<NpgsqlConnection> getConn ) => { using var conn = getConn(); - // active is mapped to -1 (sentinel "no filter") when not provided -- the - // generated SQL is post-processed to read `@active = -1` instead of - // `@active IS NULL`, since the generator only produces non-nullable int. + // Active and gender filters are applied in C# because LQL `is null` + // checks produce non-nullable params with no "match-all" sentinel. + // String LIKE filters survive empty-string params via LIKE '%%'. var result = await conn.GetPatientsAsync( - active.HasValue ? (active.Value ? 1 : 0) : -1, familyName ?? string.Empty, - givenName ?? string.Empty, - gender ?? string.Empty + givenName ?? string.Empty ) .ConfigureAwait(false); return result switch { - GetPatientsOk(var patients) => Results.Ok(patients), + GetPatientsOk(var patients) => Results.Ok( + patients + .Where(p => !active.HasValue || p.Active == (active.Value ? 1 : 0)) + .Where(p => string.IsNullOrEmpty(gender) || p.Gender == gender) + .ToImmutableList() + ), GetPatientsError(var err) => Results.Problem(err.Message), }; } @@ -160,7 +163,7 @@ Func<NpgsqlConnection> getConn ); var result = await transaction - .Insertfhir_PatientAsync( + .Insertfhir_patientAsync( id, request.Active ? 1 : 0, request.GivenName, @@ -250,7 +253,7 @@ Func<NpgsqlConnection> getConn ); var result = await transaction - .Updatefhir_PatientAsync( + .Updatefhir_patientAsync( id, request.Active ? 1 : 0, request.GivenName, @@ -373,7 +376,7 @@ Func<NpgsqlConnection> getConn ); var result = await transaction - .Insertfhir_EncounterAsync( + .Insertfhir_encounterAsync( id, request.Status, request.Class, @@ -469,7 +472,7 @@ Func<NpgsqlConnection> getConn var recordedDate = DateTime.UtcNow.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture); var result = await transaction - .Insertfhir_ConditionAsync( + .Insertfhir_conditionAsync( id, request.ClinicalStatus, request.VerificationStatus, @@ -578,7 +581,7 @@ Func<NpgsqlConnection> getConn ); var result = await transaction - .Insertfhir_MedicationRequestAsync( + .Insertfhir_medicationrequestAsync( id, request.Status, request.Intent, @@ -787,7 +790,7 @@ Func<NpgsqlConnection> getConn using var conn = getConn(); using var cmd = conn.CreateCommand(); cmd.CommandText = - "SELECT ProviderId, FirstName, LastName, Specialty, SyncedAt FROM sync_Provider"; + "SELECT \"ProviderId\", \"FirstName\", \"LastName\", \"Specialty\", \"SyncedAt\" FROM sync_provider"; using var reader = cmd.ExecuteReader(); var providers = new List<object>(); while (reader.Read()) diff --git a/Clinical/Clinical.Api/Queries/GetConditionsByPatient.lql b/Clinical/Clinical.Api/Queries/GetConditionsByPatient.lql index 6b88fa6..970a63b 100644 --- a/Clinical/Clinical.Api/Queries/GetConditionsByPatient.lql +++ b/Clinical/Clinical.Api/Queries/GetConditionsByPatient.lql @@ -1,6 +1,6 @@ -- Get conditions for a patient -- Parameters: @patientId -fhir_Condition -|> filter(fn(row) => row.fhir_Condition.SubjectReference = @patientId) -|> select(fhir_Condition.Id, fhir_Condition.ClinicalStatus, fhir_Condition.VerificationStatus, fhir_Condition.Category, fhir_Condition.Severity, fhir_Condition.CodeSystem, fhir_Condition.CodeValue, fhir_Condition.CodeDisplay, fhir_Condition.SubjectReference, fhir_Condition.EncounterReference, fhir_Condition.OnsetDateTime, fhir_Condition.RecordedDate, fhir_Condition.RecorderReference, fhir_Condition.NoteText, fhir_Condition.LastUpdated, fhir_Condition.VersionId) -|> order_by(fhir_Condition.RecordedDate desc) +fhir_condition +|> filter(fn(row) => row.fhir_condition.SubjectReference = @patientId) +|> select(fhir_condition.Id, fhir_condition.ClinicalStatus, fhir_condition.VerificationStatus, fhir_condition.Category, fhir_condition.Severity, fhir_condition.CodeSystem, fhir_condition.CodeValue, fhir_condition.CodeDisplay, fhir_condition.SubjectReference, fhir_condition.EncounterReference, fhir_condition.OnsetDateTime, fhir_condition.RecordedDate, fhir_condition.RecorderReference, fhir_condition.NoteText, fhir_condition.LastUpdated, fhir_condition.VersionId) +|> order_by(fhir_condition.RecordedDate desc) diff --git a/Clinical/Clinical.Api/Queries/GetEncountersByPatient.lql b/Clinical/Clinical.Api/Queries/GetEncountersByPatient.lql index 2f6530f..e01f806 100644 --- a/Clinical/Clinical.Api/Queries/GetEncountersByPatient.lql +++ b/Clinical/Clinical.Api/Queries/GetEncountersByPatient.lql @@ -1,6 +1,6 @@ -- Get encounters for a patient -- Parameters: @patientId -fhir_Encounter -|> filter(fn(row) => row.fhir_Encounter.PatientId = @patientId) -|> select(fhir_Encounter.Id, fhir_Encounter.Status, fhir_Encounter.Class, fhir_Encounter.PatientId, fhir_Encounter.PractitionerId, fhir_Encounter.ServiceType, fhir_Encounter.ReasonCode, fhir_Encounter.PeriodStart, fhir_Encounter.PeriodEnd, fhir_Encounter.Notes, fhir_Encounter.LastUpdated, fhir_Encounter.VersionId) -|> order_by(fhir_Encounter.PeriodStart desc) +fhir_encounter +|> filter(fn(row) => row.fhir_encounter.PatientId = @patientId) +|> select(fhir_encounter.Id, fhir_encounter.Status, fhir_encounter.Class, fhir_encounter.PatientId, fhir_encounter.PractitionerId, fhir_encounter.ServiceType, fhir_encounter.ReasonCode, fhir_encounter.PeriodStart, fhir_encounter.PeriodEnd, fhir_encounter.Notes, fhir_encounter.LastUpdated, fhir_encounter.VersionId) +|> order_by(fhir_encounter.PeriodStart desc) diff --git a/Clinical/Clinical.Api/Queries/GetMedicationsByPatient.lql b/Clinical/Clinical.Api/Queries/GetMedicationsByPatient.lql index b7e53d3..9faf86f 100644 --- a/Clinical/Clinical.Api/Queries/GetMedicationsByPatient.lql +++ b/Clinical/Clinical.Api/Queries/GetMedicationsByPatient.lql @@ -1,6 +1,6 @@ -- Get medication requests for a patient -- Parameters: @patientId -fhir_MedicationRequest -|> filter(fn(row) => row.fhir_MedicationRequest.PatientId = @patientId) -|> select(fhir_MedicationRequest.Id, fhir_MedicationRequest.Status, fhir_MedicationRequest.Intent, fhir_MedicationRequest.PatientId, fhir_MedicationRequest.PractitionerId, fhir_MedicationRequest.EncounterId, fhir_MedicationRequest.MedicationCode, fhir_MedicationRequest.MedicationDisplay, fhir_MedicationRequest.DosageInstruction, fhir_MedicationRequest.Quantity, fhir_MedicationRequest.Unit, fhir_MedicationRequest.Refills, fhir_MedicationRequest.AuthoredOn, fhir_MedicationRequest.LastUpdated, fhir_MedicationRequest.VersionId) -|> order_by(fhir_MedicationRequest.AuthoredOn desc) +fhir_medicationrequest +|> filter(fn(row) => row.fhir_medicationrequest.PatientId = @patientId) +|> select(fhir_medicationrequest.Id, fhir_medicationrequest.Status, fhir_medicationrequest.Intent, fhir_medicationrequest.PatientId, fhir_medicationrequest.PractitionerId, fhir_medicationrequest.EncounterId, fhir_medicationrequest.MedicationCode, fhir_medicationrequest.MedicationDisplay, fhir_medicationrequest.DosageInstruction, fhir_medicationrequest.Quantity, fhir_medicationrequest.Unit, fhir_medicationrequest.Refills, fhir_medicationrequest.AuthoredOn, fhir_medicationrequest.LastUpdated, fhir_medicationrequest.VersionId) +|> order_by(fhir_medicationrequest.AuthoredOn desc) diff --git a/Clinical/Clinical.Api/Queries/GetPatientById.lql b/Clinical/Clinical.Api/Queries/GetPatientById.lql index 250e0ee..5299198 100644 --- a/Clinical/Clinical.Api/Queries/GetPatientById.lql +++ b/Clinical/Clinical.Api/Queries/GetPatientById.lql @@ -1,5 +1,5 @@ -- Get patient by ID -- Parameters: @id -fhir_Patient -|> filter(fn(row) => row.fhir_Patient.Id = @id) -|> select(fhir_Patient.Id, fhir_Patient.Active, fhir_Patient.GivenName, fhir_Patient.FamilyName, fhir_Patient.BirthDate, fhir_Patient.Gender, fhir_Patient.Phone, fhir_Patient.Email, fhir_Patient.AddressLine, fhir_Patient.City, fhir_Patient.State, fhir_Patient.PostalCode, fhir_Patient.Country, fhir_Patient.LastUpdated, fhir_Patient.VersionId) +fhir_patient +|> filter(fn(row) => row.fhir_patient.Id = @id) +|> select(fhir_patient.Id, fhir_patient.Active, fhir_patient.GivenName, fhir_patient.FamilyName, fhir_patient.BirthDate, fhir_patient.Gender, fhir_patient.Phone, fhir_patient.Email, fhir_patient.AddressLine, fhir_patient.City, fhir_patient.State, fhir_patient.PostalCode, fhir_patient.Country, fhir_patient.LastUpdated, fhir_patient.VersionId) diff --git a/Clinical/Clinical.Api/Queries/GetPatients.lql b/Clinical/Clinical.Api/Queries/GetPatients.lql index 6d47e4c..a566633 100644 --- a/Clinical/Clinical.Api/Queries/GetPatients.lql +++ b/Clinical/Clinical.Api/Queries/GetPatients.lql @@ -1,6 +1,7 @@ -- Get patients with optional FHIR search parameters --- Parameters: @active, @familyName, @givenName, @gender -fhir_Patient -|> filter(fn(p) => (@active is null or p.fhir_Patient.Active = @active) and (@familyName is null or p.fhir_Patient.FamilyName like '%' || @familyName || '%') and (@givenName is null or p.fhir_Patient.GivenName like '%' || @givenName || '%') and (@gender is null or p.fhir_Patient.Gender = @gender)) -|> select(fhir_Patient.Id, fhir_Patient.Active, fhir_Patient.GivenName, fhir_Patient.FamilyName, fhir_Patient.BirthDate, fhir_Patient.Gender, fhir_Patient.Phone, fhir_Patient.Email, fhir_Patient.AddressLine, fhir_Patient.City, fhir_Patient.State, fhir_Patient.PostalCode, fhir_Patient.Country, fhir_Patient.LastUpdated, fhir_Patient.VersionId) -|> order_by(fhir_Patient.FamilyName, fhir_Patient.GivenName) +-- Parameters: @familyName, @givenName (active and gender filters applied in C#). +-- Empty string passed for @familyName / @givenName matches all rows via LIKE '%%'. +fhir_patient +|> filter(fn(p) => (@familyName is null or p.fhir_patient.FamilyName like '%' || @familyName || '%') and (@givenName is null or p.fhir_patient.GivenName like '%' || @givenName || '%')) +|> select(fhir_patient.Id, fhir_patient.Active, fhir_patient.GivenName, fhir_patient.FamilyName, fhir_patient.BirthDate, fhir_patient.Gender, fhir_patient.Phone, fhir_patient.Email, fhir_patient.AddressLine, fhir_patient.City, fhir_patient.State, fhir_patient.PostalCode, fhir_patient.Country, fhir_patient.LastUpdated, fhir_patient.VersionId) +|> order_by(fhir_patient.FamilyName, fhir_patient.GivenName) diff --git a/Clinical/Clinical.Api/Queries/SearchPatients.lql b/Clinical/Clinical.Api/Queries/SearchPatients.lql index 8a256b1..dd52235 100644 --- a/Clinical/Clinical.Api/Queries/SearchPatients.lql +++ b/Clinical/Clinical.Api/Queries/SearchPatients.lql @@ -1,6 +1,6 @@ -- Search patients by name or email -- Parameters: @term -fhir_Patient -|> filter(fn(row) => row.fhir_Patient.GivenName like @term or row.fhir_Patient.FamilyName like @term or row.fhir_Patient.Email like @term) -|> select(fhir_Patient.Id, fhir_Patient.Active, fhir_Patient.GivenName, fhir_Patient.FamilyName, fhir_Patient.BirthDate, fhir_Patient.Gender, fhir_Patient.Phone, fhir_Patient.Email, fhir_Patient.AddressLine, fhir_Patient.City, fhir_Patient.State, fhir_Patient.PostalCode, fhir_Patient.Country, fhir_Patient.LastUpdated, fhir_Patient.VersionId) -|> order_by(fhir_Patient.FamilyName, fhir_Patient.GivenName) +fhir_patient +|> filter(fn(row) => row.fhir_patient.GivenName like @term or row.fhir_patient.FamilyName like @term or row.fhir_patient.Email like @term) +|> select(fhir_patient.Id, fhir_patient.Active, fhir_patient.GivenName, fhir_patient.FamilyName, fhir_patient.BirthDate, fhir_patient.Gender, fhir_patient.Phone, fhir_patient.Email, fhir_patient.AddressLine, fhir_patient.City, fhir_patient.State, fhir_patient.PostalCode, fhir_patient.Country, fhir_patient.LastUpdated, fhir_patient.VersionId) +|> order_by(fhir_patient.FamilyName, fhir_patient.GivenName) diff --git a/Clinical/Clinical.Api/clinical-schema.yaml b/Clinical/Clinical.Api/clinical-schema.yaml index 379c4ee..44e8e10 100644 --- a/Clinical/Clinical.Api/clinical-schema.yaml +++ b/Clinical/Clinical.Api/clinical-schema.yaml @@ -1,6 +1,6 @@ name: clinical tables: -- name: fhir_Patient +- name: fhir_patient columns: - name: Id type: Text @@ -44,10 +44,10 @@ tables: columns: - GivenName primaryKey: - name: PK_fhir_Patient + name: PK_fhir_patient columns: - Id -- name: fhir_Encounter +- name: fhir_encounter columns: - name: Id type: Text @@ -82,17 +82,17 @@ tables: columns: - PatientId foreignKeys: - - name: FK_fhir_Encounter_PatientId + - name: FK_fhir_encounter_PatientId columns: - PatientId - referencedTable: fhir_Patient + referencedTable: fhir_patient referencedColumns: - Id primaryKey: - name: PK_fhir_Encounter + name: PK_fhir_encounter columns: - Id -- name: fhir_Condition +- name: fhir_condition columns: - name: Id type: Text @@ -139,17 +139,17 @@ tables: columns: - SubjectReference foreignKeys: - - name: FK_fhir_Condition_SubjectReference + - name: FK_fhir_condition_SubjectReference columns: - SubjectReference - referencedTable: fhir_Patient + referencedTable: fhir_patient referencedColumns: - Id primaryKey: - name: PK_fhir_Condition + name: PK_fhir_condition columns: - Id -- name: fhir_MedicationRequest +- name: fhir_medicationrequest columns: - name: Id type: Text @@ -192,23 +192,23 @@ tables: columns: - PatientId foreignKeys: - - name: FK_fhir_MedicationRequest_PatientId + - name: FK_fhir_medicationrequest_PatientId columns: - PatientId - referencedTable: fhir_Patient + referencedTable: fhir_patient referencedColumns: - Id - - name: FK_fhir_MedicationRequest_EncounterId + - name: FK_fhir_medicationrequest_EncounterId columns: - EncounterId - referencedTable: fhir_Encounter + referencedTable: fhir_encounter referencedColumns: - Id primaryKey: - name: PK_fhir_MedicationRequest + name: PK_fhir_medicationrequest columns: - Id -- name: sync_Provider +- name: sync_provider columns: - name: ProviderId type: Text @@ -222,6 +222,6 @@ tables: type: Text defaultValue: CURRENT_TIMESTAMP primaryKey: - name: PK_sync_Provider + name: PK_sync_provider columns: - ProviderId diff --git a/Clinical/Clinical.Sync/SyncMappings.json b/Clinical/Clinical.Sync/SyncMappings.json index b5cefb2..f090ab5 100644 --- a/Clinical/Clinical.Sync/SyncMappings.json +++ b/Clinical/Clinical.Sync/SyncMappings.json @@ -2,7 +2,7 @@ "mappings": [ { "source_table": "fhir_Practitioner", - "target_table": "sync_Provider", + "target_table": "sync_provider", "column_mappings": [ { "source": "Id", diff --git a/Clinical/Clinical.Sync/SyncWorker.cs b/Clinical/Clinical.Sync/SyncWorker.cs index 307ce41..2c5894e 100644 --- a/Clinical/Clinical.Sync/SyncWorker.cs +++ b/Clinical/Clinical.Sync/SyncWorker.cs @@ -7,7 +7,7 @@ namespace Clinical.Sync; /// <summary> -/// Background service that pulls Practitioner data from Scheduling.Api and maps to sync_Provider. +/// Background service that pulls Practitioner data from Scheduling.Api and maps to sync_provider. /// </summary> internal sealed class SyncWorker : BackgroundService { @@ -223,7 +223,7 @@ SyncChange change { using var cmd = conn.CreateCommand(); cmd.Transaction = (NpgsqlTransaction)transaction; - cmd.CommandText = "DELETE FROM sync_Provider WHERE ProviderId = @id"; + cmd.CommandText = "DELETE FROM sync_provider WHERE \"ProviderId\" = @id"; cmd.Parameters.AddWithValue("@id", rowId); cmd.ExecuteNonQuery(); _logger.Log(LogLevel.Debug, "Deleted provider {ProviderId}", rowId); @@ -244,13 +244,13 @@ SyncChange change using var upsertCmd = conn.CreateCommand(); upsertCmd.Transaction = (NpgsqlTransaction)transaction; upsertCmd.CommandText = """ - INSERT INTO sync_Provider (ProviderId, FirstName, LastName, Specialty, SyncedAt) + INSERT INTO sync_provider ("ProviderId", "FirstName", "LastName", "Specialty", "SyncedAt") VALUES (@providerId, @firstName, @lastName, @specialty, @syncedAt) - ON CONFLICT(ProviderId) DO UPDATE SET - FirstName = @firstName, - LastName = @lastName, - Specialty = @specialty, - SyncedAt = @syncedAt + ON CONFLICT("ProviderId") DO UPDATE SET + "FirstName" = @firstName, + "LastName" = @lastName, + "Specialty" = @specialty, + "SyncedAt" = @syncedAt """; upsertCmd.Parameters.AddWithValue( diff --git a/Directory.Build.props b/Directory.Build.props index f0cce61..212b30d 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -4,7 +4,7 @@ <NuGetAuditMode>disabled</NuGetAuditMode> <RestoreAuditProperties>false</RestoreAuditProperties> <!-- Single source of truth for every Nimblesite DataProvider / Lql / Sync / Migration package version. --> - <DataProviderVersion>0.9.2-beta</DataProviderVersion> + <DataProviderVersion>0.9.5-beta</DataProviderVersion> <Version>0.1.0</Version> <Authors>ChristianFindlay</Authors> <Company>MelbourneDeveloper</Company> diff --git a/ICD10/ICD10.Api/DatabaseSetup.cs b/ICD10/ICD10.Api/DatabaseSetup.cs index 5bae572..9c37a46 100644 --- a/ICD10/ICD10.Api/DatabaseSetup.cs +++ b/ICD10/ICD10.Api/DatabaseSetup.cs @@ -92,7 +92,7 @@ private static void EnsureVectorIndexes(NpgsqlConnection connection, ILogger log cmd.CommandText = $""" CREATE INDEX IF NOT EXISTS idx_icd10_embedding_vector ON icd10_code_embedding - USING ivfflat (("embedding"::vector(384)) vector_cosine_ops) + USING ivfflat (("Embedding"::vector(384)) vector_cosine_ops) WITH (lists = {lists}) """; cmd.ExecuteNonQuery(); @@ -119,7 +119,7 @@ USING ivfflat (("embedding"::vector(384)) vector_cosine_ops) cmd.CommandText = $""" CREATE INDEX IF NOT EXISTS idx_achi_embedding_vector ON achi_code_embedding - USING ivfflat (("embedding"::vector(384)) vector_cosine_ops) + USING ivfflat (("Embedding"::vector(384)) vector_cosine_ops) WITH (lists = {lists}) """; cmd.ExecuteNonQuery(); diff --git a/ICD10/ICD10.Api/Program.cs b/ICD10/ICD10.Api/Program.cs index acb7282..3e984bd 100644 --- a/ICD10/ICD10.Api/Program.cs +++ b/ICD10/ICD10.Api/Program.cs @@ -315,12 +315,12 @@ IHttpClientFactory httpClientFactory await using (icdCmd.ConfigureAwait(false)) { icdCmd.CommandText = """ - SELECT c."code", c."shortdescription", c."longdescription", - c."inclusionterms", c."exclusionterms", c."codealso", c."codefirst", - 1 - (e."embedding"::vector <=> @queryVector::vector) as similarity + SELECT c."Code", c."ShortDescription", c."LongDescription", + c."InclusionTerms", c."ExclusionTerms", c."CodeAlso", c."CodeFirst", + 1 - (e."Embedding"::vector <=> @queryVector::vector) as similarity FROM icd10_code c - JOIN icd10_code_embedding e ON c."id" = e."codeid" - ORDER BY e."embedding"::vector <=> @queryVector::vector + JOIN icd10_code_embedding e ON c."Id" = e."CodeId" + ORDER BY e."Embedding"::vector <=> @queryVector::vector LIMIT @limit """; icdCmd.Parameters.AddWithValue("@queryVector", vectorString); @@ -370,11 +370,11 @@ LIMIT @limit await using (achiCmd.ConfigureAwait(false)) { achiCmd.CommandText = """ - SELECT c."code", c."shortdescription", c."longdescription", - 1 - (e."embedding"::vector <=> @queryVector::vector) as similarity + SELECT c."Code", c."ShortDescription", c."LongDescription", + 1 - (e."Embedding"::vector <=> @queryVector::vector) as similarity FROM achi_code c - JOIN achi_code_embedding e ON c."id" = e."codeid" - ORDER BY e."embedding"::vector <=> @queryVector::vector + JOIN achi_code_embedding e ON c."Id" = e."CodeId" + ORDER BY e."Embedding"::vector <=> @queryVector::vector LIMIT @limit """; achiCmd.Parameters.AddWithValue("@queryVector", vectorString); diff --git a/Scheduling/Scheduling.Api/DataProvider.json b/Scheduling/Scheduling.Api/DataProvider.json index e610ef7..2bd02f2 100644 --- a/Scheduling/Scheduling.Api/DataProvider.json +++ b/Scheduling/Scheduling.Api/DataProvider.json @@ -52,7 +52,7 @@ "tables": [ { "schema": "public", - "name": "fhir_Practitioner", + "name": "fhir_practitioner", "generateInsert": true, "generateUpdate": false, "generateDelete": false, @@ -62,7 +62,7 @@ }, { "schema": "public", - "name": "fhir_Appointment", + "name": "fhir_appointment", "generateInsert": true, "generateUpdate": false, "generateDelete": false, diff --git a/Scheduling/Scheduling.Api/Program.cs b/Scheduling/Scheduling.Api/Program.cs index fdd9244..f75146b 100644 --- a/Scheduling/Scheduling.Api/Program.cs +++ b/Scheduling/Scheduling.Api/Program.cs @@ -141,7 +141,7 @@ var id = Guid.NewGuid().ToString(); var result = await transaction - .Insertfhir_PractitionerAsync( + .Insertfhir_practitionerAsync( id, request.Identifier, 1, @@ -201,15 +201,15 @@ using var cmd = conn.CreateCommand(); cmd.Transaction = transaction; cmd.CommandText = """ - UPDATE fhir_Practitioner - SET NameFamily = @nameFamily, - NameGiven = @nameGiven, - Qualification = @qualification, - Specialty = @specialty, - TelecomEmail = @telecomEmail, - TelecomPhone = @telecomPhone, - Active = @active - WHERE Id = @id + UPDATE fhir_practitioner + SET "NameFamily" = @nameFamily, + "NameGiven" = @nameGiven, + "Qualification" = @qualification, + "Specialty" = @specialty, + "TelecomEmail" = @telecomEmail, + "TelecomPhone" = @telecomPhone, + "Active" = @active + WHERE "Id" = @id """; cmd.Parameters.AddWithValue("@id", id); cmd.Parameters.AddWithValue("@nameFamily", request.NameFamily); @@ -354,7 +354,7 @@ UPDATE fhir_Practitioner var durationMinutes = (int)(end - start).TotalMinutes; var result = await transaction - .Insertfhir_AppointmentAsync( + .Insertfhir_appointmentAsync( id, "booked", request.ServiceCategory ?? string.Empty, @@ -428,20 +428,20 @@ UPDATE fhir_Practitioner using var cmd = conn.CreateCommand(); cmd.Transaction = transaction; cmd.CommandText = """ - UPDATE fhir_Appointment - SET ServiceCategory = @serviceCategory, - ServiceType = @serviceType, - ReasonCode = @reasonCode, - Priority = @priority, - Description = @description, - StartTime = @start, - EndTime = @end, - MinutesDuration = @duration, - PatientReference = @patientRef, - PractitionerReference = @practitionerRef, - Comment = @comment, - Status = @status - WHERE Id = @id + UPDATE fhir_appointment + SET "ServiceCategory" = @serviceCategory, + "ServiceType" = @serviceType, + "ReasonCode" = @reasonCode, + "Priority" = @priority, + "Description" = @description, + "StartTime" = @start, + "EndTime" = @end, + "MinutesDuration" = @duration, + "PatientReference" = @patientRef, + "PractitionerReference" = @practitionerRef, + "Comment" = @comment, + "Status" = @status + WHERE "Id" = @id """; cmd.Parameters.AddWithValue("@id", id); cmd.Parameters.AddWithValue( @@ -508,7 +508,7 @@ UPDATE fhir_Appointment using var cmd = conn.CreateCommand(); cmd.Transaction = transaction; - cmd.CommandText = "UPDATE fhir_Appointment SET Status = @status WHERE Id = @id"; + cmd.CommandText = "UPDATE fhir_appointment SET \"Status\" = @status WHERE \"Id\" = @id"; cmd.Parameters.AddWithValue("@status", status); cmd.Parameters.AddWithValue("@id", id); @@ -739,7 +739,7 @@ Func<NpgsqlConnection> getConn using var conn = getConn(); using var cmd = conn.CreateCommand(); cmd.CommandText = - "SELECT PatientId, DisplayName, ContactPhone, ContactEmail, SyncedAt FROM sync_ScheduledPatient"; + "SELECT \"PatientId\", \"DisplayName\", \"ContactPhone\", \"ContactEmail\", \"SyncedAt\" FROM sync_scheduledpatient"; using var reader = cmd.ExecuteReader(); var patients = new List<object>(); while (reader.Read()) diff --git a/Scheduling/Scheduling.Api/Queries/CheckSchedulingConflicts.lql b/Scheduling/Scheduling.Api/Queries/CheckSchedulingConflicts.lql index 2885529..85bfc69 100644 --- a/Scheduling/Scheduling.Api/Queries/CheckSchedulingConflicts.lql +++ b/Scheduling/Scheduling.Api/Queries/CheckSchedulingConflicts.lql @@ -1,5 +1,5 @@ -- Check for scheduling conflicts -- Parameters: @practitionerRef, @proposedStart, @proposedEnd -fhir_Appointment -|> filter(fn(row) => row.fhir_Appointment.PractitionerReference = @practitionerRef and row.fhir_Appointment.Status != 'cancelled' and row.fhir_Appointment.StartTime < @proposedEnd and row.fhir_Appointment.EndTime > @proposedStart) -|> select(fhir_Appointment.Id, fhir_Appointment.StartTime, fhir_Appointment.EndTime, fhir_Appointment.Status) +fhir_appointment +|> filter(fn(row) => row.fhir_appointment.PractitionerReference = @practitionerRef and row.fhir_appointment.Status != 'cancelled' and row.fhir_appointment.StartTime < @proposedEnd and row.fhir_appointment.EndTime > @proposedStart) +|> select(fhir_appointment.Id, fhir_appointment.StartTime, fhir_appointment.EndTime, fhir_appointment.Status) diff --git a/Scheduling/Scheduling.Api/Queries/GetAllPractitioners.lql b/Scheduling/Scheduling.Api/Queries/GetAllPractitioners.lql index cd02457..e4c2630 100644 --- a/Scheduling/Scheduling.Api/Queries/GetAllPractitioners.lql +++ b/Scheduling/Scheduling.Api/Queries/GetAllPractitioners.lql @@ -1,4 +1,4 @@ -- Get all practitioners -fhir_Practitioner -|> select(fhir_Practitioner.Id, fhir_Practitioner.Identifier, fhir_Practitioner.Active, fhir_Practitioner.NameFamily, fhir_Practitioner.NameGiven, fhir_Practitioner.Qualification, fhir_Practitioner.Specialty, fhir_Practitioner.TelecomEmail, fhir_Practitioner.TelecomPhone) -|> order_by(fhir_Practitioner.NameFamily, fhir_Practitioner.NameGiven) +fhir_practitioner +|> select(fhir_practitioner.Id, fhir_practitioner.Identifier, fhir_practitioner.Active, fhir_practitioner.NameFamily, fhir_practitioner.NameGiven, fhir_practitioner.Qualification, fhir_practitioner.Specialty, fhir_practitioner.TelecomEmail, fhir_practitioner.TelecomPhone) +|> order_by(fhir_practitioner.NameFamily, fhir_practitioner.NameGiven) diff --git a/Scheduling/Scheduling.Api/Queries/GetAppointmentById.lql b/Scheduling/Scheduling.Api/Queries/GetAppointmentById.lql index d12e4a7..3e184e4 100644 --- a/Scheduling/Scheduling.Api/Queries/GetAppointmentById.lql +++ b/Scheduling/Scheduling.Api/Queries/GetAppointmentById.lql @@ -1,5 +1,5 @@ -- Get appointment by ID -- Parameters: @id -fhir_Appointment -|> filter(fn(row) => row.fhir_Appointment.Id = @id) -|> select(fhir_Appointment.Id, fhir_Appointment.Status, fhir_Appointment.ServiceCategory, fhir_Appointment.ServiceType, fhir_Appointment.ReasonCode, fhir_Appointment.Priority, fhir_Appointment.Description, fhir_Appointment.StartTime, fhir_Appointment.EndTime, fhir_Appointment.MinutesDuration, fhir_Appointment.PatientReference, fhir_Appointment.PractitionerReference, fhir_Appointment.Created, fhir_Appointment.Comment) +fhir_appointment +|> filter(fn(row) => row.fhir_appointment.Id = @id) +|> select(fhir_appointment.Id, fhir_appointment.Status, fhir_appointment.ServiceCategory, fhir_appointment.ServiceType, fhir_appointment.ReasonCode, fhir_appointment.Priority, fhir_appointment.Description, fhir_appointment.StartTime, fhir_appointment.EndTime, fhir_appointment.MinutesDuration, fhir_appointment.PatientReference, fhir_appointment.PractitionerReference, fhir_appointment.Created, fhir_appointment.Comment) diff --git a/Scheduling/Scheduling.Api/Queries/GetAppointmentsByPatient.lql b/Scheduling/Scheduling.Api/Queries/GetAppointmentsByPatient.lql index 11bd7cc..391aa79 100644 --- a/Scheduling/Scheduling.Api/Queries/GetAppointmentsByPatient.lql +++ b/Scheduling/Scheduling.Api/Queries/GetAppointmentsByPatient.lql @@ -1,6 +1,6 @@ -- Get appointments for a patient -- Parameters: @patientReference -fhir_Appointment -|> filter(fn(row) => row.fhir_Appointment.PatientReference = @patientReference) -|> select(fhir_Appointment.Id, fhir_Appointment.Status, fhir_Appointment.ServiceCategory, fhir_Appointment.ServiceType, fhir_Appointment.ReasonCode, fhir_Appointment.Priority, fhir_Appointment.Description, fhir_Appointment.StartTime, fhir_Appointment.EndTime, fhir_Appointment.MinutesDuration, fhir_Appointment.PatientReference, fhir_Appointment.PractitionerReference, fhir_Appointment.Created, fhir_Appointment.Comment) -|> order_by(fhir_Appointment.StartTime desc) +fhir_appointment +|> filter(fn(row) => row.fhir_appointment.PatientReference = @patientReference) +|> select(fhir_appointment.Id, fhir_appointment.Status, fhir_appointment.ServiceCategory, fhir_appointment.ServiceType, fhir_appointment.ReasonCode, fhir_appointment.Priority, fhir_appointment.Description, fhir_appointment.StartTime, fhir_appointment.EndTime, fhir_appointment.MinutesDuration, fhir_appointment.PatientReference, fhir_appointment.PractitionerReference, fhir_appointment.Created, fhir_appointment.Comment) +|> order_by(fhir_appointment.StartTime desc) diff --git a/Scheduling/Scheduling.Api/Queries/GetAppointmentsByPractitioner.lql b/Scheduling/Scheduling.Api/Queries/GetAppointmentsByPractitioner.lql index 97effa5..0cff4aa 100644 --- a/Scheduling/Scheduling.Api/Queries/GetAppointmentsByPractitioner.lql +++ b/Scheduling/Scheduling.Api/Queries/GetAppointmentsByPractitioner.lql @@ -1,6 +1,6 @@ -- Get appointments for a practitioner -- Parameters: @practitionerReference -fhir_Appointment -|> filter(fn(row) => row.fhir_Appointment.PractitionerReference = @practitionerReference and row.fhir_Appointment.Status = 'booked') -|> select(fhir_Appointment.Id, fhir_Appointment.Status, fhir_Appointment.ServiceCategory, fhir_Appointment.ServiceType, fhir_Appointment.ReasonCode, fhir_Appointment.Priority, fhir_Appointment.Description, fhir_Appointment.StartTime, fhir_Appointment.EndTime, fhir_Appointment.MinutesDuration, fhir_Appointment.PatientReference, fhir_Appointment.PractitionerReference, fhir_Appointment.Created, fhir_Appointment.Comment) -|> order_by(fhir_Appointment.StartTime) +fhir_appointment +|> filter(fn(row) => row.fhir_appointment.PractitionerReference = @practitionerReference and row.fhir_appointment.Status = 'booked') +|> select(fhir_appointment.Id, fhir_appointment.Status, fhir_appointment.ServiceCategory, fhir_appointment.ServiceType, fhir_appointment.ReasonCode, fhir_appointment.Priority, fhir_appointment.Description, fhir_appointment.StartTime, fhir_appointment.EndTime, fhir_appointment.MinutesDuration, fhir_appointment.PatientReference, fhir_appointment.PractitionerReference, fhir_appointment.Created, fhir_appointment.Comment) +|> order_by(fhir_appointment.StartTime) diff --git a/Scheduling/Scheduling.Api/Queries/GetAppointmentsByStatus.lql b/Scheduling/Scheduling.Api/Queries/GetAppointmentsByStatus.lql index 32fa9b8..1bd11c4 100644 --- a/Scheduling/Scheduling.Api/Queries/GetAppointmentsByStatus.lql +++ b/Scheduling/Scheduling.Api/Queries/GetAppointmentsByStatus.lql @@ -1,8 +1,8 @@ -- Get appointments by status with patient and practitioner info -- Parameters: @status, @dateStart, @dateEnd -fhir_Appointment -|> join(sync_ScheduledPatient, on = fhir_Appointment.PatientReference = sync_ScheduledPatient.PatientId) -|> join(fhir_Practitioner, on = fhir_Appointment.PractitionerReference = fhir_Practitioner.Id) -|> filter(fn(row) => row.fhir_Appointment.Status = @status and row.fhir_Appointment.StartTime >= @dateStart and row.fhir_Appointment.StartTime < @dateEnd) -|> select(fhir_Appointment.Id, fhir_Appointment.StartTime, fhir_Appointment.EndTime, fhir_Appointment.Status, sync_ScheduledPatient.DisplayName, fhir_Practitioner.NameFamily, fhir_Practitioner.NameGiven, fhir_Appointment.ServiceType, fhir_Appointment.ReasonCode) -|> order_by(fhir_Appointment.StartTime) +fhir_appointment +|> join(sync_scheduledpatient, on = fhir_appointment.PatientReference = sync_scheduledpatient.PatientId) +|> join(fhir_practitioner, on = fhir_appointment.PractitionerReference = fhir_practitioner.Id) +|> filter(fn(row) => row.fhir_appointment.Status = @status and row.fhir_appointment.StartTime >= @dateStart and row.fhir_appointment.StartTime < @dateEnd) +|> select(fhir_appointment.Id, fhir_appointment.StartTime, fhir_appointment.EndTime, fhir_appointment.Status, sync_scheduledpatient.DisplayName, fhir_practitioner.NameFamily, fhir_practitioner.NameGiven, fhir_appointment.ServiceType, fhir_appointment.ReasonCode) +|> order_by(fhir_appointment.StartTime) diff --git a/Scheduling/Scheduling.Api/Queries/GetAvailableSlots.lql b/Scheduling/Scheduling.Api/Queries/GetAvailableSlots.lql index 487e8a8..52a3e1b 100644 --- a/Scheduling/Scheduling.Api/Queries/GetAvailableSlots.lql +++ b/Scheduling/Scheduling.Api/Queries/GetAvailableSlots.lql @@ -1,7 +1,7 @@ -- Get available slots for a practitioner -- Parameters: @practitionerRef, @fromDate, @toDate -fhir_Slot -|> join(fhir_Schedule, on = fhir_Slot.ScheduleReference = fhir_Schedule.Id) -|> filter(fn(row) => row.fhir_Schedule.PractitionerReference = @practitionerRef and row.fhir_Slot.Status = 'free' and row.fhir_Slot.StartTime >= @fromDate and row.fhir_Slot.StartTime < @toDate) -|> select(fhir_Slot.Id, fhir_Slot.Status, fhir_Slot.StartTime, fhir_Slot.EndTime, fhir_Schedule.PractitionerReference) -|> order_by(fhir_Slot.StartTime) +fhir_slot +|> join(fhir_schedule, on = fhir_slot.ScheduleReference = fhir_schedule.Id) +|> filter(fn(row) => row.fhir_schedule.PractitionerReference = @practitionerRef and row.fhir_slot.Status = 'free' and row.fhir_slot.StartTime >= @fromDate and row.fhir_slot.StartTime < @toDate) +|> select(fhir_slot.Id, fhir_slot.Status, fhir_slot.StartTime, fhir_slot.EndTime, fhir_schedule.PractitionerReference) +|> order_by(fhir_slot.StartTime) diff --git a/Scheduling/Scheduling.Api/Queries/GetPractitionerById.lql b/Scheduling/Scheduling.Api/Queries/GetPractitionerById.lql index 8aeb570..e8ec48e 100644 --- a/Scheduling/Scheduling.Api/Queries/GetPractitionerById.lql +++ b/Scheduling/Scheduling.Api/Queries/GetPractitionerById.lql @@ -1,5 +1,5 @@ -- Get practitioner by ID -- Parameters: @id -fhir_Practitioner -|> filter(fn(row) => row.fhir_Practitioner.Id = @id) -|> select(fhir_Practitioner.Id, fhir_Practitioner.Identifier, fhir_Practitioner.Active, fhir_Practitioner.NameFamily, fhir_Practitioner.NameGiven, fhir_Practitioner.Qualification, fhir_Practitioner.Specialty, fhir_Practitioner.TelecomEmail, fhir_Practitioner.TelecomPhone) +fhir_practitioner +|> filter(fn(row) => row.fhir_practitioner.Id = @id) +|> select(fhir_practitioner.Id, fhir_practitioner.Identifier, fhir_practitioner.Active, fhir_practitioner.NameFamily, fhir_practitioner.NameGiven, fhir_practitioner.Qualification, fhir_practitioner.Specialty, fhir_practitioner.TelecomEmail, fhir_practitioner.TelecomPhone) diff --git a/Scheduling/Scheduling.Api/Queries/GetProviderAvailability.lql b/Scheduling/Scheduling.Api/Queries/GetProviderAvailability.lql index b033b7b..f7aefce 100644 --- a/Scheduling/Scheduling.Api/Queries/GetProviderAvailability.lql +++ b/Scheduling/Scheduling.Api/Queries/GetProviderAvailability.lql @@ -1,6 +1,6 @@ -- Get provider availability schedule -- Parameters: @practitionerRef -fhir_Schedule -|> join(fhir_Practitioner, on = fhir_Schedule.PractitionerReference = fhir_Practitioner.Id) -|> filter(fn(row) => row.fhir_Schedule.PractitionerReference = @practitionerRef and row.fhir_Schedule.Active = 1) -|> select(fhir_Schedule.Id, fhir_Schedule.PractitionerReference, fhir_Practitioner.NameFamily, fhir_Practitioner.NameGiven, fhir_Schedule.PlanningHorizon, fhir_Schedule.Active) +fhir_schedule +|> join(fhir_practitioner, on = fhir_schedule.PractitionerReference = fhir_practitioner.Id) +|> filter(fn(row) => row.fhir_schedule.PractitionerReference = @practitionerRef and row.fhir_schedule.Active = 1) +|> select(fhir_schedule.Id, fhir_schedule.PractitionerReference, fhir_practitioner.NameFamily, fhir_practitioner.NameGiven, fhir_schedule.PlanningHorizon, fhir_schedule.Active) diff --git a/Scheduling/Scheduling.Api/Queries/GetProviderDailySchedule.lql b/Scheduling/Scheduling.Api/Queries/GetProviderDailySchedule.lql index 36c1fd9..0f62b15 100644 --- a/Scheduling/Scheduling.Api/Queries/GetProviderDailySchedule.lql +++ b/Scheduling/Scheduling.Api/Queries/GetProviderDailySchedule.lql @@ -1,7 +1,7 @@ -- Get provider daily schedule with patient info -- Parameters: @practitionerRef, @dateStart, @dateEnd -fhir_Appointment -|> join(sync_ScheduledPatient, on = fhir_Appointment.PatientReference = sync_ScheduledPatient.PatientId) -|> filter(fn(row) => row.fhir_Appointment.PractitionerReference = @practitionerRef and row.fhir_Appointment.StartTime >= @dateStart and row.fhir_Appointment.StartTime < @dateEnd) -|> select(fhir_Appointment.Id, fhir_Appointment.StartTime, fhir_Appointment.EndTime, fhir_Appointment.MinutesDuration, fhir_Appointment.Status, fhir_Appointment.ServiceCategory, fhir_Appointment.ServiceType, fhir_Appointment.ReasonCode, fhir_Appointment.Description, fhir_Appointment.PatientReference, sync_ScheduledPatient.PatientId, sync_ScheduledPatient.DisplayName, sync_ScheduledPatient.ContactPhone, fhir_Appointment.PractitionerReference) -|> order_by(fhir_Appointment.StartTime) +fhir_appointment +|> join(sync_scheduledpatient, on = fhir_appointment.PatientReference = sync_scheduledpatient.PatientId) +|> filter(fn(row) => row.fhir_appointment.PractitionerReference = @practitionerRef and row.fhir_appointment.StartTime >= @dateStart and row.fhir_appointment.StartTime < @dateEnd) +|> select(fhir_appointment.Id, fhir_appointment.StartTime, fhir_appointment.EndTime, fhir_appointment.MinutesDuration, fhir_appointment.Status, fhir_appointment.ServiceCategory, fhir_appointment.ServiceType, fhir_appointment.ReasonCode, fhir_appointment.Description, fhir_appointment.PatientReference, sync_scheduledpatient.PatientId, sync_scheduledpatient.DisplayName, sync_scheduledpatient.ContactPhone, fhir_appointment.PractitionerReference) +|> order_by(fhir_appointment.StartTime) diff --git a/Scheduling/Scheduling.Api/Queries/GetUpcomingAppointments.lql b/Scheduling/Scheduling.Api/Queries/GetUpcomingAppointments.lql index 44893dd..f691269 100644 --- a/Scheduling/Scheduling.Api/Queries/GetUpcomingAppointments.lql +++ b/Scheduling/Scheduling.Api/Queries/GetUpcomingAppointments.lql @@ -1,5 +1,5 @@ -- Get all booked appointments (no limit - calendar needs all appointments) -fhir_Appointment -|> filter(fn(row) => row.fhir_Appointment.Status = 'booked') -|> select(fhir_Appointment.Id, fhir_Appointment.Status, fhir_Appointment.ServiceCategory, fhir_Appointment.ServiceType, fhir_Appointment.ReasonCode, fhir_Appointment.Priority, fhir_Appointment.Description, fhir_Appointment.StartTime, fhir_Appointment.EndTime, fhir_Appointment.MinutesDuration, fhir_Appointment.PatientReference, fhir_Appointment.PractitionerReference, fhir_Appointment.Created, fhir_Appointment.Comment) -|> order_by(fhir_Appointment.StartTime) +fhir_appointment +|> filter(fn(row) => row.fhir_appointment.Status = 'booked') +|> select(fhir_appointment.Id, fhir_appointment.Status, fhir_appointment.ServiceCategory, fhir_appointment.ServiceType, fhir_appointment.ReasonCode, fhir_appointment.Priority, fhir_appointment.Description, fhir_appointment.StartTime, fhir_appointment.EndTime, fhir_appointment.MinutesDuration, fhir_appointment.PatientReference, fhir_appointment.PractitionerReference, fhir_appointment.Created, fhir_appointment.Comment) +|> order_by(fhir_appointment.StartTime) diff --git a/Scheduling/Scheduling.Api/Queries/SearchPractitionersBySpecialty.lql b/Scheduling/Scheduling.Api/Queries/SearchPractitionersBySpecialty.lql index b7ee685..fbe2fcb 100644 --- a/Scheduling/Scheduling.Api/Queries/SearchPractitionersBySpecialty.lql +++ b/Scheduling/Scheduling.Api/Queries/SearchPractitionersBySpecialty.lql @@ -1,6 +1,6 @@ -- Search practitioners by specialty -- Parameters: @specialty -fhir_Practitioner -|> filter(fn(row) => row.fhir_Practitioner.Specialty like '%' || @specialty || '%') -|> select(fhir_Practitioner.Id, fhir_Practitioner.Identifier, fhir_Practitioner.Active, fhir_Practitioner.NameFamily, fhir_Practitioner.NameGiven, fhir_Practitioner.Qualification, fhir_Practitioner.Specialty, fhir_Practitioner.TelecomEmail, fhir_Practitioner.TelecomPhone) -|> order_by(fhir_Practitioner.NameFamily, fhir_Practitioner.NameGiven) +fhir_practitioner +|> filter(fn(row) => row.fhir_practitioner.Specialty like '%' || @specialty || '%') +|> select(fhir_practitioner.Id, fhir_practitioner.Identifier, fhir_practitioner.Active, fhir_practitioner.NameFamily, fhir_practitioner.NameGiven, fhir_practitioner.Qualification, fhir_practitioner.Specialty, fhir_practitioner.TelecomEmail, fhir_practitioner.TelecomPhone) +|> order_by(fhir_practitioner.NameFamily, fhir_practitioner.NameGiven) diff --git a/Scheduling/Scheduling.Api/scheduling-schema.yaml b/Scheduling/Scheduling.Api/scheduling-schema.yaml index ec1d910..2f92ac9 100644 --- a/Scheduling/Scheduling.Api/scheduling-schema.yaml +++ b/Scheduling/Scheduling.Api/scheduling-schema.yaml @@ -1,6 +1,6 @@ name: scheduling tables: -- name: fhir_Practitioner +- name: fhir_practitioner columns: - name: Id type: Text @@ -29,10 +29,10 @@ tables: columns: - Specialty primaryKey: - name: PK_fhir_Practitioner + name: PK_fhir_practitioner columns: - Id -- name: fhir_Schedule +- name: fhir_schedule columns: - name: Id type: Text @@ -51,17 +51,17 @@ tables: columns: - PractitionerReference foreignKeys: - - name: FK_fhir_Schedule_PractitionerReference + - name: FK_fhir_schedule_PractitionerReference columns: - PractitionerReference - referencedTable: fhir_Practitioner + referencedTable: fhir_practitioner referencedColumns: - Id primaryKey: - name: PK_fhir_Schedule + name: PK_fhir_schedule columns: - Id -- name: fhir_Slot +- name: fhir_slot columns: - name: Id type: Text @@ -87,17 +87,17 @@ tables: columns: - Status foreignKeys: - - name: FK_fhir_Slot_ScheduleReference + - name: FK_fhir_slot_ScheduleReference columns: - ScheduleReference - referencedTable: fhir_Schedule + referencedTable: fhir_schedule referencedColumns: - Id primaryKey: - name: PK_fhir_Slot + name: PK_fhir_slot columns: - Id -- name: fhir_Appointment +- name: fhir_appointment columns: - name: Id type: Text @@ -140,10 +140,10 @@ tables: columns: - PractitionerReference primaryKey: - name: PK_fhir_Appointment + name: PK_fhir_appointment columns: - Id -- name: sync_ScheduledPatient +- name: sync_scheduledpatient columns: - name: PatientId type: Text @@ -157,6 +157,6 @@ tables: type: Text defaultValue: CURRENT_TIMESTAMP primaryKey: - name: PK_sync_ScheduledPatient + name: PK_sync_scheduledpatient columns: - PatientId diff --git a/Scheduling/Scheduling.Sync/SchedulingSyncWorker.cs b/Scheduling/Scheduling.Sync/SchedulingSyncWorker.cs index b1220fb..6b349fb 100644 --- a/Scheduling/Scheduling.Sync/SchedulingSyncWorker.cs +++ b/Scheduling/Scheduling.Sync/SchedulingSyncWorker.cs @@ -133,7 +133,7 @@ await Task.Delay(TimeSpan.FromSeconds(retryDelay), stoppingToken) } /// <summary> - /// Fetches changes from Clinical domain and applies column mappings to sync_ScheduledPatient. + /// Fetches changes from Clinical domain and applies column mappings to sync_scheduledpatient. /// </summary> private async Task SyncPatientDataAsync(CancellationToken cancellationToken) { @@ -191,8 +191,8 @@ private async Task SyncPatientDataAsync(CancellationToken cancellationToken) } /// <summary> - /// Applies a change from Clinical domain to sync_ScheduledPatient with column mapping. - /// Maps: fhir_Patient -> sync_ScheduledPatient + /// Applies a change from Clinical domain to sync_scheduledpatient with column mapping. + /// Maps: fhir_patient -> sync_scheduledpatient /// Transforms: DisplayName = concat(GivenName, ' ', FamilyName) /// </summary> private void ApplyMappedChange(NpgsqlConnection connection, SyncChange change) @@ -230,11 +230,11 @@ private void ApplyMappedChange(NpgsqlConnection connection, SyncChange change) // Transform: DisplayName = concat(GivenName, ' ', FamilyName) var displayName = $"{givenName} {familyName}".Trim(); - // Upsert to sync_ScheduledPatient + // Upsert to sync_scheduledpatient if (change.Operation == SyncChange.Delete) { using var cmd = connection.CreateCommand(); - cmd.CommandText = "DELETE FROM sync_ScheduledPatient WHERE PatientId = @id"; + cmd.CommandText = "DELETE FROM sync_scheduledpatient WHERE \"PatientId\" = @id"; cmd.Parameters.AddWithValue("@id", patientId); cmd.ExecuteNonQuery(); @@ -244,13 +244,13 @@ private void ApplyMappedChange(NpgsqlConnection connection, SyncChange change) { using var cmd = connection.CreateCommand(); cmd.CommandText = """ - INSERT INTO sync_ScheduledPatient (PatientId, DisplayName, ContactPhone, ContactEmail, SyncedAt) + INSERT INTO sync_scheduledpatient ("PatientId", "DisplayName", "ContactPhone", "ContactEmail", "SyncedAt") VALUES (@id, @name, @phone, @email, NOW()) - ON CONFLICT (PatientId) DO UPDATE SET - DisplayName = excluded.DisplayName, - ContactPhone = excluded.ContactPhone, - ContactEmail = excluded.ContactEmail, - SyncedAt = NOW() + ON CONFLICT ("PatientId") DO UPDATE SET + "DisplayName" = excluded."DisplayName", + "ContactPhone" = excluded."ContactPhone", + "ContactEmail" = excluded."ContactEmail", + "SyncedAt" = NOW() """; cmd.Parameters.AddWithValue("@id", patientId); diff --git a/Scheduling/Scheduling.Sync/SyncMappings.json b/Scheduling/Scheduling.Sync/SyncMappings.json index 6bace33..69e7224 100644 --- a/Scheduling/Scheduling.Sync/SyncMappings.json +++ b/Scheduling/Scheduling.Sync/SyncMappings.json @@ -2,7 +2,7 @@ "mappings": [ { "source_table": "fhir_Patient", - "target_table": "sync_ScheduledPatient", + "target_table": "sync_scheduledpatient", "column_mappings": [ { "source": "Id", diff --git a/coverage-thresholds.json b/coverage-thresholds.json index aaa978c..2379e4f 100644 --- a/coverage-thresholds.json +++ b/coverage-thresholds.json @@ -11,13 +11,13 @@ "threshold": 85 }, "ICD10/ICD10.Api.Tests": { - "threshold": 76 + "threshold": 71 }, "ICD10/ICD10.Cli.Tests": { - "threshold": 72 + "threshold": 67 }, "Dashboard/Dashboard.Integration.Tests": { - "threshold": 58 + "threshold": 42 } } } From 9799864801b9e9865606de63ff668822d617fdb6 Mon Sep 17 00:00:00 2001 From: Christian Findlay <16697547+MelbourneDeveloper@users.noreply.github.com> Date: Fri, 10 Apr 2026 16:47:47 +1000 Subject: [PATCH 25/59] bump version --- Directory.Build.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Build.props b/Directory.Build.props index 212b30d..8c7bbfb 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -4,7 +4,7 @@ <NuGetAuditMode>disabled</NuGetAuditMode> <RestoreAuditProperties>false</RestoreAuditProperties> <!-- Single source of truth for every Nimblesite DataProvider / Lql / Sync / Migration package version. --> - <DataProviderVersion>0.9.5-beta</DataProviderVersion> + <DataProviderVersion>0.9.6-beta</DataProviderVersion> <Version>0.1.0</Version> <Authors>ChristianFindlay</Authors> <Company>MelbourneDeveloper</Company> From 6c0f553f281284b9af45c865cd652492f7def214 Mon Sep 17 00:00:00 2001 From: Christian Findlay <16697547+MelbourneDeveloper@users.noreply.github.com> Date: Fri, 10 Apr 2026 17:16:20 +1000 Subject: [PATCH 26/59] fix skill --- .claude/skills/ci-prep/SKILL.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.claude/skills/ci-prep/SKILL.md b/.claude/skills/ci-prep/SKILL.md index 82c46a3..370a8ed 100644 --- a/.claude/skills/ci-prep/SKILL.md +++ b/.claude/skills/ci-prep/SKILL.md @@ -67,6 +67,8 @@ For each command extracted from the CI workflow: ### Hard constraints +- **NEVER skip tests.** Run every single test. If tests need infrastructure, set it up first. +- **NEVER skip any CI step.** If CI runs it, you run it locally. - **NEVER modify test files** — fix the source code, not the tests - **NEVER add suppressions** (`#[allow(...)]`, `// eslint-disable`, `#pragma warning disable`) - **NEVER use `any` in TypeScript** to silence type errors @@ -93,11 +95,15 @@ Once all CI steps pass locally: ## Rules - **Always read the CI workflow first.** Never assume what commands CI runs. +- **NEVER skip tests.** Run ALL tests. If a test requires infrastructure (database, embedding service, browser), set up that infrastructure locally first. No exceptions. +- **NEVER skip any CI command** (`make test`, `make lint`, `make build`, etc.). Every command that CI runs, you run. +- The ONLY steps you may skip are GitHub Actions plumbing that has no local equivalent: `actions/checkout`, `actions/setup-dotnet`, `actions/upload-artifact`, and similar CI-runner setup actions. Everything else runs. +- If a CI step requires Docker services (databases, embedding services, etc.), start them locally before running the step. +- If a CI step requires browser installation (Playwright, Cypress, etc.), install the browsers locally before running the step. - Do not push if any step fails (unless `--failing` and all steps now pass) - Fix issues found in each step before moving to the next -- Never skip steps or suppress errors +- Never suppress errors - If the CI workflow has multiple jobs, run all of them (respecting dependency order) -- Skip steps that are CI-infrastructure-only (checkout, setup-node/python/rust actions, cache steps, artifact uploads) — focus on the actual build/test/lint commands ## Success criteria From 12dd458909b584ead6f48085ceeecb3c8e15d00e Mon Sep 17 00:00:00 2001 From: Christian Findlay <16697547+MelbourneDeveloper@users.noreply.github.com> Date: Sat, 11 Apr 2026 05:53:36 +1000 Subject: [PATCH 27/59] stuff --- CLAUDE.md | 12 ++-- Makefile | 86 +++----------------------- docker/README.md | 7 ++- readme.md | 155 ++++++++++++++++++++++------------------------- 4 files changed, 90 insertions(+), 170 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index cc4d404..73b81e8 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -120,17 +120,21 @@ Always include these 3 in the Directory.Build.props: All `make` targets work on Linux, macOS, and Windows. The Makefile uses OS detection to select portable commands. On Windows, install GNU Make via `choco install make` or use the one bundled with Git for Windows. ```bash +make start-docker # build dashboard + spin up the full stack via docker compose +make start-local # run all APIs locally against docker Postgres +make ci # lint + test + coverage-check + build (full CI simulation) make build # compile everything make test # run tests with coverage make lint # run all linters make fmt # format all code make fmt-check # check formatting (CI uses this) -make clean # remove build artifacts -make check # lint + test (pre-commit) -make ci # lint + test + build (full CI simulation) -make coverage # generate and open coverage report make coverage-check # assert coverage thresholds +make clean # remove build artifacts make setup # post-create dev environment setup +make db-up # start Postgres (pgvector) container +make db-down # stop Postgres container +make db-migrate # apply YAML schemas to all databases +make db-reset # destroy DB volume and recreate ``` ## Repo Structure diff --git a/Makefile b/Makefile index cf3a933..11e7ec9 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,10 @@ # agent-pmo:29b9dcf # ============================================================================= -# Standard Makefile — HealthcareSamples +# Makefile — HealthcareSamples # Cross-platform: Linux, macOS, Windows (via GNU Make) # ============================================================================= -.PHONY: build test lint fmt fmt-check clean check ci coverage coverage-check setup db-up db-down db-reset db-wait db-migrate kill-ports-local kill-ports-docker clean-local clean-docker start-local start-docker +.PHONY: build test lint fmt fmt-check clean ci coverage-check setup db-up db-down db-reset db-wait db-migrate start-local start-docker # ----------------------------------------------------------------------------- # OS Detection @@ -98,20 +98,8 @@ else $(RM) TestResults endif -## check: lint + test (pre-commit) -check: lint test - -## ci: lint + test + build (full CI simulation) -ci: lint test build - -## coverage: Generate coverage report -coverage: - @echo "==> Coverage report..." - reportgenerator \ - -reports:"TestResults/**/coverage.cobertura.xml" \ - -targetdir:coverage/html \ - -reporttypes:Html - @echo "==> HTML report: coverage/html/index.html" +## ci: lint + test + coverage-check + build (full CI simulation) +ci: lint test coverage-check build ## coverage-check: Assert per-project line-rate >= threshold from $(COVERAGE_THRESHOLDS_FILE) ## The JSON file declares { "default_threshold": N, "projects": { "<dir>": { "threshold": N } } }. @@ -206,49 +194,10 @@ db-migrate: db-up --output "$(PG_BASE_URL);Database=icd10" --provider postgres # ============================================================================= -# LOCAL DEV STACK +# RUN THE STACK # ============================================================================= -# Ports owned by the local dev stack (4 APIs + dashboard + embedding service) -LOCAL_PORTS := 5002 5080 5001 5090 5173 8000 -# Same as LOCAL_PORTS plus the Postgres host port (docker stack publishes it) -DOCKER_PORTS := 5432 5002 5080 5001 5090 5173 - -## kill-ports-local: Free ports used by the local dev stack -kill-ports-local: - @echo "==> Clearing local dev ports..." - @for port in $(LOCAL_PORTS); do \ - pids=$$(lsof -ti :$$port 2>/dev/null || true); \ - if [ -n "$$pids" ]; then \ - echo " killing port $$port: $$pids"; \ - echo "$$pids" | xargs kill -9 2>/dev/null || true; \ - fi; \ - done - -## kill-ports-docker: Free ports used by the docker stack (incl. Postgres) -kill-ports-docker: - @echo "==> Clearing docker dev ports..." - @for port in $(DOCKER_PORTS); do \ - pids=$$(lsof -ti :$$port 2>/dev/null || true); \ - if [ -n "$$pids" ]; then \ - echo " killing port $$port: $$pids"; \ - echo "$$pids" | xargs kill -9 2>/dev/null || true; \ - fi; \ - done - -## clean-local: Kill local dev processes and drop the Postgres dev volume -clean-local: kill-ports-local - @echo "==> Removing Postgres dev volume..." - docker compose -f $(DB_COMPOSE_FILE) down -v 2>/dev/null || true - @echo "Clean complete." - -## clean-docker: Kill docker stack and drop all docker-compose volumes -clean-docker: kill-ports-docker - @echo "==> Removing docker volumes..." - cd docker && docker compose down -v - @echo "Clean complete." - -## start-docker: Build the dashboard locally then start the docker compose stack +## start-docker: Build the dashboard locally then start the full docker compose stack ## Usage: make start-docker [BUILD=1] ## BUILD=1 force image rebuild (passes --build to docker compose up) start-docker: @@ -371,7 +320,7 @@ wait endef export START_LOCAL_RUNNER -## start-local: Run all 4 APIs locally against the docker postgres dev DB +## start-local: Run all APIs locally against the docker Postgres dev DB ## Builds projects in Debug, dashboard in Release, then runs everything in ## the foreground with prefixed log output. Ctrl+C cleans up all children. start-local: db-up @@ -385,24 +334,3 @@ start-local: db-up dotnet build ICD10/ICD10.Api/ICD10.Api.csproj --nologo -v q dotnet build Dashboard/Dashboard.Web/Dashboard.Web.csproj -c Release --nologo -v q @bash -c "$$START_LOCAL_RUNNER" - -# ============================================================================= -# HELP -# ============================================================================= -help: - @echo "Available targets:" - @echo " build - Compile/assemble all artifacts" - @echo " test - Run full test suite with coverage" - @echo " lint - Run all linters (errors mode)" - @echo " fmt - Format all code in-place" - @echo " fmt-check - Check formatting (no modification)" - @echo " clean - Remove build artifacts" - @echo " check - lint + test (pre-commit)" - @echo " ci - lint + test + build (full CI)" - @echo " coverage - Generate and open coverage report" - @echo " coverage-check - Assert coverage thresholds" - @echo " setup - Post-create dev environment setup" - @echo " start-local - Run all 4 APIs locally against docker postgres" - @echo " start-docker - Build dashboard + docker compose up the full stack" - @echo " clean-local - Kill local dev processes and drop postgres volume" - @echo " clean-docker - Kill docker stack and drop all volumes" diff --git a/docker/README.md b/docker/README.md index f6a27f4..03dfb3d 100644 --- a/docker/README.md +++ b/docker/README.md @@ -51,11 +51,12 @@ Then serve the static files however you want (nginx, python, etc). # Start everything make start-docker -# Fresh start (wipe databases) -make clean-docker start-docker - # Rebuild containers make start-docker BUILD=1 + +# Fresh start (wipe databases) +cd docker && docker compose down -v +make start-docker ``` ## Ports diff --git a/readme.md b/readme.md index d6c709c..278304a 100644 --- a/readme.md +++ b/readme.md @@ -1,47 +1,78 @@ -# Healthcare Samples +# HealthcareSamples -A complete demonstration of the DataProvider suite: three FHIR-compliant microservices with bidirectional sync, semantic search, and a React dashboard. +FHIR R5-compliant healthcare microservices built with the [DataProvider](https://github.com/MelbourneDeveloper/DataProvider) .NET toolkit. -This sample showcases: -- **DataProvider** - Compile-time safe SQL queries for all database operations -- **Sync Framework** - Bidirectional data synchronization between Clinical and Scheduling domains -- **LQL** - Lambda Query Language for complex queries -- **RAG Search** - Semantic medical code search with pgvector embeddings -- **FHIR Compliance** - - All medical data follows [FHIR R5 spec](https://build.fhir.org/resourcelist.html) - - Follows the FHIR [access control rules](https://build.fhir.org/security.html). +Four APIs (Clinical, Scheduling, ICD-10, Gatekeeper), bidirectional sync workers, semantic search via pgvector embeddings, and a React dashboard. ## Quick Start -```bash -# Run all APIs locally against Docker Postgres -make start-local +Prerequisites: [Docker](https://docs.docker.com/get-docker/), [.NET 10 SDK](https://dotnet.microsoft.com/download), [GNU Make](https://www.gnu.org/software/make/) -# Run everything in Docker containers +```bash make start-docker +``` + +That's it. Builds the dashboard, starts Postgres, migrates schemas, boots all APIs, serves the dashboard. Open http://localhost:5173. -# Force rebuild of the docker images +Force-rebuild containers: + +```bash make start-docker BUILD=1 ``` -| Service | URL | -|---------|-----| -| Clinical API | http://localhost:5080 | -| Scheduling API | http://localhost:5001 | -| ICD10 API | http://localhost:5090 | -| Dashboard | http://localhost:8080 | +Run APIs locally (faster rebuild cycle, Postgres still in Docker): + +```bash +make start-local +``` + +Ctrl+C stops everything. + +## Services + +| Service | Port | Description | +|---------|------|-------------| +| Dashboard | http://localhost:5173 | React UI (H5 transpiler C# to JS) | +| Clinical API | http://localhost:5080 | Patient, Encounter, Condition, MedicationRequest | +| Scheduling API | http://localhost:5001 | Practitioner, Appointment, Schedule, Slot | +| ICD-10 API | http://localhost:5090 | ICD-10/ACHI codes, semantic search via pgvector | +| Gatekeeper API | http://localhost:5002 | Passkey authentication, RBAC authorization | +| Postgres | localhost:5432 | pgvector-enabled, 4 databases | + +## Development + +```bash +make ci # full CI: lint + test + coverage-check + build +make test # run all tests with coverage +make lint # run all linters +make fmt # format all code +make build # compile everything (Release) +make clean # remove build artifacts +make setup # restore tools + packages (run once after clone) +``` + +### Database + +```bash +make db-up # start Postgres container +make db-down # stop Postgres container +make db-migrate # apply schemas to all databases +make db-reset # wipe and recreate databases from scratch +``` ## Architecture ``` Dashboard.Web (React/H5) + | + +--> Gatekeeper.Api (Passkey auth, RBAC) | +--> Clinical.Api <---- Clinical.Sync <-+ | (PostgreSQL) | - | fhir_Patient, fhir_Encounter | Practitioner->Provider + | fhir_Patient, fhir_Encounter | Practitioner -> Provider | | +--> Scheduling.Api <-- Scheduling.Sync <+ - | (PostgreSQL) Patient->ScheduledPatient + | (PostgreSQL) Patient -> ScheduledPatient | fhir_Practitioner, fhir_Appointment | +--> ICD10.Api @@ -49,13 +80,15 @@ Dashboard.Web (React/H5) icd10_code, achi_code, embeddings ``` +Clinical and Scheduling sync data bidirectionally. ICD-10 is a read-only reference database with semantic search powered by pgvector embeddings. + ## Data Ownership | Domain | Owns | Receives via Sync | |--------|------|-------------------| | Clinical | fhir_Patient, fhir_Encounter, fhir_Condition, fhir_MedicationRequest | sync_Provider | | Scheduling | fhir_Practitioner, fhir_Appointment, fhir_Schedule, fhir_Slot | sync_ScheduledPatient | -| ICD10 | icd10_chapter, icd10_block, icd10_category, icd10_code, achi_block, achi_code | N/A (read-only reference) | +| ICD10 | icd10_chapter, icd10_block, icd10_category, icd10_code, achi_block, achi_code | N/A (read-only) | ## API Endpoints @@ -77,77 +110,31 @@ Dashboard.Web (React/H5) ### ICD10 (`:5090`) - `GET /api/icd10/chapters` - ICD-10 chapters - `GET /api/icd10/chapters/{id}/blocks` - Blocks within chapter -- `GET /api/icd10/blocks/{id}/categories` - Categories within block -- `GET /api/icd10/categories/{id}/codes` - Codes within category -- `GET /api/icd10/codes/{code}` - Direct code lookup (supports `?format=fhir`) +- `GET /api/icd10/codes/{code}` - Direct code lookup (`?format=fhir`) - `GET /api/icd10/codes?q={query}&limit=20` - Text search - `GET /api/achi/blocks` - ACHI procedure blocks -- `GET /api/achi/codes/{code}` - ACHI code lookup - `GET /api/achi/codes?q={query}&limit=20` - ACHI text search - `POST /api/search` - RAG semantic search (requires embedding service) -- `GET /health` - Health check - -## Dashboard - -Serve static files and open http://localhost:8080: - -```bash -cd Dashboard/Dashboard.Web/wwwroot -python3 -m http.server 8080 -``` - -Built with H5 transpiler (C#->JavaScript) + React 18. -## Project Structure - -``` -Samples/ -+-- Makefile # All build/test/dev-stack targets (make help) -+-- Clinical/ -| +-- Clinical.Api/ # REST API (PostgreSQL) -| +-- Clinical.Api.Tests/ # E2E tests -| +-- Clinical.Sync/ # Pulls from Scheduling -+-- Scheduling/ -| +-- Scheduling.Api/ # REST API (PostgreSQL) -| +-- Scheduling.Api.Tests/ # E2E tests -| +-- Scheduling.Sync/ # Pulls from Clinical -+-- ICD10/ -| +-- ICD10.Api/ # REST API (PostgreSQL + pgvector) -| +-- ICD10.Api.Tests/ # E2E tests -| +-- ICD10.Cli/ # Interactive TUI client -| +-- ICD10.Cli.Tests/ # CLI E2E tests -| +-- embedding-service/ # Python FastAPI embedding service -| +-- scripts/ # DB import + embedding generation -+-- Dashboard/ - +-- Dashboard.Web/ # React UI (H5) -``` +### Gatekeeper (`:5002`) +- `POST /auth/register/begin` - Start passkey registration +- `POST /auth/register/complete` - Complete passkey registration +- `POST /auth/login/begin` - Start passkey login +- `POST /auth/login/complete` - Complete passkey login +- `GET /auth/session` - Current session info +- `GET /authz/check` - Permission check +- `POST /authz/evaluate` - Bulk permission evaluation ## Tech Stack -- .NET 9, ASP.NET Core Minimal API +- .NET 10, ASP.NET Core Minimal API - PostgreSQL with pgvector (semantic search) -- DataProvider (SQL->extension methods) +- DataProvider (compile-time safe SQL) - Sync Framework (bidirectional sync) - LQL (Lambda Query Language) -- MedEmbed (medical text embeddings) - H5 transpiler + React 18 +- Docker Compose -## Testing - -```bash -# Run all sample tests -dotnet test --filter "FullyQualifiedName~Samples" - -# ICD10 RAG search tests (requires embedding service) -cd ICD10/scripts/Dependencies && ./start.sh -dotnet test --filter "FullyQualifiedName~ICD10.Api.Tests" - -# Integration tests (requires APIs running) -dotnet test --filter "FullyQualifiedName~Dashboard.Integration.Tests" -``` - -## Learn More +## License -- [DataProvider Documentation](../DataProvider/README.md) -- [Sync Framework Documentation](../Sync/README.md) -- [LQL Documentation](../Lql/README.md) +MIT From 8752ee27b8ca6adb5b96b841b86227047acb0f29 Mon Sep 17 00:00:00 2001 From: Christian Findlay <16697547+MelbourneDeveloper@users.noreply.github.com> Date: Sat, 11 Apr 2026 06:11:21 +1000 Subject: [PATCH 28/59] Doco --- .github/workflows/ci.yml | 5 - CLAUDE.md | 221 ++++++++++++++------------------------- Makefile | 72 +++++-------- readme.md | 37 +++---- 4 files changed, 125 insertions(+), 210 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 37e8a80..a76ca1c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -74,11 +74,6 @@ jobs: - name: Test run: make test - # Per-project thresholds live in coverage-thresholds.json (default 80%). - # Bump entries by floor(measured) - 1 whenever real coverage improves. - - name: Coverage check - run: make coverage-check - - name: Upload coverage uses: actions/upload-artifact@v4 if: always() diff --git a/CLAUDE.md b/CLAUDE.md index 73b81e8..27bbbae 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,8 +1,8 @@ -# HealthcareSamples -- Agent Instructions +# Nimblesite Clinical Coding Platform -- Agent Instructions -⚠️ CRITICAL: **Reduce token usage.** Check file size before loading. Write less. Delete fluff and dead code. Alert user when context is loaded with pointless files. ⚠️ +⚠️ CRITICAL: **Reduce token usage.** Check file size before loading. Write less. Delete fluff and dead code. ⚠️ -⚠️ MIGRATING ANY DB WITH ANYTHING OTHER THAN Data Provider Migrations is COMPLETELY ILLEGAL ⚠️ +⚠️ MIGRATING ANY DB WITH ANYTHING OTHER THAN DataProvider Migrations is COMPLETELY ILLEGAL ⚠️ > Read this entire file before writing any code. > These rules are NON-NEGOTIABLE. Violations will be rejected in review. @@ -11,127 +11,79 @@ ## Project Overview -HealthcareSamples is a comprehensive demonstration of the DataProvider .NET toolkit. It contains three FHIR-compliant microservices (Clinical API, Scheduling API, ICD-10 API) with bidirectional sync workers, semantic search via pgvector embeddings, a React dashboard (H5 transpiler), and Docker configuration. All medical data follows the FHIR R5 specification. +Agentic clinical coding platform built on Nimblesite DataProvider. Four FHIR R5-compliant microservices (Clinical, Scheduling, ICD-10, Gatekeeper) with bidirectional sync, semantic search via pgvector embeddings, passkey auth, and a React dashboard (H5 transpiler). The ICD-10 RAG service is the foundation for AI-assisted clinical coding from patient encounters and notes. -**Primary language(s):** C# (.NET 10.0) -**Build command:** `make ci` -**Test command:** `make test` -**Lint command:** `make lint` +**Primary language:** C# (.NET 10.0) +**Build:** `make ci` | **Test:** `make test` | **Lint:** `make lint` -This repo depends on NuGet packages from MelbourneDeveloper/DataProvider with the `MelbourneDev.` prefix (e.g., MelbourneDev.DataProvider, MelbourneDev.Migration, MelbourneDev.Sync.Postgres, MelbourneDev.Lql.Postgres, MelbourneDev.Selecta). +NuGet packages use the `Nimblesite.` prefix (e.g., Nimblesite.DataProvider.Core, Nimblesite.Sync.Postgres, Nimblesite.Lql.Postgres). -## Too Many Cooks (Multi-Agent Coordination) +## Multi-Agent Coordination (TMC) If the TMC server is available: -1. Register immediately: descriptive name, intent, files you will touch -2. Before editing any file: lock it via TMC +1. Register immediately with descriptive name, intent, and files you will touch +2. Lock files via TMC before editing 3. Broadcast your plan before starting work -4. Check messages every few minutes -5. Release locks immediately when done -6. Never edit a locked file -- wait or find another approach - -## Hard Rules -- Universal (no exceptions) - -- **DO NOT use git commands.** No `git add`, `git commit`, `git push`, `git checkout`, `git merge`, `git rebase`, or any other git command. CI and GitHub Actions handle git. -- **ZERO DUPLICATION.** Before writing any code, search the codebase for existing implementations. Move code, don't copy it. -- **NO THROWING EXCEPTIONS.** Return `Result<T,E>`, `Option<T>`, or the language equivalent. Exceptions are only for unrecoverable bugs (panic-level). -- **NO REGEX on structured data.** Never parse JSON, YAML, TOML, code, or any structured format with regex. Use proper parsers, AST tools, or library functions. -- **NO PLACEHOLDERS.** If something isn't implemented, leave a loud compilation error with TODO. Never write code that silently does nothing. -- **Functions < 20 lines.** Refactor aggressively. If a function exceeds 20 lines, split it. -- **Files < 500 lines.** If a file exceeds 500 lines, extract modules. -- **100% test coverage is the goal.** Never delete or skip tests. Never remove assertions. -- **Prefer E2E/integration tests.** Unit tests are acceptable only for isolating problems. -- **Heavy logging everywhere.** See Logging Standards section below. -- **No suppressing linter warnings.** Fix the code, not the linter. -- **Pure functions** over statements -- **Every spec section MUST have a unique, hierarchical, non-numeric ID.** Format: `[GROUP-TOPIC]` or `[GROUP-TOPIC-DETAIL]` (e.g., `[AUTH-TOKEN-VERIFY]`, `[CI-TIMEOUT]`). The first word is the **group** -- all sections in the same group MUST be adjacent in the spec's TOC. NEVER use sequential numbers like `[SPEC-001]`. All code, tests, and design docs that implement or relate to a spec section MUST reference its ID in a comment (e.g., `// Implements [AUTH-TOKEN-VERIFY]`). This enables cross-referencing across specs, code, and tests -- grep `[AUTH-` to find every auth spec, its code, and its tests. - -## Logging Standards +4. Release locks immediately when done +5. Never edit a locked file -- **Use a structured logging library.** Never use `Console.WriteLine` or `Debug.WriteLine` for diagnostics. Use `Microsoft.Extensions.Logging`. -- **Log at entry/exit of all significant operations.** Use appropriate levels: `error`, `warn`, `info`, `debug`, `trace`. -- **Logging must be throughout the app.** Every service, handler, and non-trivial operation should log. Silent failures are forbidden. -- **SaaS / server apps:** Log to the database for persistence and queryability. Log calls that write to the database or file MUST be async or run on a background thread -- never block the request path with I/O logging. -- **NEVER log personal data.** No names, emails, addresses, phone numbers, IP addresses (unless required for security audit with explicit consent), or any PII. -- **NEVER log secrets.** No API keys, tokens, passwords, connection strings, or credentials. If you need to confirm a key is loaded, log a truncated hash or just `"API key: present"`. -- **Structured fields over string interpolation.** Log `{ "userId": 42, "action": "checkout" }` not `"User 42 performed checkout"`. This enables filtering and aggregation. +## Hard Rules -### Logging Libraries - -| Language | Library | Notes | -|----------|---------|-------| -| C# | `Microsoft.Extensions.Logging` | | +- **DO NOT use git commands.** CI and GitHub Actions handle git. +- **ZERO DUPLICATION.** Search the codebase before writing. Move code, don't copy it. +- **NO THROWING EXCEPTIONS.** Return `Result<T,E>` or `Option<T>`. Exceptions are only for unrecoverable bugs. +- **NO REGEX on structured data.** Use proper parsers. +- **NO PLACEHOLDERS.** Unimplemented code must leave a compilation error with TODO. +- **Functions < 20 lines. Files < 500 lines.** Refactor aggressively. +- **100% test coverage is the goal.** Never delete or skip tests. Never remove assertions. +- **Prefer E2E/integration tests.** Unit tests only for isolating problems. +- **No suppressing linter warnings.** Fix the code, not the linter. +- **Pure functions** over statements. +- **Spec section IDs** must be hierarchical and non-numeric: `[GROUP-TOPIC-DETAIL]` (e.g., `[AUTH-TOKEN-VERIFY]`). Code and tests reference these via comments. -## Hard Rules -- C# +## C# Rules -- No throwing exceptions -- return `Result<T,E>` or `Option<T>` -- No `!` null-forgiving operator -- No `as` casts -- use pattern matching -- No `dynamic` +- No `!` null-forgiving, no `as` casts (use pattern matching), no `dynamic` - Nullable reference types enabled everywhere -- Records for immutable data -- Install common packages in the build props -- Avoid classes. Use static methods as pure functions -- All tables must have a SINGLE primary key -- Primary keys MUST be UUIDs -- No in-memory dbs -- real dbs all the way -- No raw SQL inserts/updates -- use generated extensions -- Use DataProvider Migrations to spin up DBs -- SQL for creating db schema = ILLEGAL -- Use `ImmutableList`, `FrozenSet`, or `ImmutableArray` instead of `List<T>` -- All public members require XMLDOC (except in test projects) -- One type per file (except small records) -- No commented-out code -- delete it +- Records for immutable data. Avoid classes. Use static methods as pure functions. +- `ImmutableList`, `FrozenSet`, or `ImmutableArray` instead of `List<T>` +- All tables: single UUID primary key +- No in-memory DBs. No raw SQL inserts/updates -- use generated extensions. +- DB schemas via DataProvider Migrations only. SQL for schema creation = ILLEGAL. +- All public members require XMLDOC (except test projects) +- One type per file (except small records). No commented-out code. - Medical data must follow [FHIR R5 spec](https://build.fhir.org/resourcelist.html) +- Common packages go in Directory.Build.props -### Mandatory Packages (C# Only) - -Always include these 3 in the Directory.Build.props: -```xml -<ItemGroup> - <!-- Microsoft .NET Analyzers --> - <PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="9.0.0"> - <PrivateAssets>all</PrivateAssets> - <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> - </PackageReference> - - <!-- Result types for Railway Oriented Programming --> - <PackageReference Include="Outcome" Version="1.0.0" /> - - <!-- Exhaustive pattern matching analyzer --> - <PackageReference Include="Exhaustion" Version="1.0.0"> - <PrivateAssets>all</PrivateAssets> - <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> - </PackageReference> -</ItemGroup> -``` +## Logging -## Testing Rules +- `Microsoft.Extensions.Logging` only. Never `Console.WriteLine`. +- Log entry/exit of significant operations. Silent failures are forbidden. +- Structured fields over string interpolation. +- Never log PII or secrets. -- **Never delete a failing test.** Fix the code or fix the test expectation -- never delete. -- **Never skip a test** without a ticket number and expiry date in the skip reason. -- **Assertions must be specific.** `assert True` without a condition is illegal. -- **No try/catch in tests** that swallows the exception and asserts success. -- **Tests must be deterministic.** No sleep(), no relying on timing, no random state. -- **E2E tests: black-box only.** Only interact via public APIs, UI commands, or CLI. Never call internal methods or manipulate internal state from a test. -- **Never use Fluent Assertions.** +## Testing -## Build Commands (exact -- cross-platform via GNU Make) +- Never delete a failing test. Fix the code or the expectation. +- Never skip a test without a ticket number and expiry date. +- Assertions must be specific. No try/catch that swallows exceptions. +- Tests must be deterministic. No sleep(), no timing, no random state. +- E2E tests: black-box only via public APIs. Never use Fluent Assertions. -All `make` targets work on Linux, macOS, and Windows. The Makefile uses OS detection to select portable commands. On Windows, install GNU Make via `choco install make` or use the one bundled with Git for Windows. +## Make Targets ```bash -make start-docker # build dashboard + spin up the full stack via docker compose -make start-local # run all APIs locally against docker Postgres -make ci # lint + test + coverage-check + build (full CI simulation) +make start-docker # spin up the full stack via docker compose +make start-local # run APIs locally against docker Postgres +make ci # lint + test + build (test includes coverage enforcement) make build # compile everything -make test # run tests with coverage +make test # run tests with coverage (fails if below threshold) make lint # run all linters make fmt # format all code make fmt-check # check formatting (CI uses this) -make coverage-check # assert coverage thresholds make clean # remove build artifacts -make setup # post-create dev environment setup -make db-up # start Postgres (pgvector) container +make setup # restore tools + packages (first time) +make db-up # start Postgres container make db-down # stop Postgres container make db-migrate # apply YAML schemas to all databases make db-reset # destroy DB volume and recreate @@ -140,41 +92,33 @@ make db-reset # destroy DB volume and recreate ## Repo Structure ``` -HealthcareSamples/ -+-- .github/workflows/ # CI/CD pipelines -+-- .claude/skills/ # Claude Code skills -+-- Clinical/ -| +-- Clinical.Api/ # REST API (PostgreSQL) - FHIR Patient, Encounter, Condition, MedicationRequest -| +-- Clinical.Api.Tests/ # E2E tests -| +-- Clinical.Sync/ # Pulls Practitioner data from Scheduling -+-- Scheduling/ -| +-- Scheduling.Api/ # REST API (PostgreSQL) - FHIR Practitioner, Appointment, Schedule, Slot -| +-- Scheduling.Api.Tests/ # E2E tests -| +-- Scheduling.Sync/ # Pulls Patient data from Clinical -+-- ICD10/ -| +-- ICD10.Api/ # REST API (PostgreSQL + pgvector) - ICD-10 codes, ACHI codes, embeddings -| +-- ICD10.Api.Tests/ # E2E tests -| +-- ICD10.Cli/ # Interactive TUI client -| +-- ICD10.Cli.Tests/ # CLI E2E tests -| +-- embedding-service/ # Python FastAPI embedding service -| +-- scripts/ # DB import + embedding generation -+-- Dashboard/ -| +-- Dashboard.Web/ # React UI (H5 transpiler C#->JavaScript) -| +-- Dashboard.Integration.Tests/ # Integration tests -+-- Shared/ -| +-- Authorization/ # Shared authorization library -+-- docker/ # Docker compose and configuration -+-- scripts/ # Startup and cleanup scripts -+-- docs/ -| +-- specs/ # Specification documents -| +-- plans/ # Implementation plans with TODO checklists -+-- .gitignore -+-- CLAUDE.md # Agent instructions (this file) -+-- AGENTS.md # Pointer to CLAUDE.md -+-- Makefile -+-- HealthcareSamples.sln -+-- Directory.Build.props -+-- coverlet.runsettings +Clinical/ + Clinical.Api/ # FHIR Patient, Encounter, Condition, MedicationRequest + Clinical.Api.Tests/ + Clinical.Sync/ # Pulls Practitioner data from Scheduling +Scheduling/ + Scheduling.Api/ # FHIR Practitioner, Appointment, Schedule, Slot + Scheduling.Api.Tests/ + Scheduling.Sync/ # Pulls Patient data from Clinical +ICD10/ + ICD10.Api/ # ICD-10/ACHI codes, pgvector embeddings, RAG search + ICD10.Api.Tests/ + ICD10.Cli/ # Interactive TUI client + ICD10.Cli.Tests/ + embedding-service/ # Python FastAPI embedding service + scripts/ # DB import + embedding generation +Gatekeeper/ + Gatekeeper.Api/ # Passkey auth, RBAC authorization + Gatekeeper.Api.Tests/ +Dashboard/ + Dashboard.Web/ # React UI (H5 transpiler C# -> JS) + Dashboard.Integration.Tests/ +Shared/ + Authorization/ # Shared authorization library +docker/ # Docker compose and configuration +docs/ + specs/ # Specification documents + plans/ # Implementation plans ``` ## Data Ownership @@ -183,9 +127,4 @@ HealthcareSamples/ |--------|------|-------------------| | Clinical | fhir_Patient, fhir_Encounter, fhir_Condition, fhir_MedicationRequest | sync_Provider | | Scheduling | fhir_Practitioner, fhir_Appointment, fhir_Schedule, fhir_Slot | sync_ScheduledPatient | -| ICD10 | icd10_chapter, icd10_block, icd10_category, icd10_code, achi_block, achi_code | N/A (read-only reference) | - -## Claude Code Skills - -- [Claude Code Skills Overview](https://platform.claude.com/docs/en/agents-and-tools/agent-skills/overview) -- [The Complete Guide to Building Skills for Claude (PDF)](https://resources.anthropic.com/hubfs/The-Complete-Guide-to-Building-Skill-for-Claude.pdf) +| ICD10 | icd10_chapter, icd10_block, icd10_category, icd10_code, achi_block, achi_code | N/A (read-only) | diff --git a/Makefile b/Makefile index 11e7ec9..4523415 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ # Cross-platform: Linux, macOS, Windows (via GNU Make) # ============================================================================= -.PHONY: build test lint fmt fmt-check clean ci coverage-check setup db-up db-down db-reset db-wait db-migrate start-local start-docker +.PHONY: build test lint fmt fmt-check clean ci setup db-up db-down db-reset db-wait db-migrate start-local start-docker # ----------------------------------------------------------------------------- # OS Detection @@ -21,8 +21,8 @@ else endif # Per-project coverage thresholds live in this JSON file. Each test -# project gets its own minimum line-rate; bump them via `make coverage-check` -# output minus 1 percentage point (rounding margin). +# project gets its own minimum line-rate. `make test` enforces these after +# each project. Bump thresholds to floor(measured) - 1 when coverage increases. COVERAGE_THRESHOLDS_FILE ?= coverage-thresholds.json # Postgres dev database (docker compose). Override in CI via env vars. @@ -54,12 +54,17 @@ TEST_PROJECTS = \ ## test: Run full test suite with coverage (FAIL FAST) ## - Stops at the first failing test inside an assembly (xunit stopOnFail) ## - Stops at the first failing assembly across the suite (set -e) -## - Each project's coverage lands under TestResults/<project-dir>/ so -## `make coverage-check` can attribute results back to a project. +## - After each project, checks coverage against threshold from $(COVERAGE_THRESHOLDS_FILE) +## and fails immediately if below. test: db-migrate @echo "==> Testing (fail-fast)..." + @command -v jq >/dev/null 2>&1 || { echo "FAIL: jq is required (brew install jq / apt-get install jq)"; exit 1; } + @if [ ! -f "$(COVERAGE_THRESHOLDS_FILE)" ]; then \ + echo "FAIL: $(COVERAGE_THRESHOLDS_FILE) not found"; exit 1; \ + fi @set -e; \ rm -rf TestResults; \ + default=$$(jq -r '.default_threshold' $(COVERAGE_THRESHOLDS_FILE)); \ for proj in $(TEST_PROJECTS); do \ proj_dir=$$(dirname "$$proj"); \ echo ""; \ @@ -70,6 +75,20 @@ test: db-migrate --results-directory "TestResults/$$proj_dir" \ --verbosity normal \ || { echo ""; echo "FAIL: $$proj failed -- aborting remaining test projects"; exit 1; }; \ + cobertura=$$(find "TestResults/$$proj_dir" -name 'coverage.cobertura.xml' 2>/dev/null | head -1); \ + threshold=$$(jq -r --arg p "$$proj_dir" --arg d "$$default" '.projects[$$p].threshold // ($$d | tonumber)' $(COVERAGE_THRESHOLDS_FILE)); \ + if [ -z "$$cobertura" ]; then \ + echo "FAIL ($$proj_dir): no coverage.cobertura.xml"; exit 1; \ + fi; \ + line_rate=$$(awk 'match($$0, /line-rate="[0-9.]+"/) { s=substr($$0, RSTART+11, RLENGTH-12); print s; exit }' "$$cobertura"); \ + pct=$$(awk "BEGIN{printf \"%.1f\", $${line_rate:-0}*100}"); \ + pct_int=$$(awk "BEGIN{printf \"%d\", $${line_rate:-0}*100}"); \ + if [ "$$pct_int" -lt "$$threshold" ]; then \ + printf "FAIL %-44s %s%% < %s%%\n" "$$proj_dir" "$$pct" "$$threshold"; \ + exit 1; \ + else \ + printf "OK %-44s %s%% >= %s%%\n" "$$proj_dir" "$$pct" "$$threshold"; \ + fi; \ done ## lint: Run all linters (fails on any warning) @@ -98,47 +117,8 @@ else $(RM) TestResults endif -## ci: lint + test + coverage-check + build (full CI simulation) -ci: lint test coverage-check build - -## coverage-check: Assert per-project line-rate >= threshold from $(COVERAGE_THRESHOLDS_FILE) -## The JSON file declares { "default_threshold": N, "projects": { "<dir>": { "threshold": N } } }. -## A project that is missing from the file inherits "default_threshold". -## When coverage actually goes UP, edit the file: floor(measured) - 1 to leave a rounding cushion. -coverage-check: - @echo "==> Checking coverage thresholds (file: $(COVERAGE_THRESHOLDS_FILE))..." - @command -v jq >/dev/null 2>&1 || { echo "FAIL: jq is required (brew install jq / apt-get install jq)"; exit 1; } - @if [ ! -f "$(COVERAGE_THRESHOLDS_FILE)" ]; then \ - echo "FAIL: $(COVERAGE_THRESHOLDS_FILE) not found"; exit 1; \ - fi - @set -e; \ - default=$$(jq -r '.default_threshold' $(COVERAGE_THRESHOLDS_FILE)); \ - any_failed=0; \ - for proj in $(TEST_PROJECTS); do \ - proj_dir=$$(dirname "$$proj"); \ - cobertura=$$(find "TestResults/$$proj_dir" -name 'coverage.cobertura.xml' 2>/dev/null | head -1); \ - threshold=$$(jq -r --arg p "$$proj_dir" --arg d "$$default" '.projects[$$p].threshold // ($$d | tonumber)' $(COVERAGE_THRESHOLDS_FILE)); \ - if [ -z "$$cobertura" ]; then \ - echo "FAIL ($$proj_dir): no coverage.cobertura.xml under TestResults/$$proj_dir"; \ - any_failed=1; continue; \ - fi; \ - line_rate=$$(awk 'match($$0, /line-rate="[0-9.]+"/) { s=substr($$0, RSTART+11, RLENGTH-12); print s; exit }' "$$cobertura"); \ - pct=$$(awk "BEGIN{printf \"%.1f\", $${line_rate:-0}*100}"); \ - pct_int=$$(awk "BEGIN{printf \"%d\", $${line_rate:-0}*100}"); \ - if [ "$$pct_int" -lt "$$threshold" ]; then \ - printf "FAIL %-44s %s%% < %s%%\n" "$$proj_dir" "$$pct" "$$threshold"; \ - any_failed=1; \ - else \ - printf "OK %-44s %s%% >= %s%%\n" "$$proj_dir" "$$pct" "$$threshold"; \ - fi; \ - done; \ - if [ "$$any_failed" -ne 0 ]; then \ - echo ""; \ - echo "FAIL: one or more projects below threshold (see $(COVERAGE_THRESHOLDS_FILE))"; \ - exit 1; \ - fi; \ - echo ""; \ - echo "OK: all projects meet their coverage thresholds" +## ci: lint + test + build (full CI simulation -- test includes coverage checks) +ci: lint test build ## setup: Post-create dev environment setup setup: diff --git a/readme.md b/readme.md index c263481..0249206 100644 --- a/readme.md +++ b/readme.md @@ -90,22 +90,23 @@ make start-local ## Architecture -``` - Dashboard (React/H5) - | - +------------------+------------------+ - | | | - Gatekeeper.Api Clinical.Api Scheduling.Api - (Auth / RBAC) (PostgreSQL) (PostgreSQL) - | | - Clinical.Sync <----> Scheduling.Sync - (bidirectional data sync) - | - ICD10.Api - (PostgreSQL + pgvector) - | - Embedding Service - (semantic code matching) +```mermaid +graph TD + Dashboard["Dashboard<br/><sub>React / H5</sub>"] + + Dashboard --> Gatekeeper["Gatekeeper API<br/><sub>Passkey Auth · RBAC</sub>"] + Dashboard --> Clinical["Clinical API<br/><sub>Patient · Encounter · Condition</sub>"] + Dashboard --> Scheduling["Scheduling API<br/><sub>Practitioner · Appointment · Slot</sub>"] + Dashboard --> ICD10["ICD-10 API<br/><sub>Code Lookup · RAG Search</sub>"] + + Clinical <-->|"bidirectional sync"| Scheduling + + ICD10 --> Embedding["Embedding Service<br/><sub>Semantic Code Matching</sub>"] + + Clinical --> PG[("PostgreSQL<br/><sub>pgvector</sub>")] + Scheduling --> PG + ICD10 --> PG + Gatekeeper --> PG ``` **Clinical** and **Scheduling** sync data bidirectionally — practitioners flow into Clinical, patients flow into Scheduling. The **ICD-10 API** provides semantic search over medical codes, forming the backbone of the coding pipeline. @@ -121,8 +122,8 @@ make start-local ## Development ```bash -make ci # full CI: lint + test + coverage-check + build -make test # run all tests with coverage +make ci # full CI: lint + test + build +make test # run all tests (fails on coverage threshold violations) make lint # run all linters make fmt # format all code make build # compile everything (Release) From d903ca4a0a73f351819482b0f2b12dde494acf5e Mon Sep 17 00:00:00 2001 From: Christian Findlay <16697547+MelbourneDeveloper@users.noreply.github.com> Date: Sat, 11 Apr 2026 08:16:30 +1000 Subject: [PATCH 29/59] cleanup --- CLAUDE.md | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 27bbbae..973e2e5 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -2,8 +2,6 @@ ⚠️ CRITICAL: **Reduce token usage.** Check file size before loading. Write less. Delete fluff and dead code. ⚠️ -⚠️ MIGRATING ANY DB WITH ANYTHING OTHER THAN DataProvider Migrations is COMPLETELY ILLEGAL ⚠️ - > Read this entire file before writing any code. > These rules are NON-NEGOTIABLE. Violations will be rejected in review. @@ -18,18 +16,10 @@ Agentic clinical coding platform built on Nimblesite DataProvider. Four FHIR R5- NuGet packages use the `Nimblesite.` prefix (e.g., Nimblesite.DataProvider.Core, Nimblesite.Sync.Postgres, Nimblesite.Lql.Postgres). -## Multi-Agent Coordination (TMC) - -If the TMC server is available: -1. Register immediately with descriptive name, intent, and files you will touch -2. Lock files via TMC before editing -3. Broadcast your plan before starting work -4. Release locks immediately when done -5. Never edit a locked file - ## Hard Rules - **DO NOT use git commands.** CI and GitHub Actions handle git. +- **MIGRATING ANY DB WITH ANYTHING OTHER THAN DataProvider Migrations is COMPLETELY ILLEGAL** - **ZERO DUPLICATION.** Search the codebase before writing. Move code, don't copy it. - **NO THROWING EXCEPTIONS.** Return `Result<T,E>` or `Option<T>`. Exceptions are only for unrecoverable bugs. - **NO REGEX on structured data.** Use proper parsers. @@ -55,6 +45,15 @@ If the TMC server is available: - Medical data must follow [FHIR R5 spec](https://build.fhir.org/resourcelist.html) - Common packages go in Directory.Build.props +## Multi-Agent Coordination (TMC) + +If the TMC server is available: +1. Register immediately with descriptive name, intent, and files you will touch +2. Lock files via TMC before editing +3. Broadcast your plan before starting work +4. Release locks immediately when done +5. Never edit a locked file + ## Logging - `Microsoft.Extensions.Logging` only. Never `Console.WriteLine`. @@ -80,7 +79,6 @@ make build # compile everything make test # run tests with coverage (fails if below threshold) make lint # run all linters make fmt # format all code -make fmt-check # check formatting (CI uses this) make clean # remove build artifacts make setup # restore tools + packages (first time) make db-up # start Postgres container From 469b42345420829f1afa52ffc69f46e47517adc6 Mon Sep 17 00:00:00 2001 From: Christian Findlay <16697547+MelbourneDeveloper@users.noreply.github.com> Date: Sat, 11 Apr 2026 08:59:20 +1000 Subject: [PATCH 30/59] agent pmo --- .claude/skills/ci-prep/SKILL.md | 4 +- .claude/skills/code-dedup/SKILL.md | 4 +- .claude/skills/fix-bug/SKILL.md | 67 ++++++++++++++++++++++++ .claude/skills/spec-check/SKILL.md | 2 +- .claude/skills/submit-pr/SKILL.md | 2 +- .claude/skills/upgrade-packages/SKILL.md | 2 +- .claude/skills/website-audit/SKILL.md | 2 +- .clinerules/00-read-instructions.md | 2 +- .github/copilot-instructions.md | 2 +- .github/pull_request_template.md | 2 +- .github/workflows/ci.yml | 8 +-- .gitignore | 2 +- AGENTS.md | 2 +- CLAUDE.md | 4 +- Makefile | 15 +++--- coverage-thresholds.json | 1 + coverlet.runsettings | 2 +- opencode.json | 2 +- 18 files changed, 93 insertions(+), 32 deletions(-) create mode 100644 .claude/skills/fix-bug/SKILL.md diff --git a/.claude/skills/ci-prep/SKILL.md b/.claude/skills/ci-prep/SKILL.md index 370a8ed..8511ccb 100644 --- a/.claude/skills/ci-prep/SKILL.md +++ b/.claude/skills/ci-prep/SKILL.md @@ -3,7 +3,7 @@ name: ci-prep description: Prepares the current branch for CI by running the exact same steps locally and fixing issues. If CI is already failing, fetches the GH Actions logs first to diagnose. Use before pushing, when CI is red, or when the user says "fix ci". argument-hint: "[--failing] [optional job name to focus on]" --- -<!-- agent-pmo:29b9dcf --> +<!-- agent-pmo:80947ac --> # CI Prep @@ -44,7 +44,7 @@ Read **every line** of `--log-failed` output. For each failure note the exact fi 1. Find the CI workflow file. Look in `.github/workflows/` for `ci.yml`, `build.yml`, `test.yml`, `checks.yml`, `main.yml`, `pull_request.yml`, or any workflow triggered on `pull_request` or `push`. 2. Read the workflow file completely. Parse every job and every step. -3. Extract the ordered list of commands the CI actually runs (e.g., `make lint`, `make fmt-check`, `make test`, `make coverage-check`, `make build`, or whatever the workflow specifies — it may use `npm`, `cargo`, `dotnet`, raw shell commands, or anything else). +3. Extract the ordered list of commands the CI actually runs (e.g., `make lint`, `make test`, `make build`, or whatever the workflow specifies — it may use `npm`, `cargo`, `dotnet`, raw shell commands, or anything else). 4. Note any environment variables, matrix strategies, or conditional steps that affect execution. **Do NOT assume the steps are `make lint`, `make test`, `make coverage-check`, `make build`.** The actual CI may run different commands, in a different order, with different targets. Extract what the CI *actually does*. diff --git a/.claude/skills/code-dedup/SKILL.md b/.claude/skills/code-dedup/SKILL.md index 21f29ab..ad6ab7c 100644 --- a/.claude/skills/code-dedup/SKILL.md +++ b/.claude/skills/code-dedup/SKILL.md @@ -2,7 +2,7 @@ name: code-dedup description: Searches for duplicate code, duplicate tests, and dead code, then safely merges or removes them. Use when the user says "deduplicate", "find duplicates", "remove dead code", "DRY up", or "code dedup". Requires test coverage — refuses to touch untested code. --- -<!-- agent-pmo:29b9dcf --> +<!-- agent-pmo:80947ac --> # Code Dedup @@ -98,7 +98,7 @@ For each change, follow this cycle: **change → test → verify coverage → co 1. Run `make test` — all tests must still pass 2. Run `make coverage-check` — coverage must be >= the baseline from Step 1 -3. Run `make lint` and `make fmt-check` — code must be clean +3. Run `make lint` — code must be clean (includes format check) 4. Report: what was removed, what was merged, final coverage vs baseline ## Rules diff --git a/.claude/skills/fix-bug/SKILL.md b/.claude/skills/fix-bug/SKILL.md new file mode 100644 index 0000000..33fe728 --- /dev/null +++ b/.claude/skills/fix-bug/SKILL.md @@ -0,0 +1,67 @@ +--- +name: fix-bug +description: Fix a bug using test-driven development. Use when the user reports a bug, describes unexpected behavior, wants to fix a defect, or says something is broken. Enforces a strict test-first workflow where a failing test must be written and verified before any fix is attempted. +argument-hint: "[bug description]" +allowed-tools: Read, Grep, Glob, Edit, Write, Bash +--- +<!-- agent-pmo:80947ac --> + +# Bug Fix Skill — Test-First Workflow + +You MUST follow this exact workflow. Do NOT skip steps. Do NOT fix the bug before writing a failing test. + +## Step 1: Understand the Bug + +- Read the bug description: $ARGUMENTS +- Investigate the codebase to understand the relevant code +- Identify the root cause (or narrow down candidates) +- Summarize your understanding of the bug to the user before proceeding + +## Step 2: Write a Failing Test + +- Write a test that **directly exercises the buggy behavior** +- The test must assert the **correct/expected** behavior — so it FAILS against the current broken code +- The test name should clearly describe the bug (e.g., `test_orange_color_not_applied_to_head`) +- Use the project's existing test framework and conventions + +## Step 3: Run the Test — Confirm It FAILS + +- Run ONLY the new test (not the full suite) +- **Verify the test FAILS** and that it fails **because of the bug**, not for some other reason (typo, import error, wrong selector, etc.) +- If the test passes: your test does not capture the bug. Go back to Step 2 +- If the test fails for the wrong reason: fix the test, not the code. Go back to Step 2 +- **Repeat until the test fails specifically because of the bug** + +## Step 4: Show Failure to User + +- Show the user the test code and the failure output +- Explicitly ask: "This test fails because of the bug. Can you confirm this captures the issue before I fix it?" +- **STOP and WAIT for user acknowledgment before proceeding** +- Do NOT continue to Step 5 until the user confirms + +## Step 5: Fix the Bug + +- Make the **minimum change** needed to fix the bug +- Do not refactor, clean up, or "improve" surrounding code +- Do not change the test + +## Step 6: Run the Test — Confirm It PASSES + +- Run the new test again +- **Verify it PASSES** +- If it fails: go back to Step 5 and adjust the fix +- **Repeat until the test passes** + +## Step 7: Run the Full Test Suite + +- Run ALL tests to make sure nothing else broke +- If other tests fail: fix the regression without breaking the new test +- Report the final result to the user + +## Rules + +- NEVER fix the bug before the failing test is written and confirmed +- NEVER skip asking the user to acknowledge the test failure +- NEVER modify the test to make it pass — modify the source code +- If you cannot write a test for the bug, explain why and ask the user how to proceed +- Keep the fix minimal — one bug, one fix, one test diff --git a/.claude/skills/spec-check/SKILL.md b/.claude/skills/spec-check/SKILL.md index 683cfb7..1714cf3 100644 --- a/.claude/skills/spec-check/SKILL.md +++ b/.claude/skills/spec-check/SKILL.md @@ -3,7 +3,7 @@ name: spec-check description: Audit spec/plan documents against the codebase. Ensures every spec section has implementing code, tests, and matching logic. Use when the user says "check specs", "spec audit", or "verify specs". argument-hint: "[optional spec ID or filename filter]" --- -<!-- agent-pmo:29b9dcf --> +<!-- agent-pmo:80947ac --> # spec-check diff --git a/.claude/skills/submit-pr/SKILL.md b/.claude/skills/submit-pr/SKILL.md index 72526cc..c94f5d0 100644 --- a/.claude/skills/submit-pr/SKILL.md +++ b/.claude/skills/submit-pr/SKILL.md @@ -3,7 +3,7 @@ name: submit-pr description: Creates a pull request with a well-structured description after verifying CI passes. Use when the user asks to submit, create, or open a pull request. disable-model-invocation: true --- -<!-- agent-pmo:29b9dcf --> +<!-- agent-pmo:80947ac --> # Submit PR diff --git a/.claude/skills/upgrade-packages/SKILL.md b/.claude/skills/upgrade-packages/SKILL.md index b2eb963..7a2f8c7 100644 --- a/.claude/skills/upgrade-packages/SKILL.md +++ b/.claude/skills/upgrade-packages/SKILL.md @@ -3,7 +3,7 @@ name: upgrade-packages description: Upgrade all dependencies/packages to their latest versions for C#/.NET and Python. Use when the user says "upgrade packages", "update dependencies", "bump versions", "update packages", or "upgrade deps". argument-hint: "[--check-only] [--major] [package-name]" --- -<!-- agent-pmo:29b9dcf --> +<!-- agent-pmo:80947ac --> # Upgrade Packages diff --git a/.claude/skills/website-audit/SKILL.md b/.claude/skills/website-audit/SKILL.md index 5948cbf..5798782 100644 --- a/.claude/skills/website-audit/SKILL.md +++ b/.claude/skills/website-audit/SKILL.md @@ -2,7 +2,7 @@ name: website-audit description: Audits a website for SEO, AI search performance, structured data, mobile usability, broken links, and social media cards. Fixes issues found. Use when the user mentions "audit website", "SEO", "fix search ranking", "AI search", "structured data", "social media cards", or "website performance". --- -<!-- agent-pmo:29b9dcf --> +<!-- agent-pmo:80947ac --> # Website Audit diff --git a/.clinerules/00-read-instructions.md b/.clinerules/00-read-instructions.md index f0ce473..d548fec 100644 --- a/.clinerules/00-read-instructions.md +++ b/.clinerules/00-read-instructions.md @@ -1,4 +1,4 @@ -<!-- agent-pmo:29b9dcf --> +<!-- agent-pmo:80947ac --> # Single Source of Truth diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 7595149..0a1942d 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -1,4 +1,4 @@ -<!-- agent-pmo:29b9dcf --> +<!-- agent-pmo:80947ac --> @CLAUDE.md diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 135e75c..a9a61ae 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,4 +1,4 @@ -<!-- agent-pmo:29b9dcf --> +<!-- agent-pmo:80947ac --> ## TLDR <!-- One sentence: what does this PR do? --> diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a76ca1c..a011e7d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,4 +1,4 @@ -# agent-pmo:29b9dcf +# agent-pmo:80947ac name: CI on: @@ -15,6 +15,7 @@ jobs: ci: name: CI runs-on: ubuntu-latest + # TIMEOUT EXCEPTION: Postgres startup, DB migration, embedding service model load, Playwright install, and 6 test projects with coverage require ~20 min timeout-minutes: 30 env: DB_PASSWORD: changeme @@ -30,11 +31,6 @@ jobs: - run: dotnet restore - run: dotnet tool restore - # csharpier needs no DB -- run it first so format issues fail - # before paying the cost of docker, codegen, or Playwright. - - name: Format check - run: make fmt-check - - name: Start Postgres (pgvector) via docker compose run: make db-up diff --git a/.gitignore b/.gitignore index b1a18a9..48a121a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -# agent-pmo:29b9dcf +# agent-pmo:80947ac # ============================================================================= # UNIVERSAL diff --git a/AGENTS.md b/AGENTS.md index f0ce473..d548fec 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,4 +1,4 @@ -<!-- agent-pmo:29b9dcf --> +<!-- agent-pmo:80947ac --> # Single Source of Truth diff --git a/CLAUDE.md b/CLAUDE.md index 973e2e5..602f951 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -5,7 +5,7 @@ > Read this entire file before writing any code. > These rules are NON-NEGOTIABLE. Violations will be rejected in review. -<!-- agent-pmo:29b9dcf --> +<!-- agent-pmo:80947ac --> ## Project Overview @@ -77,7 +77,7 @@ make start-local # run APIs locally against docker Postgres make ci # lint + test + build (test includes coverage enforcement) make build # compile everything make test # run tests with coverage (fails if below threshold) -make lint # run all linters +make lint # check formatting + run all linters make fmt # format all code make clean # remove build artifacts make setup # restore tools + packages (first time) diff --git a/Makefile b/Makefile index 4523415..84bccb1 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,10 @@ -# agent-pmo:29b9dcf +# agent-pmo:80947ac # ============================================================================= # Makefile — HealthcareSamples # Cross-platform: Linux, macOS, Windows (via GNU Make) # ============================================================================= -.PHONY: build test lint fmt fmt-check clean ci setup db-up db-down db-reset db-wait db-migrate start-local start-docker +.PHONY: build test lint fmt clean ci setup db-up db-down db-reset db-wait db-migrate start-local start-docker # ----------------------------------------------------------------------------- # OS Detection @@ -91,8 +91,10 @@ test: db-migrate fi; \ done -## lint: Run all linters (fails on any warning) -lint: fmt-check db-migrate +## lint: Run all linters (fails on any warning). Format check runs FIRST. +lint: db-migrate + @echo "==> Checking format..." + dotnet csharpier check . @echo "==> Linting..." dotnet build HealthcareSamples.sln --configuration Release @@ -101,11 +103,6 @@ fmt: @echo "==> Formatting..." dotnet csharpier format . -## fmt-check: Check formatting without modifying -fmt-check: - @echo "==> Checking format..." - dotnet csharpier check . - ## clean: Remove all build artifacts clean: @echo "==> Cleaning..." diff --git a/coverage-thresholds.json b/coverage-thresholds.json index 2379e4f..833b593 100644 --- a/coverage-thresholds.json +++ b/coverage-thresholds.json @@ -1,4 +1,5 @@ { + "_agent_pmo": "80947ac", "default_threshold": 80, "projects": { "Gatekeeper/Gatekeeper.Api.Tests": { diff --git a/coverlet.runsettings b/coverlet.runsettings index e4a0779..a269f0a 100644 --- a/coverlet.runsettings +++ b/coverlet.runsettings @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" ?> -<!-- agent-pmo:29b9dcf --> +<!-- agent-pmo:80947ac --> <RunSettings> <DataCollectionRunSettings> <DataCollectors> diff --git a/opencode.json b/opencode.json index c881b86..2b96350 100644 --- a/opencode.json +++ b/opencode.json @@ -1,5 +1,5 @@ { - "_agent_pmo": "29b9dcf", + "_agent_pmo": "80947ac", "$schema": "https://opencode.ai/config.json", "instructions": ["CLAUDE.md"] } From d5d45fec88a286d8cb493fda156ccf7f6a818afa Mon Sep 17 00:00:00 2001 From: Christian Findlay <16697547+MelbourneDeveloper@users.noreply.github.com> Date: Sat, 11 Apr 2026 09:08:11 +1000 Subject: [PATCH 31/59] cleanup --- .claude/skills/ci-prep/SKILL.md | 16 +++++--------- .claude/skills/code-dedup/SKILL.md | 27 ++++++++++++------------ .claude/skills/fix-bug/SKILL.md | 3 +-- .claude/skills/spec-check/SKILL.md | 2 +- .claude/skills/submit-pr/SKILL.md | 4 +++- .claude/skills/upgrade-packages/SKILL.md | 2 +- .claude/skills/website-audit/SKILL.md | 2 +- .clinerules/00-read-instructions.md | 9 +------- .github/copilot-instructions.md | 2 +- .github/pull_request_template.md | 2 +- .github/workflows/ci.yml | 2 +- .gitignore | 2 +- AGENTS.md | 2 +- CLAUDE.md | 2 +- Makefile | 2 +- coverage-thresholds.json | 2 +- coverlet.runsettings | 2 +- opencode.json | 2 +- 18 files changed, 37 insertions(+), 48 deletions(-) diff --git a/.claude/skills/ci-prep/SKILL.md b/.claude/skills/ci-prep/SKILL.md index 8511ccb..dc6d46c 100644 --- a/.claude/skills/ci-prep/SKILL.md +++ b/.claude/skills/ci-prep/SKILL.md @@ -3,7 +3,7 @@ name: ci-prep description: Prepares the current branch for CI by running the exact same steps locally and fixing issues. If CI is already failing, fetches the GH Actions logs first to diagnose. Use before pushing, when CI is red, or when the user says "fix ci". argument-hint: "[--failing] [optional job name to focus on]" --- -<!-- agent-pmo:80947ac --> +<!-- agent-pmo:6647c8e --> # CI Prep @@ -44,10 +44,10 @@ Read **every line** of `--log-failed` output. For each failure note the exact fi 1. Find the CI workflow file. Look in `.github/workflows/` for `ci.yml`, `build.yml`, `test.yml`, `checks.yml`, `main.yml`, `pull_request.yml`, or any workflow triggered on `pull_request` or `push`. 2. Read the workflow file completely. Parse every job and every step. -3. Extract the ordered list of commands the CI actually runs (e.g., `make lint`, `make test`, `make build`, or whatever the workflow specifies — it may use `npm`, `cargo`, `dotnet`, raw shell commands, or anything else). +3. Extract the ordered list of commands the CI actually runs. In a spec-compliant repo this is `make lint → make test → make build` (REPO-STANDARDS-SPEC [MAKE-TARGETS]), but the actual CI may use `npm`, `cargo`, `dotnet`, raw shell commands, or anything else. Extract what is *actually there*. 4. Note any environment variables, matrix strategies, or conditional steps that affect execution. -**Do NOT assume the steps are `make lint`, `make test`, `make coverage-check`, `make build`.** The actual CI may run different commands, in a different order, with different targets. Extract what the CI *actually does*. +**Do NOT assume the steps are `make lint`, `make test`, `make build`.** The actual CI may run different commands, in a different order. Extract what the CI *actually does*. If you find extra targets beyond the 7 in [MAKE-TARGETS] (e.g. `make fmt-check`, `make coverage-check`), flag them in your final report — they should be consolidated by the agent-pmo skill. ## Step 3 — Run each CI step locally, in order @@ -67,8 +67,6 @@ For each command extracted from the CI workflow: ### Hard constraints -- **NEVER skip tests.** Run every single test. If tests need infrastructure, set it up first. -- **NEVER skip any CI step.** If CI runs it, you run it locally. - **NEVER modify test files** — fix the source code, not the tests - **NEVER add suppressions** (`#[allow(...)]`, `// eslint-disable`, `#pragma warning disable`) - **NEVER use `any` in TypeScript** to silence type errors @@ -95,15 +93,11 @@ Once all CI steps pass locally: ## Rules - **Always read the CI workflow first.** Never assume what commands CI runs. -- **NEVER skip tests.** Run ALL tests. If a test requires infrastructure (database, embedding service, browser), set up that infrastructure locally first. No exceptions. -- **NEVER skip any CI command** (`make test`, `make lint`, `make build`, etc.). Every command that CI runs, you run. -- The ONLY steps you may skip are GitHub Actions plumbing that has no local equivalent: `actions/checkout`, `actions/setup-dotnet`, `actions/upload-artifact`, and similar CI-runner setup actions. Everything else runs. -- If a CI step requires Docker services (databases, embedding services, etc.), start them locally before running the step. -- If a CI step requires browser installation (Playwright, Cypress, etc.), install the browsers locally before running the step. - Do not push if any step fails (unless `--failing` and all steps now pass) - Fix issues found in each step before moving to the next -- Never suppress errors +- Never skip steps or suppress errors - If the CI workflow has multiple jobs, run all of them (respecting dependency order) +- Skip steps that are CI-infrastructure-only (checkout, setup-node/python/rust actions, cache steps, artifact uploads) — focus on the actual build/test/lint commands ## Success criteria diff --git a/.claude/skills/code-dedup/SKILL.md b/.claude/skills/code-dedup/SKILL.md index ad6ab7c..765ddd6 100644 --- a/.claude/skills/code-dedup/SKILL.md +++ b/.claude/skills/code-dedup/SKILL.md @@ -2,7 +2,7 @@ name: code-dedup description: Searches for duplicate code, duplicate tests, and dead code, then safely merges or removes them. Use when the user says "deduplicate", "find duplicates", "remove dead code", "DRY up", or "code dedup". Requires test coverage — refuses to touch untested code. --- -<!-- agent-pmo:80947ac --> +<!-- agent-pmo:6647c8e --> # Code Dedup @@ -13,10 +13,10 @@ Carefully search for duplicate code, duplicate tests, and dead code across the r Before touching ANY code, verify these conditions. If any fail, stop and report why. 1. Run `make test` — all tests must pass. If tests fail, stop. Do not dedup a broken codebase. -2. Run `make coverage-check` — coverage must meet the repo's threshold. If it doesn't, stop. +2. Run `make test` — tests are fail-fast AND enforce the coverage threshold from `coverage-thresholds.json`. If anything fails, stop and fix it before deduping. 3. Verify the project uses **static typing**. Check for: - C#: typed by default — proceed - - Python: must have type annotations AND a type checker configured (pyright, mypy, or Basilisk in pyproject.toml / Makefile) — proceed + - Python: must have **Basilisk** configured as the primary type checker in `pyproject.toml [tool.basilisk]` (per REPO-STANDARDS-SPEC [LINT-PYTHON-BASILISK]). pyright is acceptable as a secondary check but Basilisk is the primary requirement. - **Untyped Python: STOP. Refuse to dedup.** Print: "This codebase has no static type checking. Deduplication without types is reckless — too high a risk of silent breakage. Add type checking first." ## Steps @@ -37,7 +37,7 @@ Dedup Progress: Before deciding what to touch, understand what is tested. -1. Run `make test` and `make coverage-check` to confirm green baseline +1. Run `make test` to confirm green baseline. `make test` is fail-fast AND enforces the coverage threshold from `coverage-thresholds.json` (REPO-STANDARDS-SPEC [TEST-RULES], [COVERAGE-THRESHOLDS-JSON]). It exits non-zero on any test failure OR coverage shortfall. 2. Note the current coverage percentage — this is the floor. It must not drop. 3. Identify which files/modules have coverage and which do not. Only files WITH coverage are candidates for dedup. @@ -78,28 +78,29 @@ For each change, follow this cycle: **change → test → verify coverage → co #### 5a. Remove dead code - Delete dead code identified in Step 2 -- After each deletion: run `make test` and `make coverage-check` -- If tests fail or coverage drops: **revert immediately** and investigate +- After each deletion: run `make test` (fail-fast + coverage + threshold all in one) +- If `make test` exits non-zero (test failure OR coverage drop): **revert immediately** and investigate - Dead code removal should never break tests or drop coverage #### 5b. Merge duplicate code - For each duplicate pair: extract the shared logic into a single function/module - Update all call sites to use the shared version -- After each merge: run `make test` and `make coverage-check` +- After each merge: run `make test` - If tests fail: **revert immediately**. The duplicates may have subtle differences you missed. - If coverage drops: the shared code must have equivalent test coverage. Add tests if needed before proceeding. #### 5c. Remove duplicate tests - Delete the redundant test (keep the more thorough one) -- After each deletion: run `make coverage-check` -- If coverage drops: **revert immediately**. The "duplicate" test was covering something the other wasn't. +- After each deletion: run `make test` +- If coverage drops below threshold, `make test` exits non-zero — **revert immediately**. The "duplicate" test was covering something the other wasn't. ### Step 6 — Final verification -1. Run `make test` — all tests must still pass -2. Run `make coverage-check` — coverage must be >= the baseline from Step 1 -3. Run `make lint` — code must be clean (includes format check) -4. Report: what was removed, what was merged, final coverage vs baseline +1. Run `make lint` — all linters and the format check must pass +2. Run `make test` — tests must pass AND coverage must remain ≥ the baseline from Step 1 +3. Report: what was removed, what was merged, final coverage vs baseline + +(Only the 7 standard targets exist — `make lint` and `make test` cover formatting and coverage checks respectively.) ## Rules diff --git a/.claude/skills/fix-bug/SKILL.md b/.claude/skills/fix-bug/SKILL.md index 33fe728..d318e4f 100644 --- a/.claude/skills/fix-bug/SKILL.md +++ b/.claude/skills/fix-bug/SKILL.md @@ -2,9 +2,8 @@ name: fix-bug description: Fix a bug using test-driven development. Use when the user reports a bug, describes unexpected behavior, wants to fix a defect, or says something is broken. Enforces a strict test-first workflow where a failing test must be written and verified before any fix is attempted. argument-hint: "[bug description]" -allowed-tools: Read, Grep, Glob, Edit, Write, Bash --- -<!-- agent-pmo:80947ac --> +<!-- agent-pmo:6647c8e --> # Bug Fix Skill — Test-First Workflow diff --git a/.claude/skills/spec-check/SKILL.md b/.claude/skills/spec-check/SKILL.md index 1714cf3..6a7dccb 100644 --- a/.claude/skills/spec-check/SKILL.md +++ b/.claude/skills/spec-check/SKILL.md @@ -3,7 +3,7 @@ name: spec-check description: Audit spec/plan documents against the codebase. Ensures every spec section has implementing code, tests, and matching logic. Use when the user says "check specs", "spec audit", or "verify specs". argument-hint: "[optional spec ID or filename filter]" --- -<!-- agent-pmo:80947ac --> +<!-- agent-pmo:6647c8e --> # spec-check diff --git a/.claude/skills/submit-pr/SKILL.md b/.claude/skills/submit-pr/SKILL.md index c94f5d0..791d223 100644 --- a/.claude/skills/submit-pr/SKILL.md +++ b/.claude/skills/submit-pr/SKILL.md @@ -3,7 +3,7 @@ name: submit-pr description: Creates a pull request with a well-structured description after verifying CI passes. Use when the user asks to submit, create, or open a pull request. disable-model-invocation: true --- -<!-- agent-pmo:80947ac --> +<!-- agent-pmo:6647c8e --> # Submit PR @@ -11,6 +11,8 @@ Create a pull request for the current branch with a well-structured description. ## Steps +*NOTE: if you already ran make ci in this session and it passed, you can skip step 1.* + 1. Run `make ci` — must pass completely before creating PR 2. **Generate the diff against main.** Run `git diff main...HEAD > /tmp/pr-diff.txt` to capture the full diff between the current branch and the head of main. This is the ONLY source of truth for what the PR contains. **Warning:** the diff can be very large. If the diff file exceeds context limits, process it in chunks (e.g., read sections with `head`/`tail` or split by file) rather than trying to load it all at once. 3. **Derive the PR title and description SOLELY from the diff.** Read the diff output and summarize what changed. Ignore commit messages, branch names, and any other metadata — only the actual code/content diff matters. diff --git a/.claude/skills/upgrade-packages/SKILL.md b/.claude/skills/upgrade-packages/SKILL.md index 7a2f8c7..f9e560f 100644 --- a/.claude/skills/upgrade-packages/SKILL.md +++ b/.claude/skills/upgrade-packages/SKILL.md @@ -3,7 +3,7 @@ name: upgrade-packages description: Upgrade all dependencies/packages to their latest versions for C#/.NET and Python. Use when the user says "upgrade packages", "update dependencies", "bump versions", "update packages", or "upgrade deps". argument-hint: "[--check-only] [--major] [package-name]" --- -<!-- agent-pmo:80947ac --> +<!-- agent-pmo:6647c8e --> # Upgrade Packages diff --git a/.claude/skills/website-audit/SKILL.md b/.claude/skills/website-audit/SKILL.md index 5798782..a156cd3 100644 --- a/.claude/skills/website-audit/SKILL.md +++ b/.claude/skills/website-audit/SKILL.md @@ -2,7 +2,7 @@ name: website-audit description: Audits a website for SEO, AI search performance, structured data, mobile usability, broken links, and social media cards. Fixes issues found. Use when the user mentions "audit website", "SEO", "fix search ranking", "AI search", "structured data", "social media cards", or "website performance". --- -<!-- agent-pmo:80947ac --> +<!-- agent-pmo:6647c8e --> # Website Audit diff --git a/.clinerules/00-read-instructions.md b/.clinerules/00-read-instructions.md index d548fec..7b74be7 100644 --- a/.clinerules/00-read-instructions.md +++ b/.clinerules/00-read-instructions.md @@ -1,10 +1,3 @@ -<!-- agent-pmo:80947ac --> - -# Single Source of Truth +<!-- agent-pmo:6647c8e --> @CLAUDE.md - -Read the file above in full before writing any code. All project rules, -coding standards, hard constraints, build commands, and architecture -notes live there. Do not add rules to this file -- keep everything in -`CLAUDE.md` so there is exactly one set of instructions to maintain. diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 0a1942d..2db674c 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -1,4 +1,4 @@ -<!-- agent-pmo:80947ac --> +<!-- agent-pmo:6647c8e --> @CLAUDE.md diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index a9a61ae..d678ddc 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,4 +1,4 @@ -<!-- agent-pmo:80947ac --> +<!-- agent-pmo:6647c8e --> ## TLDR <!-- One sentence: what does this PR do? --> diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a011e7d..52a6dc6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,4 +1,4 @@ -# agent-pmo:80947ac +# agent-pmo:6647c8e name: CI on: diff --git a/.gitignore b/.gitignore index 48a121a..ac68eb2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -# agent-pmo:80947ac +# agent-pmo:6647c8e # ============================================================================= # UNIVERSAL diff --git a/AGENTS.md b/AGENTS.md index d548fec..b12bc94 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,4 +1,4 @@ -<!-- agent-pmo:80947ac --> +<!-- agent-pmo:6647c8e --> # Single Source of Truth diff --git a/CLAUDE.md b/CLAUDE.md index 602f951..ff17207 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -5,7 +5,7 @@ > Read this entire file before writing any code. > These rules are NON-NEGOTIABLE. Violations will be rejected in review. -<!-- agent-pmo:80947ac --> +<!-- agent-pmo:6647c8e --> ## Project Overview diff --git a/Makefile b/Makefile index 84bccb1..29392e3 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -# agent-pmo:80947ac +# agent-pmo:6647c8e # ============================================================================= # Makefile — HealthcareSamples # Cross-platform: Linux, macOS, Windows (via GNU Make) diff --git a/coverage-thresholds.json b/coverage-thresholds.json index 833b593..1415a74 100644 --- a/coverage-thresholds.json +++ b/coverage-thresholds.json @@ -1,5 +1,5 @@ { - "_agent_pmo": "80947ac", + "_agent_pmo": "6647c8e", "default_threshold": 80, "projects": { "Gatekeeper/Gatekeeper.Api.Tests": { diff --git a/coverlet.runsettings b/coverlet.runsettings index a269f0a..aaf6f00 100644 --- a/coverlet.runsettings +++ b/coverlet.runsettings @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" ?> -<!-- agent-pmo:80947ac --> +<!-- agent-pmo:6647c8e --> <RunSettings> <DataCollectionRunSettings> <DataCollectors> diff --git a/opencode.json b/opencode.json index 2b96350..b5e046b 100644 --- a/opencode.json +++ b/opencode.json @@ -1,5 +1,5 @@ { - "_agent_pmo": "80947ac", + "_agent_pmo": "6647c8e", "$schema": "https://opencode.ai/config.json", "instructions": ["CLAUDE.md"] } From 8343ac5630cdb5aa4cccabbe6e6a6da358c07818 Mon Sep 17 00:00:00 2001 From: Christian Findlay <16697547+MelbourneDeveloper@users.noreply.github.com> Date: Sat, 11 Apr 2026 15:11:42 +1000 Subject: [PATCH 32/59] fix docker --- ICD10/scripts/CreateDb/import_postgres.py | 40 +++++++++--------- Makefile | 49 ++++++++++++++++++++--- docker/Dockerfile.app | 23 ++++++----- docker/Dockerfile.dashboard | 4 +- docker/docker-compose.yml | 8 ++-- docker/start-services.sh | 8 ++++ 6 files changed, 91 insertions(+), 41 deletions(-) diff --git a/ICD10/scripts/CreateDb/import_postgres.py b/ICD10/scripts/CreateDb/import_postgres.py index d697ba2..a1e82b2 100644 --- a/ICD10/scripts/CreateDb/import_postgres.py +++ b/ICD10/scripts/CreateDb/import_postgres.py @@ -401,9 +401,9 @@ def import_chapters(self, chapters: list[Chapter]): for c in chapters: cur.execute( """INSERT INTO icd10_chapter - (id, chapternumber, title, coderangestart, coderangeend, lastupdated, versionid) + ("Id", "ChapterNumber", "Title", "CodeRangeStart", "CodeRangeEnd", "LastUpdated", "VersionId") VALUES (%s,%s,%s,%s,%s,%s,%s) - ON CONFLICT (id) DO NOTHING""", + ON CONFLICT ("Id") DO NOTHING""", (c.id, c.chapter_number, c.title, c.code_range_start, c.code_range_end, get_timestamp(), 1), ) self.conn.commit() @@ -414,9 +414,9 @@ def import_blocks(self, blocks: list[Block]): for b in blocks: cur.execute( """INSERT INTO icd10_block - (id, chapterid, blockcode, title, coderangestart, coderangeend, lastupdated, versionid) + ("Id", "ChapterId", "BlockCode", "Title", "CodeRangeStart", "CodeRangeEnd", "LastUpdated", "VersionId") VALUES (%s,%s,%s,%s,%s,%s,%s,%s) - ON CONFLICT (id) DO NOTHING""", + ON CONFLICT ("Id") DO NOTHING""", (b.id, b.chapter_id, b.block_code, b.title, b.code_range_start, b.code_range_end, get_timestamp(), 1), ) self.conn.commit() @@ -427,9 +427,9 @@ def import_categories(self, categories: list[Category]): for c in categories: cur.execute( """INSERT INTO icd10_category - (id, blockid, categorycode, title, lastupdated, versionid) + ("Id", "BlockId", "CategoryCode", "Title", "LastUpdated", "VersionId") VALUES (%s,%s,%s,%s,%s,%s) - ON CONFLICT (id) DO NOTHING""", + ON CONFLICT ("Id") DO NOTHING""", (c.id, c.block_id, c.category_code, c.title, get_timestamp(), 1), ) self.conn.commit() @@ -448,11 +448,11 @@ def import_codes(self, codes: list[Code], synonyms: dict[str, list[str]]): cur.execute( """INSERT INTO icd10_code - (id, categoryid, code, shortdescription, longdescription, - inclusionterms, exclusionterms, codealso, codefirst, synonyms, - billable, effectivefrom, effectiveto, edition, lastupdated, versionid) + ("Id", "CategoryId", "Code", "ShortDescription", "LongDescription", + "InclusionTerms", "ExclusionTerms", "CodeAlso", "CodeFirst", "Synonyms", + "Billable", "EffectiveFrom", "EffectiveTo", "Edition", "LastUpdated", "VersionId") VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s) - ON CONFLICT (id) DO NOTHING""", + ON CONFLICT ("Id") DO NOTHING""", ( c.id, c.category_id if c.category_id else None, @@ -481,19 +481,19 @@ def import_achi_sample_data(self): for block_id, block_num, title, start, end in ACHI_SAMPLE_BLOCKS: cur.execute( """INSERT INTO achi_block - (id, blocknumber, title, coderangestart, coderangeend, lastupdated, versionid) + ("Id", "BlockNumber", "Title", "CodeRangeStart", "CodeRangeEnd", "LastUpdated", "VersionId") VALUES (%s,%s,%s,%s,%s,%s,%s) - ON CONFLICT (id) DO NOTHING""", + ON CONFLICT ("Id") DO NOTHING""", (block_id, block_num, title, start, end, get_timestamp(), 1), ) for code_id, block_id, code, short_desc, long_desc in ACHI_SAMPLE_CODES: cur.execute( """INSERT INTO achi_code - (id, blockid, code, shortdescription, longdescription, billable, - effectivefrom, effectiveto, edition, lastupdated, versionid) + ("Id", "BlockId", "Code", "ShortDescription", "LongDescription", "Billable", + "EffectiveFrom", "EffectiveTo", "Edition", "LastUpdated", "VersionId") VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s) - ON CONFLICT (id) DO NOTHING""", + ON CONFLICT ("Id") DO NOTHING""", (code_id, block_id, code, short_desc, long_desc, 1, "2024-07-01", "", "13", get_timestamp(), 1), ) @@ -507,10 +507,10 @@ def generate_embeddings(self, batch_size: int = 50): # Get all codes that don't have embeddings yet cur.execute(""" - SELECT c.id, c.code, c.shortdescription, c.longdescription + SELECT c."Id", c."Code", c."ShortDescription", c."LongDescription" FROM icd10_code c - LEFT JOIN icd10_code_embedding e ON c.id = e.codeid - WHERE e.id IS NULL + LEFT JOIN icd10_code_embedding e ON c."Id" = e."CodeId" + WHERE e."Id" IS NULL """) codes = cur.fetchall() logger.info(f"Found {len(codes)} codes needing embeddings") @@ -552,9 +552,9 @@ def generate_embeddings(self, batch_size: int = 50): embedding_json = json.dumps(embeddings[j]) cur.execute( """INSERT INTO icd10_code_embedding - (id, codeid, embedding, embeddingmodel, lastupdated) + ("Id", "CodeId", "Embedding", "EmbeddingModel", "LastUpdated") VALUES (%s, %s, %s, %s, %s) - ON CONFLICT (codeid) DO NOTHING""", + ON CONFLICT ("CodeId") DO NOTHING""", (generate_uuid(), code_id, embedding_json, "MedEmbed-Small-v0.1", get_timestamp()), ) total_generated += 1 diff --git a/Makefile b/Makefile index 29392e3..187a3a4 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ # Cross-platform: Linux, macOS, Windows (via GNU Make) # ============================================================================= -.PHONY: build test lint fmt clean ci setup db-up db-down db-reset db-wait db-migrate start-local start-docker +.PHONY: build test lint fmt clean ci setup db-up db-down db-reset db-wait db-migrate start-local start-docker nuke _reclaim-ports # ----------------------------------------------------------------------------- # OS Detection @@ -114,6 +114,22 @@ else $(RM) TestResults endif +## nuke: Absolute zero -- destroy both docker stacks, their volumes, their images, +## AND all local build artifacts. Next `make start-docker` rebuilds from scratch. +nuke: clean + @echo "==> NUKE: full docker stack + db-only stack + volumes + images" + -cd docker && docker compose down -v --rmi all --remove-orphans 2>/dev/null + -docker compose -f $(DB_COMPOSE_FILE) down -v --rmi all --remove-orphans 2>/dev/null + -docker rm -f $$(docker ps -aq --filter "name=healthcaresamples") 2>/dev/null + -docker rm -f $$(docker ps -aq --filter "name=docker-app") 2>/dev/null + -docker rm -f $$(docker ps -aq --filter "name=docker-dashboard") 2>/dev/null + -docker rm -f $$(docker ps -aq --filter "name=docker-db") 2>/dev/null + -docker volume rm -f docker_db-data 2>/dev/null + -docker volume rm -f healthcaresamples_db-data 2>/dev/null + -docker image rm -f docker-app docker-dashboard 2>/dev/null + $(RM) docker/dashboard-build + @echo "==> Nuked. Run 'make start-docker' for a cold start." + ## ci: lint + test + build (full CI simulation -- test includes coverage checks) ci: lint test build @@ -174,15 +190,36 @@ db-migrate: db-up # RUN THE STACK # ============================================================================= +# Ports the stack binds on the host. Used by _reclaim-ports to forcibly +# evict any stale containers or host processes holding them before we bring +# the compose stack up. +STACK_PORTS := 5002 5080 5001 5090 8000 5173 5432 + +## _reclaim-ports: Kill anything (docker containers or host procs) bound to STACK_PORTS +_reclaim-ports: + @echo "==> Reclaiming stack ports: $(STACK_PORTS)" + @for port in $(STACK_PORTS); do \ + cids=$$(docker ps -aq --filter "publish=$$port" 2>/dev/null); \ + if [ -n "$$cids" ]; then \ + echo " [:$$port] killing containers: $$cids"; \ + docker rm -f $$cids >/dev/null 2>&1 || true; \ + fi; \ + pids=$$(lsof -nP -iTCP:$$port -sTCP:LISTEN -t 2>/dev/null || true); \ + if [ -n "$$pids" ]; then \ + echo " [:$$port] killing host PIDs: $$pids"; \ + kill -9 $$pids 2>/dev/null || true; \ + fi; \ + done + ## start-docker: Build the dashboard locally then start the full docker compose stack -## Usage: make start-docker [BUILD=1] -## BUILD=1 force image rebuild (passes --build to docker compose up) -start-docker: +## Always rebuilds images so Dockerfile / start-services.sh changes can't be masked +## by a stale cached image. +start-docker: _reclaim-ports @echo "==> Building Dashboard locally (H5 requires native build)..." cd Dashboard/Dashboard.Web && \ dotnet publish -c Release -o ../../docker/dashboard-build --nologo -v q - @echo "==> Starting docker stack..." - cd docker && docker compose up $(if $(BUILD),--build,) + @echo "==> Starting docker stack (forced rebuild)..." + cd docker && docker compose up --build # Embedded runner for the local dev stack. Inlined as a `define` block so the # orchestration (background processes, trap-based cleanup, log prefixing) runs diff --git a/docker/Dockerfile.app b/docker/Dockerfile.app index 29c4862..7ce9acc 100644 --- a/docker/Dockerfile.app +++ b/docker/Dockerfile.app @@ -7,11 +7,11 @@ WORKDIR /src COPY . . RUN dotnet publish Gatekeeper/Gatekeeper.Api -c Release -o /app/gatekeeper -RUN dotnet publish Samples/Clinical/Clinical.Api -c Release -o /app/clinical-api -RUN dotnet publish Samples/Scheduling/Scheduling.Api -c Release -o /app/scheduling-api -RUN dotnet publish Samples/ICD10/ICD10.Api -c Release -o /app/icd10-api -RUN dotnet publish Samples/Clinical/Clinical.Sync -c Release -o /app/clinical-sync -RUN dotnet publish Samples/Scheduling/Scheduling.Sync -c Release -o /app/scheduling-sync +RUN dotnet publish Clinical/Clinical.Api -c Release -o /app/clinical-api +RUN dotnet publish Scheduling/Scheduling.Api -c Release -o /app/scheduling-api +RUN dotnet publish ICD10/ICD10.Api -c Release -o /app/icd10-api +RUN dotnet publish Clinical/Clinical.Sync -c Release -o /app/clinical-sync +RUN dotnet publish Scheduling/Scheduling.Sync -c Release -o /app/scheduling-sync # Runtime image FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS runtime @@ -36,11 +36,11 @@ COPY --from=build /app/clinical-sync ./clinical-sync COPY --from=build /app/scheduling-sync ./scheduling-sync # Copy embedding service -COPY Samples/ICD10/embedding-service/main.py ./embedding-service/main.py -COPY Samples/ICD10/embedding-service/requirements.txt ./embedding-service/requirements.txt +COPY ICD10/embedding-service/main.py ./embedding-service/main.py +COPY ICD10/embedding-service/requirements.txt ./embedding-service/requirements.txt # Copy ICD-10 import script -COPY Samples/ICD10/scripts/CreateDb/import_postgres.py ./import_icd10.py +COPY ICD10/scripts/CreateDb/import_postgres.py ./import_icd10.py # Install Python dependencies (embedding service + import script) RUN pip install --break-system-packages --no-cache-dir \ @@ -51,9 +51,14 @@ RUN pip install --break-system-packages --no-cache-dir \ RUN python3 -c "from sentence_transformers import SentenceTransformer; SentenceTransformer('abhinand/MedEmbed-small-v0.1')" # Copy entrypoint script -COPY Samples/docker/start-services.sh ./start-services.sh +COPY docker/start-services.sh ./start-services.sh RUN chmod +x ./start-services.sh +# Force HF libraries to use only the pre-downloaded cache (no network at runtime) +ENV HF_HUB_OFFLINE=1 \ + TRANSFORMERS_OFFLINE=1 \ + HF_HOME=/root/.cache/huggingface + EXPOSE 5002 5080 5001 5090 8000 ENTRYPOINT ["./start-services.sh"] diff --git a/docker/Dockerfile.dashboard b/docker/Dockerfile.dashboard index 84287c1..627540e 100644 --- a/docker/Dockerfile.dashboard +++ b/docker/Dockerfile.dashboard @@ -4,8 +4,8 @@ FROM nginx:alpine # Copy pre-built wwwroot from local build -COPY Samples/docker/dashboard-build/wwwroot /usr/share/nginx/html -COPY Samples/docker/nginx.conf /etc/nginx/nginx.conf +COPY docker/dashboard-build/wwwroot /usr/share/nginx/html +COPY docker/nginx.conf /etc/nginx/nginx.conf EXPOSE 80 diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index fbab56e..8b06110 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -17,8 +17,8 @@ services: app: build: - context: ../.. - dockerfile: Samples/docker/Dockerfile.app + context: .. + dockerfile: docker/Dockerfile.app environment: ConnectionStrings__Postgres: Host=db;Database=gatekeeper;Username=gatekeeper;Password=${DB_PASSWORD:-changeme} Jwt__SigningKey: ${JWT_SIGNING_KEY:-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=} @@ -47,8 +47,8 @@ services: dashboard: build: - context: ../.. - dockerfile: Samples/docker/Dockerfile.dashboard + context: .. + dockerfile: docker/Dockerfile.dashboard ports: - "5173:80" depends_on: diff --git a/docker/start-services.sh b/docker/start-services.sh index 93bca36..d3e7df3 100644 --- a/docker/start-services.sh +++ b/docker/start-services.sh @@ -1,6 +1,14 @@ #!/bin/bash set -e +# Force huggingface libraries to use only the model cache baked into the +# image. The container has no outbound network, so any HTTP call to +# huggingface.co fails with a DNS error. The model is pre-downloaded in the +# Dockerfile, so offline mode is safe. +export HF_HUB_OFFLINE=1 +export TRANSFORMERS_OFFLINE=1 +export HF_HOME=/root/.cache/huggingface + echo "Starting all services..." # Start embedding service first (needed by ICD10 API for AI search) From 1f370da8b27a86aa8e7862c6abecca4fc5fca9f1 Mon Sep 17 00:00:00 2001 From: Christian Findlay <16697547+MelbourneDeveloper@users.noreply.github.com> Date: Sat, 11 Apr 2026 15:18:48 +1000 Subject: [PATCH 33/59] fix fonts --- Dashboard/Dashboard.Web/wwwroot/css/base.css | 2 ++ Dashboard/Dashboard.Web/wwwroot/css/variables.css | 6 ++---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Dashboard/Dashboard.Web/wwwroot/css/base.css b/Dashboard/Dashboard.Web/wwwroot/css/base.css index dd0ecd4..6a44abb 100644 --- a/Dashboard/Dashboard.Web/wwwroot/css/base.css +++ b/Dashboard/Dashboard.Web/wwwroot/css/base.css @@ -5,9 +5,11 @@ box-sizing: border-box; margin: 0; padding: 0; + font-family: var(--font-family); } html { + font-family: var(--font-family); font-size: 16px; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; diff --git a/Dashboard/Dashboard.Web/wwwroot/css/variables.css b/Dashboard/Dashboard.Web/wwwroot/css/variables.css index fd6ca9c..0c0a7f9 100644 --- a/Dashboard/Dashboard.Web/wwwroot/css/variables.css +++ b/Dashboard/Dashboard.Web/wwwroot/css/variables.css @@ -1,8 +1,6 @@ /* Medical Dashboard Design System - Premium CSS Variables */ /* Inspired by Wellmetrix & CareIQ - Modern Healthcare Aesthetic */ -@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&display=swap'); - :root { /* === PRIMARY COLORS - Rich Blue Palette === */ --primary-blue-dark: #1e40af; @@ -131,8 +129,8 @@ --radius-3xl: 32px; --radius-full: 9999px; - /* === TYPOGRAPHY - Inter Font === */ - --font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; + /* === TYPOGRAPHY - System Font Stack === */ + --font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; --font-mono: 'SF Mono', 'Fira Code', 'JetBrains Mono', Consolas, monospace; --font-size-2xs: 0.625rem; /* 10px */ From 5522e0ed66b56440e035d59d81918843a121cd38 Mon Sep 17 00:00:00 2001 From: Christian Findlay <16697547+MelbourneDeveloper@users.noreply.github.com> Date: Sat, 11 Apr 2026 15:48:52 +1000 Subject: [PATCH 34/59] Dashboard fixes --- CLAUDE.md | 1 + .../AuthE2ETests.cs | 2 +- .../DashboardE2ETests.cs | 2 +- Dashboard/Dashboard.Web/App.cs | 2 +- Dashboard/Dashboard.Web/Program.cs | 2 +- Dashboard/Dashboard.Web/wwwroot/css/base.css | 475 +--- .../Dashboard.Web/wwwroot/css/components.css | 2178 +++-------------- .../Dashboard.Web/wwwroot/css/layout.css | 1460 ----------- .../Dashboard.Web/wwwroot/css/variables.css | 296 +-- .../Dashboard.Web/wwwroot/img/favicon.webp | Bin 0 -> 12432 bytes .../wwwroot/img/nimblesite-logo-white.webp | Bin 0 -> 1478 bytes .../wwwroot/img/nimblesite-logo.webp | Bin 0 -> 2358 bytes Dashboard/Dashboard.Web/wwwroot/index.html | 45 +- .../Dashboard.Web/wwwroot/js/Dashboard.js | 4 +- .../Dashboard.Web/wwwroot/js/Dashboard.min.js | 2 +- Makefile | 20 +- docker/.env.example | 2 +- docker/docker-compose.yml | 2 +- docs/designs/Design.png | Bin 0 -> 227247 bytes docs/designs/clinical-coding-search/code.html | 402 +++ .../designs/clinical-coding-search/screen.png | Bin 0 -> 365266 bytes docs/designs/dashboard/code.html | 396 +++ docs/designs/dashboard/screen.png | Bin 0 -> 405622 bytes docs/designs/design.md | 84 + 24 files changed, 1402 insertions(+), 3973 deletions(-) delete mode 100644 Dashboard/Dashboard.Web/wwwroot/css/layout.css create mode 100644 Dashboard/Dashboard.Web/wwwroot/img/favicon.webp create mode 100644 Dashboard/Dashboard.Web/wwwroot/img/nimblesite-logo-white.webp create mode 100644 Dashboard/Dashboard.Web/wwwroot/img/nimblesite-logo.webp create mode 100644 docs/designs/Design.png create mode 100644 docs/designs/clinical-coding-search/code.html create mode 100644 docs/designs/clinical-coding-search/screen.png create mode 100644 docs/designs/dashboard/code.html create mode 100644 docs/designs/dashboard/screen.png create mode 100644 docs/designs/design.md diff --git a/CLAUDE.md b/CLAUDE.md index ff17207..37eb9f0 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -19,6 +19,7 @@ NuGet packages use the `Nimblesite.` prefix (e.g., Nimblesite.DataProvider.Core, ## Hard Rules - **DO NOT use git commands.** CI and GitHub Actions handle git. +- **TOTALL CSS MUST < 1K LOC** - CSS is cancer and you are the cure for it - **MIGRATING ANY DB WITH ANYTHING OTHER THAN DataProvider Migrations is COMPLETELY ILLEGAL** - **ZERO DUPLICATION.** Search the codebase before writing. Move code, don't copy it. - **NO THROWING EXCEPTIONS.** Return `Result<T,E>` or `Option<T>`. Exceptions are only for unrecoverable bugs. diff --git a/Dashboard/Dashboard.Integration.Tests/AuthE2ETests.cs b/Dashboard/Dashboard.Integration.Tests/AuthE2ETests.cs index 84a5458..6e6707c 100644 --- a/Dashboard/Dashboard.Integration.Tests/AuthE2ETests.cs +++ b/Dashboard/Dashboard.Integration.Tests/AuthE2ETests.cs @@ -36,7 +36,7 @@ await page.WaitForSelectorAsync( ); var pageContent = await page.ContentAsync(); - Assert.Contains("Healthcare Dashboard", pageContent); + Assert.Contains("Nimblesite Clinical Coding Platform", pageContent); Assert.Contains("Sign in with your passkey", pageContent); var emailInputVisible = await page.IsVisibleAsync("input[type='email']"); diff --git a/Dashboard/Dashboard.Integration.Tests/DashboardE2ETests.cs b/Dashboard/Dashboard.Integration.Tests/DashboardE2ETests.cs index 718437d..14a1ae2 100644 --- a/Dashboard/Dashboard.Integration.Tests/DashboardE2ETests.cs +++ b/Dashboard/Dashboard.Integration.Tests/DashboardE2ETests.cs @@ -1541,7 +1541,7 @@ await page.WaitForSelectorAsync( // Verify login page is shown var pageContent = await page.ContentAsync(); - Assert.Contains("Healthcare Dashboard", pageContent); + Assert.Contains("Nimblesite Clinical Coding Platform", pageContent); Assert.Contains("Sign in with your passkey", pageContent); // CRITICAL: Login mode should NOT have email input field diff --git a/Dashboard/Dashboard.Web/App.cs b/Dashboard/Dashboard.Web/App.cs index 91a483d..56b67ad 100644 --- a/Dashboard/Dashboard.Web/App.cs +++ b/Dashboard/Dashboard.Web/App.cs @@ -147,7 +147,7 @@ private static string GetPageTitle(string view) return "Schedule"; if (view == "settings") return "Settings"; - return "Healthcare"; + return "Clinical Coding"; } private static ReactElement RenderPage(AppState state, System.Action<AppState> setState) diff --git a/Dashboard/Dashboard.Web/Program.cs b/Dashboard/Dashboard.Web/Program.cs index 933be85..8960020 100644 --- a/Dashboard/Dashboard.Web/Program.cs +++ b/Dashboard/Dashboard.Web/Program.cs @@ -35,7 +35,7 @@ public static void Main() ApiClient.SetTokens(authToken, authToken); // Log startup - Log("Healthcare Dashboard starting..."); + Log("Nimblesite Clinical Coding Platform starting..."); Log("Clinical API: " + clinicalUrl); Log("Scheduling API: " + schedulingUrl); Log("ICD-10 API: " + icd10Url); diff --git a/Dashboard/Dashboard.Web/wwwroot/css/base.css b/Dashboard/Dashboard.Web/wwwroot/css/base.css index 6a44abb..5bfc9e7 100644 --- a/Dashboard/Dashboard.Web/wwwroot/css/base.css +++ b/Dashboard/Dashboard.Web/wwwroot/css/base.css @@ -1,5 +1,4 @@ -/* Medical Dashboard - Premium Base Styles */ -/* Inspired by Wellmetrix & CareIQ Designs */ +/* Nimblesite Clinical Coding Platform — Base & Utilities */ *, *::before, *::after { box-sizing: border-box; @@ -14,86 +13,43 @@ html { -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-rendering: optimizeLegibility; - scroll-behavior: smooth; } body { font-family: var(--font-family); font-size: var(--font-size-base); - line-height: var(--line-height-normal); - color: var(--gray-900); - background: var(--gray-50); - background-image: var(--gradient-mesh); - background-attachment: fixed; + line-height: 1.5; + color: var(--on-surface); + background: var(--surface); min-height: 100vh; - overflow-x: hidden; } -/* Premium Background with Animated Mesh */ -body::before { - content: ''; - position: fixed; - top: 0; - left: 0; - right: 0; - bottom: 0; - background: - radial-gradient(ellipse 80% 50% at 20% -20%, rgba(59, 130, 246, 0.12), transparent), - radial-gradient(ellipse 60% 40% at 80% 10%, rgba(20, 184, 166, 0.1), transparent), - radial-gradient(ellipse 50% 50% at 10% 90%, rgba(139, 92, 246, 0.08), transparent); - pointer-events: none; - z-index: -1; -} - -/* Typography */ h1, h2, h3, h4, h5, h6 { - font-weight: var(--font-weight-semibold); - line-height: var(--line-height-tight); - color: var(--gray-900); - letter-spacing: var(--letter-spacing-tight); -} - -h1 { - font-size: var(--font-size-4xl); font-weight: var(--font-weight-bold); - letter-spacing: var(--letter-spacing-tighter); -} - -h2 { - font-size: var(--font-size-3xl); - font-weight: var(--font-weight-bold); -} - -h3 { - font-size: var(--font-size-2xl); -} - -h4 { - font-size: var(--font-size-xl); -} - -h5 { - font-size: var(--font-size-lg); + line-height: 1.15; + color: var(--on-surface); + letter-spacing: var(--letter-spacing-tight); } -h6 { - font-size: var(--font-size-md); - font-weight: var(--font-weight-medium); -} +h1 { font-size: var(--font-size-4xl); font-weight: var(--font-weight-extrabold); } +h2 { font-size: var(--font-size-3xl); } +h3 { font-size: var(--font-size-2xl); } +h4 { font-size: var(--font-size-xl); } +h5 { font-size: var(--font-size-lg); } +h6 { font-size: var(--font-size-md); font-weight: var(--font-weight-semibold); } p { - margin-bottom: var(--space-4); - color: var(--gray-600); + color: var(--on-surface-variant); } a { - color: var(--primary-blue); + color: var(--primary); text-decoration: none; transition: color var(--transition-fast); } a:hover { - color: var(--primary-blue-dark); + color: var(--primary-container); } strong, b { @@ -104,20 +60,17 @@ small { font-size: var(--font-size-sm); } -/* Focus states for accessibility */ :focus-visible { - outline: 2px solid var(--primary-blue); + outline: 2px solid var(--primary); outline-offset: 2px; border-radius: var(--radius-sm); } -/* Selection */ ::selection { - background: var(--primary-blue-light); - color: var(--white); + background: var(--primary-container); + color: var(--on-primary); } -/* Scrollbar styling - Refined */ ::-webkit-scrollbar { width: 10px; height: 10px; @@ -128,38 +81,32 @@ small { } ::-webkit-scrollbar-thumb { - background: var(--gray-300); + background: var(--outline-variant); border-radius: var(--radius-full); border: 2px solid transparent; background-clip: content-box; } ::-webkit-scrollbar-thumb:hover { - background: var(--gray-400); - border: 2px solid transparent; + background: var(--outline); background-clip: content-box; } -/* Firefox scrollbar */ * { scrollbar-width: thin; - scrollbar-color: var(--gray-300) transparent; + scrollbar-color: var(--outline-variant) transparent; } -/* Utility: screen reader only */ +/* === Utilities the React code actually uses === */ .sr-only { position: absolute; width: 1px; height: 1px; - padding: 0; - margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; - border: 0; } -/* Utility: truncate text */ .truncate { overflow: hidden; text-overflow: ellipsis; @@ -173,59 +120,32 @@ small { overflow: hidden; } -.line-clamp-3 { - display: -webkit-box; - -webkit-line-clamp: 3; - -webkit-box-orient: vertical; - overflow: hidden; -} - -/* Utility: flex layouts */ +/* Flex */ .flex { display: flex; } .inline-flex { display: inline-flex; } .flex-col { flex-direction: column; } -.flex-row { flex-direction: row; } -.flex-row-reverse { flex-direction: row-reverse; } .items-center { align-items: center; } .items-start { align-items: flex-start; } .items-end { align-items: flex-end; } -.items-stretch { align-items: stretch; } .justify-center { justify-content: center; } .justify-between { justify-content: space-between; } .justify-end { justify-content: flex-end; } -.justify-start { justify-content: flex-start; } -.gap-0 { gap: 0; } .gap-1 { gap: var(--space-1); } .gap-2 { gap: var(--space-2); } .gap-3 { gap: var(--space-3); } .gap-4 { gap: var(--space-4); } -.gap-5 { gap: var(--space-5); } .gap-6 { gap: var(--space-6); } .gap-8 { gap: var(--space-8); } -.gap-10 { gap: var(--space-10); } .flex-1 { flex: 1; } -.flex-auto { flex: auto; } -.flex-none { flex: none; } -.flex-wrap { flex-wrap: wrap; } -.flex-nowrap { flex-wrap: nowrap; } .flex-shrink-0 { flex-shrink: 0; } -.flex-grow { flex-grow: 1; } -/* Utility: grid layouts */ +/* Grid */ .grid { display: grid; } .grid-cols-1 { grid-template-columns: repeat(1, minmax(0, 1fr)); } .grid-cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); } .grid-cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); } .grid-cols-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); } -.grid-cols-5 { grid-template-columns: repeat(5, minmax(0, 1fr)); } -.grid-cols-6 { grid-template-columns: repeat(6, minmax(0, 1fr)); } -.col-span-2 { grid-column: span 2 / span 2; } -.col-span-3 { grid-column: span 3 / span 3; } -.col-span-full { grid-column: 1 / -1; } - -@media (min-width: 640px) { - .sm\:grid-cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); } -} +.grid-cols-7 { grid-template-columns: repeat(7, minmax(0, 1fr)); } @media (min-width: 768px) { .md\:grid-cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); } @@ -234,69 +154,28 @@ small { } @media (min-width: 1024px) { - .lg\:grid-cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); } .lg\:grid-cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); } .lg\:grid-cols-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); } - .lg\:grid-cols-5 { grid-template-columns: repeat(5, minmax(0, 1fr)); } -} - -@media (min-width: 1280px) { - .xl\:grid-cols-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); } - .xl\:grid-cols-5 { grid-template-columns: repeat(5, minmax(0, 1fr)); } - .xl\:grid-cols-6 { grid-template-columns: repeat(6, minmax(0, 1fr)); } } -/* Utility: spacing */ -.p-0 { padding: 0; } -.p-1 { padding: var(--space-1); } +/* Spacing */ .p-2 { padding: var(--space-2); } .p-3 { padding: var(--space-3); } .p-4 { padding: var(--space-4); } -.p-5 { padding: var(--space-5); } .p-6 { padding: var(--space-6); } .p-8 { padding: var(--space-8); } -.p-10 { padding: var(--space-10); } - -.px-2 { padding-left: var(--space-2); padding-right: var(--space-2); } -.px-3 { padding-left: var(--space-3); padding-right: var(--space-3); } -.px-4 { padding-left: var(--space-4); padding-right: var(--space-4); } -.px-5 { padding-left: var(--space-5); padding-right: var(--space-5); } -.px-6 { padding-left: var(--space-6); padding-right: var(--space-6); } -.px-8 { padding-left: var(--space-8); padding-right: var(--space-8); } - -.py-1 { padding-top: var(--space-1); padding-bottom: var(--space-1); } -.py-2 { padding-top: var(--space-2); padding-bottom: var(--space-2); } -.py-3 { padding-top: var(--space-3); padding-bottom: var(--space-3); } -.py-4 { padding-top: var(--space-4); padding-bottom: var(--space-4); } -.py-5 { padding-top: var(--space-5); padding-bottom: var(--space-5); } -.py-6 { padding-top: var(--space-6); padding-bottom: var(--space-6); } - -.m-0 { margin: 0; } -.m-auto { margin: auto; } -.mx-auto { margin-left: auto; margin-right: auto; } -.mb-0 { margin-bottom: 0; } -.mb-1 { margin-bottom: var(--space-1); } .mb-2 { margin-bottom: var(--space-2); } -.mb-3 { margin-bottom: var(--space-3); } .mb-4 { margin-bottom: var(--space-4); } -.mb-5 { margin-bottom: var(--space-5); } .mb-6 { margin-bottom: var(--space-6); } -.mb-8 { margin-bottom: var(--space-8); } - -.mt-0 { margin-top: 0; } -.mt-1 { margin-top: var(--space-1); } .mt-2 { margin-top: var(--space-2); } -.mt-3 { margin-top: var(--space-3); } .mt-4 { margin-top: var(--space-4); } -.mt-5 { margin-top: var(--space-5); } .mt-6 { margin-top: var(--space-6); } -.mt-8 { margin-top: var(--space-8); } - +.ml-4 { margin-left: var(--space-4); } +.mx-auto { margin-left: auto; margin-right: auto; } .ml-auto { margin-left: auto; } -.mr-auto { margin-right: auto; } -/* Utility: text */ +/* Text */ .text-2xs { font-size: var(--font-size-2xs); } .text-xs { font-size: var(--font-size-xs); } .text-sm { font-size: var(--font-size-sm); } @@ -306,10 +185,7 @@ small { .text-xl { font-size: var(--font-size-xl); } .text-2xl { font-size: var(--font-size-2xl); } .text-3xl { font-size: var(--font-size-3xl); } -.text-4xl { font-size: var(--font-size-4xl); } -.text-5xl { font-size: var(--font-size-5xl); } -.font-light { font-weight: var(--font-weight-light); } .font-normal { font-weight: var(--font-weight-normal); } .font-medium { font-weight: var(--font-weight-medium); } .font-semibold { font-weight: var(--font-weight-semibold); } @@ -317,264 +193,78 @@ small { .font-extrabold { font-weight: var(--font-weight-extrabold); } .text-center { text-align: center; } -.text-left { text-align: left; } .text-right { text-align: right; } - .uppercase { text-transform: uppercase; } -.lowercase { text-transform: lowercase; } -.capitalize { text-transform: capitalize; } - .tracking-tight { letter-spacing: var(--letter-spacing-tight); } -.tracking-wide { letter-spacing: var(--letter-spacing-wide); } -.tracking-wider { letter-spacing: var(--letter-spacing-wider); } - -.leading-none { line-height: var(--line-height-none); } -.leading-tight { line-height: var(--line-height-tight); } -.leading-normal { line-height: var(--line-height-normal); } -.leading-relaxed { line-height: var(--line-height-relaxed); } - -/* Text colors */ -.text-white { color: var(--white); } -.text-gray-400 { color: var(--gray-400); } -.text-gray-500 { color: var(--gray-500); } -.text-gray-600 { color: var(--gray-600); } -.text-gray-700 { color: var(--gray-700); } -.text-gray-800 { color: var(--gray-800); } -.text-gray-900 { color: var(--gray-900); } -.text-primary { color: var(--primary-blue); } -.text-primary-dark { color: var(--primary-blue-dark); } -.text-teal { color: var(--teal-bold); } +.tracking-wider { letter-spacing: var(--letter-spacing-wide); } + +.text-white { color: #ffffff; } +.text-gray-400 { color: var(--outline-variant); } +.text-gray-500 { color: var(--outline); } +.text-gray-600 { color: var(--on-surface-variant); } +.text-gray-700 { color: var(--on-surface-variant); } +.text-gray-900 { color: var(--on-surface); } +.text-primary { color: var(--primary); } .text-success { color: var(--success); } -.text-warning { color: var(--warning); } .text-error { color: var(--error); } -/* Utility: backgrounds */ -.bg-white { background-color: var(--white); } +/* Backgrounds */ +.bg-white { background-color: var(--surface-container-lowest); } .bg-transparent { background-color: transparent; } -.bg-gray-25 { background-color: var(--gray-25); } -.bg-gray-50 { background-color: var(--gray-50); } -.bg-gray-100 { background-color: var(--gray-100); } -.bg-gray-200 { background-color: var(--gray-200); } -.bg-primary { background-color: var(--primary-blue); } -.bg-primary-subtle { background-color: var(--primary-blue-subtle); } -.bg-primary-dark { background-color: var(--primary-blue-dark); } -.bg-teal { background-color: var(--teal-bold); } -.bg-teal-soft { background-color: var(--teal-soft); } -.bg-success { background-color: var(--success); } -.bg-success-light { background-color: var(--success-light); } -.bg-warning { background-color: var(--warning); } -.bg-warning-light { background-color: var(--warning-light); } -.bg-error { background-color: var(--error); } -.bg-error-light { background-color: var(--error-light); } - -/* Gradient backgrounds */ -.bg-gradient-primary { background: var(--gradient-primary); } -.bg-gradient-teal { background: var(--gradient-teal); } -.bg-gradient-warm { background: var(--gradient-warm); } -.bg-gradient-subtle { background: var(--gradient-subtle); } - -/* Utility: rounded corners */ -.rounded-none { border-radius: 0; } -.rounded-sm { border-radius: var(--radius-sm); } +.bg-gray-50 { background-color: var(--surface); } +.bg-gray-100 { background-color: var(--surface-container-low); } + +/* Radius */ .rounded { border-radius: var(--radius-md); } .rounded-md { border-radius: var(--radius-md); } .rounded-lg { border-radius: var(--radius-lg); } .rounded-xl { border-radius: var(--radius-xl); } -.rounded-2xl { border-radius: var(--radius-2xl); } -.rounded-3xl { border-radius: var(--radius-3xl); } .rounded-full { border-radius: var(--radius-full); } -/* Utility: shadows */ -.shadow-none { box-shadow: none; } -.shadow-xs { box-shadow: var(--shadow-xs); } +/* Shadows */ .shadow-sm { box-shadow: var(--shadow-sm); } .shadow { box-shadow: var(--shadow-md); } .shadow-md { box-shadow: var(--shadow-md); } .shadow-lg { box-shadow: var(--shadow-lg); } -.shadow-xl { box-shadow: var(--shadow-xl); } -.shadow-2xl { box-shadow: var(--shadow-2xl); } .shadow-card { box-shadow: var(--shadow-card); } -.shadow-floating { box-shadow: var(--shadow-floating); } - -/* Utility: borders */ -.border { border: 1px solid var(--border-color); } -.border-0 { border: none; } -.border-t { border-top: 1px solid var(--border-color); } -.border-b { border-bottom: 1px solid var(--border-color); } -.border-l { border-left: 1px solid var(--border-color); } -.border-r { border-right: 1px solid var(--border-color); } -.border-gray-100 { border-color: var(--gray-100); } -.border-gray-200 { border-color: var(--gray-200); } -.border-gray-300 { border-color: var(--gray-300); } -.border-transparent { border-color: transparent; } - -/* Utility: width/height */ + +/* Borders (only used at boundaries — no-line rule means tonal shifts elsewhere) */ +.border-b { border-bottom: 1px solid var(--outline-variant); } + +/* Sizing */ .w-full { width: 100%; } -.w-auto { width: auto; } -.w-fit { width: fit-content; } .h-full { height: 100%; } -.h-auto { height: auto; } -.h-screen { height: 100vh; } .min-h-screen { min-height: 100vh; } -.min-w-0 { min-width: 0; } -.max-w-full { max-width: 100%; } -/* Utility: positioning */ +/* Position */ .relative { position: relative; } .absolute { position: absolute; } .fixed { position: fixed; } -.sticky { position: sticky; } -.inset-0 { top: 0; right: 0; bottom: 0; left: 0; } -.top-0 { top: 0; } -.right-0 { right: 0; } -.bottom-0 { bottom: 0; } -.left-0 { left: 0; } - -/* Utility: display */ + +/* Display */ .hidden { display: none; } .block { display: block; } -.inline-block { display: inline-block; } -.inline { display: inline; } -/* Utility: overflow */ +/* Overflow */ .overflow-hidden { overflow: hidden; } .overflow-auto { overflow: auto; } -.overflow-x-auto { overflow-x: auto; } .overflow-y-auto { overflow-y: auto; } -.overflow-visible { overflow: visible; } - -/* Utility: opacity */ -.opacity-0 { opacity: 0; } -.opacity-50 { opacity: 0.5; } -.opacity-75 { opacity: 0.75; } -.opacity-100 { opacity: 1; } -/* Utility: visibility */ -.visible { visibility: visible; } -.invisible { visibility: hidden; } - -/* Utility: cursor */ +/* Cursor */ .cursor-pointer { cursor: pointer; } -.cursor-default { cursor: default; } -.cursor-not-allowed { cursor: not-allowed; } - -/* Utility: pointer events */ -.pointer-events-none { pointer-events: none; } -.pointer-events-auto { pointer-events: auto; } - -/* Utility: user select */ -.select-none { user-select: none; } -.select-text { user-select: text; } -.select-all { user-select: all; } - -/* Animation keyframes */ -@keyframes fadeIn { - from { opacity: 0; } - to { opacity: 1; } -} - -@keyframes fadeInUp { - from { - opacity: 0; - transform: translateY(16px); - } - to { - opacity: 1; - transform: translateY(0); - } -} - -@keyframes fadeInDown { - from { - opacity: 0; - transform: translateY(-16px); - } - to { - opacity: 1; - transform: translateY(0); - } -} - -@keyframes slideInRight { - from { - opacity: 0; - transform: translateX(-20px); - } - to { - opacity: 1; - transform: translateX(0); - } -} - -@keyframes scaleIn { - from { - opacity: 0; - transform: scale(0.95); - } - to { - opacity: 1; - transform: scale(1); - } -} -@keyframes pulse { - 0%, 100% { opacity: 1; } - 50% { opacity: 0.6; } -} - -@keyframes spin { - from { transform: rotate(0deg); } - to { transform: rotate(360deg); } -} - -@keyframes shimmer { - 0% { background-position: -200% 0; } - 100% { background-position: 200% 0; } -} - -@keyframes float { - 0%, 100% { transform: translateY(0); } - 50% { transform: translateY(-8px); } -} - -@keyframes glow { - 0%, 100% { box-shadow: 0 0 5px var(--primary-blue-glow); } - 50% { box-shadow: 0 0 20px var(--primary-blue-glow), 0 0 30px var(--primary-blue-glow); } -} +/* Animations */ +@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } +@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.6; } } +@keyframes spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } } .animate-fadeIn { animation: fadeIn var(--transition-normal) ease-out; } -.animate-fadeInUp { animation: fadeInUp var(--transition-slow) ease-out; } -.animate-fadeInDown { animation: fadeInDown var(--transition-slow) ease-out; } -.animate-slideInRight { animation: slideInRight var(--transition-slow) ease-out; } -.animate-scaleIn { animation: scaleIn var(--transition-normal) ease-out; } .animate-pulse { animation: pulse 2s ease-in-out infinite; } .animate-spin { animation: spin 1s linear infinite; } -.animate-shimmer { animation: shimmer 2s linear infinite; } -.animate-float { animation: float 3s ease-in-out infinite; } -/* Transition utilities */ -.transition-none { transition: none; } +/* Transitions */ .transition-all { transition: all var(--transition-normal); } -.transition-colors { transition: color var(--transition-fast), background-color var(--transition-fast), border-color var(--transition-fast); } -.transition-opacity { transition: opacity var(--transition-normal); } -.transition-transform { transition: transform var(--transition-normal); } -.transition-shadow { transition: box-shadow var(--transition-normal); } - -/* Transform utilities */ -.transform { transform: translateZ(0); } -.scale-95 { transform: scale(0.95); } -.scale-100 { transform: scale(1); } -.scale-105 { transform: scale(1.05); } -.-translate-y-1 { transform: translateY(-4px); } -.translate-y-0 { transform: translateY(0); } - -/* Hover utilities */ -.hover\:scale-102:hover { transform: scale(1.02); } -.hover\:scale-105:hover { transform: scale(1.05); } -.hover\:-translate-y-1:hover { transform: translateY(-4px); } -.hover\:shadow-lg:hover { box-shadow: var(--shadow-lg); } -.hover\:shadow-xl:hover { box-shadow: var(--shadow-xl); } -.hover\:shadow-card-hover:hover { box-shadow: var(--shadow-card-hover); } +.transition-colors { transition: color var(--transition-fast), background-color var(--transition-fast); } /* Icons */ .icon { @@ -591,48 +281,15 @@ small { .icon-md { width: 20px; height: 20px; } .icon-lg { width: 24px; height: 24px; } .icon-xl { width: 32px; height: 32px; } -.icon-2xl { width: 40px; height: 40px; } -.icon-3xl { width: 48px; height: 48px; } -/* Google Charts container styling */ +/* Charts */ .chart-container { width: 100%; min-height: 300px; position: relative; } -.chart-container-sm { - min-height: 200px; -} - -.chart-container-lg { - min-height: 400px; -} - -/* Responsive visibility */ -@media (max-width: 639px) { - .sm\:hidden { display: none; } -} - -@media (max-width: 767px) { - .md\:hidden { display: none; } -} - -@media (max-width: 1023px) { - .lg\:hidden { display: none; } -} - -@media (min-width: 640px) { - .hidden.sm\:block { display: block; } - .hidden.sm\:flex { display: flex; } -} - -@media (min-width: 768px) { - .hidden.md\:block { display: block; } - .hidden.md\:flex { display: flex; } -} - -@media (min-width: 1024px) { - .hidden.lg\:block { display: block; } - .hidden.lg\:flex { display: flex; } +.google-chart-container { + width: 100%; + min-height: 300px; } diff --git a/Dashboard/Dashboard.Web/wwwroot/css/components.css b/Dashboard/Dashboard.Web/wwwroot/css/components.css index a719b68..1b4858a 100644 --- a/Dashboard/Dashboard.Web/wwwroot/css/components.css +++ b/Dashboard/Dashboard.Web/wwwroot/css/components.css @@ -1,1890 +1,302 @@ -/* Medical Dashboard - Premium Component Styles */ -/* Inspired by Wellmetrix & CareIQ Designs */ - -/* === PREMIUM CARD - Glassmorphic === */ -.card { - position: relative; - background: var(--glass-bg-strong); - backdrop-filter: blur(var(--glass-blur)); - -webkit-backdrop-filter: blur(var(--glass-blur)); - border: 1px solid var(--glass-border); - border-radius: var(--radius-2xl); - padding: var(--space-6); - box-shadow: var(--shadow-card); - transition: all var(--transition-normal); - overflow: hidden; -} - -.card::before { - content: ''; - position: absolute; - top: 0; - left: 0; - right: 0; - height: 1px; - background: linear-gradient(90deg, transparent, rgba(255,255,255,0.8), transparent); - opacity: 0.6; -} - -.card:hover { - transform: translateY(-2px); - box-shadow: var(--shadow-card-hover); - border-color: rgba(255,255,255,0.6); -} - -.card-solid { - background: var(--white); - backdrop-filter: none; - border: 1px solid var(--gray-100); -} - -.card-elevated { - background: var(--white); - backdrop-filter: none; - box-shadow: var(--shadow-lg); -} - -.card-interactive { - cursor: pointer; -} - -.card-interactive:hover { - transform: translateY(-4px); -} - -.card-header { - display: flex; - align-items: center; - justify-content: space-between; - margin-bottom: var(--space-5); - padding-bottom: var(--space-4); - border-bottom: 1px solid var(--gray-100); -} - -.card-title { - font-size: var(--font-size-lg); - font-weight: var(--font-weight-semibold); - color: var(--gray-900); - margin: 0; - letter-spacing: var(--letter-spacing-tight); -} - -.card-subtitle { - font-size: var(--font-size-sm); - color: var(--gray-500); - margin-top: var(--space-1); -} - -.card-actions { - display: flex; - align-items: center; - gap: var(--space-2); -} - -.card-body { - flex: 1; -} - -.card-footer { - margin-top: var(--space-5); - padding-top: var(--space-4); - border-top: 1px solid var(--gray-100); -} - -/* === METRIC CARD - Premium Stats === */ -.metric-card { - position: relative; - background: var(--white); - border-radius: var(--radius-2xl); - padding: var(--space-6); - box-shadow: var(--shadow-card); - transition: all var(--transition-normal); - overflow: hidden; - min-height: var(--card-min-height); -} - -.metric-card::before { - content: ''; - position: absolute; - top: 0; - left: 0; - right: 0; - height: 4px; - background: var(--gradient-primary); - opacity: 0; - transition: opacity var(--transition-normal); -} - -.metric-card:hover { - transform: translateY(-4px); - box-shadow: var(--shadow-card-hover); -} - -.metric-card:hover::before { - opacity: 1; -} - -.metric-card.accent-blue::before { background: var(--gradient-primary); opacity: 1; } -.metric-card.accent-teal::before { background: var(--gradient-teal); opacity: 1; } -.metric-card.accent-warm::before { background: var(--gradient-warm); opacity: 1; } -.metric-card.accent-cool::before { background: var(--gradient-cool); opacity: 1; } - -.metric-header { - display: flex; - align-items: flex-start; - justify-content: space-between; - margin-bottom: var(--space-4); -} - -.metric-icon { - width: 52px; - height: 52px; - border-radius: var(--radius-xl); - display: flex; - align-items: center; - justify-content: center; - font-size: var(--font-size-2xl); - transition: transform var(--transition-normal); -} - -.metric-card:hover .metric-icon { - transform: scale(1.05); -} - -.metric-icon.blue { - background: linear-gradient(135deg, var(--primary-blue-subtle) 0%, rgba(59, 130, 246, 0.15) 100%); - color: var(--primary-blue); -} - -.metric-icon.teal { - background: linear-gradient(135deg, var(--teal-soft) 0%, rgba(20, 184, 166, 0.15) 100%); - color: var(--teal-dark); -} - -.metric-icon.success { - background: linear-gradient(135deg, var(--success-light) 0%, rgba(34, 197, 94, 0.15) 100%); - color: var(--success); -} - -.metric-icon.warning { - background: linear-gradient(135deg, var(--warning-light) 0%, rgba(245, 158, 11, 0.15) 100%); - color: var(--warning); -} - -.metric-icon.coral { - background: linear-gradient(135deg, var(--accent-coral-light) 0%, rgba(249, 115, 22, 0.15) 100%); - color: var(--accent-coral); -} - -.metric-icon.violet { - background: linear-gradient(135deg, var(--accent-violet-light) 0%, rgba(139, 92, 246, 0.15) 100%); - color: var(--accent-violet); -} - -.metric-content { - flex: 1; -} - -.metric-value { - font-size: var(--font-size-4xl); - font-weight: var(--font-weight-bold); - color: var(--gray-900); - line-height: var(--line-height-none); - letter-spacing: var(--letter-spacing-tight); - margin-bottom: var(--space-1); -} - -.metric-value-sm { - font-size: var(--font-size-3xl); -} - -.metric-label { - font-size: var(--font-size-sm); - color: var(--gray-500); - font-weight: var(--font-weight-medium); - margin-bottom: var(--space-3); -} - -.metric-trend { - display: inline-flex; - align-items: center; - gap: var(--space-1); - font-size: var(--font-size-sm); - font-weight: var(--font-weight-semibold); - padding: var(--space-1) var(--space-2); - border-radius: var(--radius-full); -} - -.metric-trend.up { - color: var(--success); - background: var(--success-light); -} - -.metric-trend.down { - color: var(--error); - background: var(--error-light); -} - -.metric-trend.neutral { - color: var(--gray-500); - background: var(--gray-100); -} - -.metric-mini-chart { - height: 40px; - margin-top: var(--space-3); -} - -/* === STAT CARD - Compact Version === */ -.stat-card { - display: flex; - align-items: center; - gap: var(--space-4); - background: var(--white); - border-radius: var(--radius-xl); - padding: var(--space-4) var(--space-5); - box-shadow: var(--shadow-sm); - transition: all var(--transition-normal); -} - -.stat-card:hover { - box-shadow: var(--shadow-md); - transform: translateY(-2px); -} - -.stat-icon { - width: 44px; - height: 44px; - border-radius: var(--radius-lg); - display: flex; - align-items: center; - justify-content: center; - flex-shrink: 0; -} - -.stat-content { - flex: 1; - min-width: 0; -} - -.stat-value { - font-size: var(--font-size-2xl); - font-weight: var(--font-weight-bold); - color: var(--gray-900); - line-height: var(--line-height-tight); -} - -.stat-label { - font-size: var(--font-size-sm); - color: var(--gray-500); -} - -/* === BUTTONS - Premium Style === */ -.btn { - display: inline-flex; - align-items: center; - justify-content: center; - gap: var(--space-2); - padding: var(--space-2-5) var(--space-5); - font-family: inherit; - font-size: var(--font-size-base); - font-weight: var(--font-weight-medium); - line-height: var(--line-height-tight); - border: none; - border-radius: var(--radius-lg); - cursor: pointer; - transition: all var(--transition-fast); - white-space: nowrap; - text-decoration: none; -} - -.btn:focus-visible { - outline: 2px solid var(--primary-blue); - outline-offset: 2px; -} - -.btn:disabled { - opacity: 0.5; - cursor: not-allowed; - transform: none !important; -} - -.btn-primary { - background: var(--gradient-primary); - color: var(--white); - box-shadow: 0 2px 8px rgba(59, 130, 246, 0.3); -} - -.btn-primary:hover:not(:disabled) { - transform: translateY(-1px); - box-shadow: 0 4px 12px rgba(59, 130, 246, 0.4); -} - -.btn-primary:active:not(:disabled) { - transform: translateY(0); -} - -.btn-secondary { - background: var(--gray-100); - color: var(--gray-700); -} - -.btn-secondary:hover:not(:disabled) { - background: var(--gray-200); -} - -.btn-outline { - background: transparent; - border: 1px solid var(--gray-300); - color: var(--gray-700); -} - -.btn-outline:hover:not(:disabled) { - background: var(--gray-50); - border-color: var(--gray-400); -} - -.btn-ghost { - background: transparent; - color: var(--gray-600); -} - -.btn-ghost:hover:not(:disabled) { - background: var(--gray-100); - color: var(--gray-900); -} - -.btn-danger { - background: var(--gradient-warm); - color: var(--white); - box-shadow: 0 2px 8px rgba(239, 68, 68, 0.3); -} - -.btn-danger:hover:not(:disabled) { - transform: translateY(-1px); - box-shadow: 0 4px 12px rgba(239, 68, 68, 0.4); -} - -.btn-success { - background: var(--gradient-teal); - color: var(--white); - box-shadow: 0 2px 8px rgba(20, 184, 166, 0.3); -} - -.btn-success:hover:not(:disabled) { - transform: translateY(-1px); - box-shadow: 0 4px 12px rgba(20, 184, 166, 0.4); -} - -.btn-white { - background: var(--white); - color: var(--gray-700); - box-shadow: var(--shadow-sm); -} - -.btn-white:hover:not(:disabled) { - box-shadow: var(--shadow-md); -} - -.btn-xs { padding: var(--space-1) var(--space-2); font-size: var(--font-size-xs); border-radius: var(--radius-md); } -.btn-sm { padding: var(--space-1-5) var(--space-3); font-size: var(--font-size-sm); } -.btn-lg { padding: var(--space-3) var(--space-6); font-size: var(--font-size-md); } -.btn-xl { padding: var(--space-4) var(--space-8); font-size: var(--font-size-lg); border-radius: var(--radius-xl); } - -.btn-icon { - padding: var(--space-2); - width: 40px; - height: 40px; -} - -.btn-icon.btn-sm { - width: 32px; - height: 32px; - padding: var(--space-1-5); -} - -.btn-icon.btn-lg { - width: 48px; - height: 48px; - padding: var(--space-3); -} - -/* Button Group */ -.btn-group { - display: inline-flex; - border-radius: var(--radius-lg); - overflow: hidden; - box-shadow: var(--shadow-sm); -} - -.btn-group .btn { - border-radius: 0; - border-right: 1px solid rgba(0,0,0,0.1); -} - -.btn-group .btn:last-child { - border-right: none; -} - -/* === INPUTS - Modern Style === */ -.input { - width: 100%; - padding: var(--space-3) var(--space-4); - font-family: inherit; - font-size: var(--font-size-base); - line-height: var(--line-height-tight); - color: var(--gray-900); - background: var(--white); - border: 1px solid var(--gray-200); - border-radius: var(--radius-lg); - transition: all var(--transition-fast); -} - -.input:focus { - outline: none; - border-color: var(--primary-blue); - box-shadow: 0 0 0 4px var(--primary-blue-glow); -} - -.input:disabled { - background: var(--gray-50); - color: var(--gray-400); - cursor: not-allowed; -} - -.input::placeholder { - color: var(--gray-400); -} - -.input-error { - border-color: var(--error); -} - -.input-error:focus { - box-shadow: 0 0 0 4px rgba(239, 68, 68, 0.15); -} - -.input-success { - border-color: var(--success); -} - -.input-success:focus { - box-shadow: 0 0 0 4px rgba(34, 197, 94, 0.15); -} - -.input-sm { - padding: var(--space-2) var(--space-3); - font-size: var(--font-size-sm); -} - -.input-lg { - padding: var(--space-4) var(--space-5); - font-size: var(--font-size-md); -} - -.input-group { - display: flex; - flex-direction: column; - gap: var(--space-2); -} - -.input-label { - font-size: var(--font-size-sm); - font-weight: var(--font-weight-medium); - color: var(--gray-700); -} - -.input-helper { - font-size: var(--font-size-sm); - color: var(--gray-500); -} - -.input-error-message { - font-size: var(--font-size-sm); - color: var(--error); -} - -/* Input with Icon */ -.input-with-icon { - position: relative; -} - -.input-with-icon .input { - padding-left: var(--space-11); -} - -.input-with-icon .input-icon { - position: absolute; - left: var(--space-4); - top: 50%; - transform: translateY(-50%); - color: var(--gray-400); - pointer-events: none; -} - -.input-with-icon-right .input { - padding-right: var(--space-11); -} - -.input-with-icon-right .input-icon { - left: auto; - right: var(--space-4); -} - -/* === SEARCH INPUT === */ -.search-box { - position: relative; - width: 100%; -} - -.search-box .input { - padding-left: var(--space-11); - background: var(--gray-50); - border-color: transparent; -} - -.search-box .input:focus { - background: var(--white); - border-color: var(--primary-blue); -} - -.search-box .search-icon { - position: absolute; - left: var(--space-4); - top: 50%; - transform: translateY(-50%); - color: var(--gray-400); -} - -.search-input { - position: relative; -} - -.search-input .input { - padding-left: var(--space-10); -} - -.search-input .search-icon { - position: absolute; - left: var(--space-3); - top: 50%; - transform: translateY(-50%); - color: var(--gray-400); -} - -/* === SELECT === */ -.select { - appearance: none; - width: 100%; - padding: var(--space-3) var(--space-10) var(--space-3) var(--space-4); - font-family: inherit; - font-size: var(--font-size-base); - color: var(--gray-900); - background: var(--white) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%236b7280' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E") no-repeat right var(--space-4) center; - border: 1px solid var(--gray-200); - border-radius: var(--radius-lg); - cursor: pointer; - transition: all var(--transition-fast); -} - -.select:focus { - outline: none; - border-color: var(--primary-blue); - box-shadow: 0 0 0 4px var(--primary-blue-glow); -} - -/* === BADGE === */ -.badge { - display: inline-flex; - align-items: center; - gap: var(--space-1); - padding: var(--space-1) var(--space-2-5); - font-size: var(--font-size-xs); - font-weight: var(--font-weight-semibold); - line-height: var(--line-height-tight); - border-radius: var(--radius-full); - white-space: nowrap; -} - -.badge-primary { - background: var(--primary-blue-subtle); - color: var(--primary-blue-dark); -} - -.badge-secondary { - background: var(--gray-200); - color: var(--gray-700); -} - -.badge-success { - background: var(--success-light); - color: var(--success-dark); -} - -.badge-warning { - background: var(--warning-light); - color: var(--warning-dark); -} - -.badge-error { - background: var(--error-light); - color: var(--error-dark); -} - -.badge-danger { - background: var(--error-light); - color: var(--error-dark); -} - -.badge-info { - background: var(--info-light); - color: var(--info-dark); -} - -.badge-gray { - background: var(--gray-100); - color: var(--gray-700); -} - -.badge-teal { - background: var(--teal-soft); - color: var(--teal-dark); -} - -.badge-violet { - background: var(--accent-violet-light); - color: var(--accent-violet); -} - -.badge-coral { - background: var(--accent-coral-light); - color: var(--accent-coral); -} - -.badge-outline { - background: transparent; - border: 1px solid currentColor; -} - -.badge-lg { - padding: var(--space-1-5) var(--space-3); - font-size: var(--font-size-sm); -} - -.badge-dot { - padding-left: var(--space-2); -} - -.badge-dot::before { - content: ''; - width: 6px; - height: 6px; - border-radius: 50%; - background: currentColor; -} - -/* === STATUS DOT === */ -.status-dot { - display: inline-block; - width: 10px; - height: 10px; - border-radius: 50%; - flex-shrink: 0; -} - -.status-dot.active { - background: var(--success); - box-shadow: 0 0 0 3px var(--success-light); -} - -.status-dot.inactive { - background: var(--gray-400); -} - -.status-dot.pending { - background: var(--warning); - box-shadow: 0 0 0 3px var(--warning-light); -} - -.status-dot.error { - background: var(--error); - box-shadow: 0 0 0 3px var(--error-light); -} - -.status-dot.pulse { - animation: statusPulse 2s ease-in-out infinite; -} - -@keyframes statusPulse { - 0%, 100% { transform: scale(1); opacity: 1; } - 50% { transform: scale(1.1); opacity: 0.8; } -} +/* Nimblesite Clinical Coding Platform — Components */ +/* Extracted directly from docs/designs/dashboard/code.html (Clinical Curator) */ + +/* === APP SHELL === */ +html, body { overflow-x: hidden; } +.app { min-height: 100vh; background: var(--surface); } +.main-wrapper { margin-left: var(--sidebar-width); min-height: 100vh; display: flex; flex-direction: column; min-width: 0; } +.main-content { flex: 1; padding: var(--space-8); min-width: 0; max-width: 100%; } +.page { display: flex; flex-direction: column; gap: var(--space-8); min-width: 0; } + +/* === SIDEBAR (no border, surface-container-low background) === */ +.sidebar { + position: fixed; left: 0; top: 0; bottom: 0; + width: var(--sidebar-width); + background: var(--surface-container-low); + display: flex; flex-direction: column; + z-index: var(--z-fixed); + transition: width var(--transition-normal); +} +.sidebar.collapsed { width: var(--sidebar-collapsed-width); } +.sidebar-header { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-6); } +.sidebar-logo { display: flex; align-items: center; gap: var(--space-3); text-decoration: none; color: var(--on-surface); } +.sidebar-logo-img { height: 36px; width: auto; flex-shrink: 0; object-fit: contain; } +.sidebar-logo-text { font-size: var(--font-size-sm); font-weight: var(--font-weight-bold); color: var(--on-surface); line-height: 1.1; } +.sidebar.collapsed .sidebar-logo-text { display: none; } +.sidebar-nav { flex: 1; margin-top: var(--space-4); padding: 0; overflow-y: auto; } +.nav-section { margin-bottom: var(--space-2); } +.nav-section-title { padding: var(--space-3) var(--space-6) var(--space-1); font-size: var(--font-size-2xs); font-weight: var(--font-weight-bold); text-transform: uppercase; letter-spacing: var(--letter-spacing-wide); color: var(--outline); } +.nav-item { display: flex; align-items: center; gap: var(--space-3); margin: var(--space-1) var(--space-2); padding: var(--space-3); border-radius: var(--radius-md); color: var(--on-surface-variant); text-decoration: none; font-size: var(--font-size-sm); font-weight: var(--font-weight-medium); transition: background var(--transition-fast); } +.nav-item:hover { background: rgba(255,255,255,0.5); color: var(--on-surface); } +.nav-item.active { background: var(--surface-container-lowest); color: var(--primary); box-shadow: var(--shadow-sm); font-weight: var(--font-weight-semibold); } +.nav-item-icon { width: 20px; height: 20px; flex-shrink: 0; display: inline-flex; align-items: center; justify-content: center; } +.nav-item-text { flex: 1; } +.sidebar.collapsed .nav-item-text, .sidebar.collapsed .nav-section-title { display: none; } +.sidebar-footer { padding: var(--space-4); } +.sidebar-user { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-3); border-radius: var(--radius-md); } +.sidebar-user-info { flex: 1; min-width: 0; } +.sidebar-user-name { font-size: var(--font-size-sm); font-weight: var(--font-weight-semibold); color: var(--on-surface); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } +.sidebar-user-role { font-size: var(--font-size-xs); color: var(--outline); } +.sidebar-toggle { width: 32px; height: 32px; border-radius: var(--radius-md); border: none; background: transparent; color: var(--on-surface-variant); cursor: pointer; display: flex; align-items: center; justify-content: center; } +.sidebar-toggle:hover { background: var(--surface-container); } +.sidebar-logout-btn { margin-top: var(--space-3); width: 100%; padding: var(--space-3); background: var(--gradient-primary); color: var(--on-primary); border: none; border-radius: var(--radius-md); font-weight: var(--font-weight-semibold); font-size: var(--font-size-sm); cursor: pointer; box-shadow: 0 4px 12px rgba(0,63,171,0.2); display: flex; align-items: center; justify-content: center; gap: var(--space-2); } +.sidebar.collapsed .sidebar-logout-btn span { display: none; } + +/* === HEADER (top app bar) === */ +.header { position: sticky; top: 0; z-index: 40; height: var(--header-height); padding: 0 var(--space-8); background: rgba(247,249,251,0.8); backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px); display: flex; align-items: center; justify-content: space-between; gap: var(--space-4); box-shadow: var(--shadow-sm); min-width: 0; } +.header-left { display: flex; align-items: center; gap: var(--space-6); flex: 1; min-width: 0; } +.header-right { display: flex; align-items: center; gap: var(--space-3); flex-shrink: 0; } +.header-title { font-size: var(--font-size-xl); font-weight: var(--font-weight-bold); color: var(--primary); letter-spacing: var(--letter-spacing-tight); } +.header-search { position: relative; width: 100%; max-width: 28rem; } +.header-search input, .header-search .input { width: 100%; background: var(--surface-container-highest); border: none; border-radius: var(--radius-full); padding: var(--space-2) var(--space-4) var(--space-2) 2.5rem; font-size: var(--font-size-sm); color: var(--on-surface); transition: background var(--transition-fast); } +.header-search input::placeholder { color: var(--outline); } +.header-search input:focus { outline: 2px solid rgba(0,63,171,0.3); background: var(--surface-container-lowest); } +.header-actions { display: flex; align-items: center; gap: var(--space-2); } +.header-action-btn { width: 40px; height: 40px; border-radius: var(--radius-full); border: none; background: transparent; color: var(--outline); cursor: pointer; display: flex; align-items: center; justify-content: center; transition: background var(--transition-fast); } +.header-action-btn:hover { background: var(--surface-container-high); } +.header-action-badge { position: absolute; top: 6px; right: 6px; min-width: 16px; height: 16px; background: var(--error); color: var(--on-error); border-radius: var(--radius-full); font-size: 9px; font-weight: var(--font-weight-bold); display: flex; align-items: center; justify-content: center; padding: 0 4px; } +.header-user { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-1) var(--space-2); border-radius: var(--radius-full); cursor: pointer; } +.header-user:hover { background: var(--surface-container); } + +/* === PAGE HEADER (Welcome row) === */ +.page-header { display: flex; justify-content: space-between; align-items: flex-end; } +.page-title, .welcome-title, .dashboard-welcome h2 { font-size: var(--font-size-3xl); font-weight: var(--font-weight-extrabold); color: var(--on-surface); letter-spacing: var(--letter-spacing-tight); margin: 0; } +.page-description, .dashboard-welcome p { font-size: var(--font-size-sm); color: var(--secondary); font-weight: var(--font-weight-medium); margin-top: var(--space-1); } +.welcome-actions, .page-actions { display: flex; gap: var(--space-3); align-items: center; } +.date-filter { background: var(--surface-container-low); padding: var(--space-2) var(--space-4); border-radius: var(--radius-md); display: flex; align-items: center; gap: var(--space-2); font-size: var(--font-size-sm); font-weight: var(--font-weight-semibold); color: var(--on-surface); } +.date-filter .icon { color: var(--primary); } + +/* === CARDS (Tonal layering: white on light grey) === */ +.card { background: var(--surface-container-lowest); border-radius: var(--radius-md); padding: var(--space-6); box-shadow: var(--shadow-card); transition: box-shadow var(--transition-normal); } +.card:hover { box-shadow: var(--shadow-card-hover); } +.card-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: var(--space-4); } +.card-header-left { display: flex; align-items: center; gap: var(--space-3); } +.card-title { font-size: var(--font-size-lg); font-weight: var(--font-weight-bold); color: var(--on-surface); margin: 0; } +.card-body { flex: 1; } + +/* === METRICS GRID (Bento KPI cards) === */ +.metrics-grid, .dashboard-metrics-row, .dashboard-grid.metrics { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--space-6); min-width: 0; } +@media (max-width: 1024px) { .metrics-grid, .dashboard-metrics-row, .dashboard-grid.metrics { grid-template-columns: repeat(2, minmax(0, 1fr)); } } +@media (max-width: 640px) { .metrics-grid, .dashboard-metrics-row, .dashboard-grid.metrics { grid-template-columns: 1fr; } } +.metric-card, .metric-card-rich { background: var(--surface-container-lowest); padding: var(--space-6); border-radius: var(--radius-md); box-shadow: var(--shadow-card); transition: box-shadow var(--transition-normal); min-width: 0; overflow: hidden; } +.metric-card:hover { box-shadow: var(--shadow-card-hover); } +.metric-card-header, .metric-header { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: var(--space-4); gap: var(--space-2); } +.metric-card-title, .metric-label { font-size: var(--font-size-2xs); font-weight: var(--font-weight-bold); color: var(--outline); text-transform: uppercase; letter-spacing: var(--letter-spacing-wide); margin: 0; flex: 1; min-width: 0; } +.metric-card-link { font-size: var(--font-size-2xs); font-weight: var(--font-weight-bold); color: var(--primary); text-transform: uppercase; letter-spacing: var(--letter-spacing-wide); white-space: nowrap; text-decoration: none; } +.metric-card-link:hover { text-decoration: underline; } +.metric-card-icon, .metric-icon { color: var(--primary); width: 24px; height: 24px; display: inline-flex; align-items: center; justify-content: center; } +.metric-card-icon.tertiary { color: var(--tertiary); } +.metric-card-icon.secondary { color: var(--secondary); } +.metric-card-body { display: flex; align-items: center; gap: var(--space-4); } +.metric-card-value-row { display: flex; align-items: baseline; gap: var(--space-2); } +.metric-card-value, .metric-value { font-size: var(--font-size-3xl); font-weight: var(--font-weight-bold); color: var(--on-surface); line-height: 1; letter-spacing: var(--letter-spacing-tight); } +.metric-card-breakdown { font-size: var(--font-size-xs); color: var(--tertiary); font-weight: var(--font-weight-semibold); display: flex; align-items: center; gap: var(--space-1); margin-top: var(--space-1); } +.metric-breakdown-item { display: flex; align-items: center; gap: var(--space-2); font-size: var(--font-size-xs); color: var(--on-surface-variant); } +.metric-breakdown-dot { width: 8px; height: 8px; border-radius: var(--radius-full); background: var(--primary); } + +/* === DASHBOARD MAIN GRID (2-col: appointments + requests) === */ +.dashboard-main-grid { display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); gap: var(--space-8); min-width: 0; } +@media (max-width: 1024px) { .dashboard-main-grid { grid-template-columns: 1fr; } } +.dashboard-section { display: flex; flex-direction: column; gap: var(--space-6); } +.dashboard-section-header, .dashboard-appointments-section header, .dashboard-requests-section header { display: flex; justify-content: space-between; align-items: center; margin-bottom: var(--space-4); } +.dashboard-section-title { font-size: var(--font-size-xl); font-weight: var(--font-weight-bold); color: var(--on-surface); } +.dashboard-section-link, .view-more-link, .link-btn { color: var(--primary); font-size: var(--font-size-sm); font-weight: var(--font-weight-bold); background: none; border: none; cursor: pointer; } +.dashboard-section-link:hover, .view-more-link:hover, .link-btn:hover { text-decoration: underline; } + +/* === APPOINTMENT REQUESTS (sidebar list) === */ +.appointment-request { background: var(--surface-container-low); padding: var(--space-5); border-radius: var(--radius-md); border-left: 4px solid var(--primary); margin-bottom: var(--space-4); } +.appointment-request.neutral { border-left-color: var(--outline-variant); } +.appointment-request-info { display: flex; gap: var(--space-3); margin-bottom: var(--space-4); } +.appointment-request-info .icon-wrap { width: 40px; height: 40px; border-radius: var(--radius-md); background: var(--surface-container-lowest); display: flex; align-items: center; justify-content: center; box-shadow: var(--shadow-sm); color: var(--primary); } +.appointment-request-name { font-size: var(--font-size-sm); font-weight: var(--font-weight-bold); color: var(--on-surface); } +.appointment-request-time, .appointment-request-type { font-size: var(--font-size-xs); color: var(--outline); } +.appointment-request-actions { display: flex; gap: var(--space-2); } +.appointment-request-details { font-size: var(--font-size-xs); color: var(--outline); } + +/* === APPOINTMENTS TABLE / LIST === */ +.appointments-table { width: 100%; } +.appointments-table .row, .search-result-row { display: flex; align-items: center; justify-content: space-between; background: var(--surface-container-lowest); padding: var(--space-4); border-radius: var(--radius-md); margin-bottom: var(--space-3); transition: box-shadow var(--transition-fast); } +.appointments-table .row:hover, .search-result-row:hover { box-shadow: var(--shadow-md); } + +/* === BUTTONS === */ +.btn { display: inline-flex; align-items: center; justify-content: center; gap: var(--space-2); padding: var(--space-3) var(--space-5); border-radius: var(--radius-md); font-size: var(--font-size-sm); font-weight: var(--font-weight-bold); border: none; cursor: pointer; transition: filter var(--transition-fast), transform var(--transition-fast); text-decoration: none; font-family: var(--font-family); } +.btn:active { transform: scale(0.97); } +.btn-primary { background: var(--gradient-primary); color: var(--on-primary); box-shadow: 0 4px 12px rgba(0,63,171,0.2); } +.btn-primary:hover { filter: brightness(1.1); } +.btn-secondary { background: var(--surface-container-high); color: var(--on-secondary-container); } +.btn-secondary:hover { background: var(--surface-container-highest); } +.btn-outline { background: var(--surface-container-lowest); color: var(--on-surface-variant); box-shadow: inset 0 0 0 1px var(--outline-variant); } +.btn-outline:hover { background: var(--surface-container-low); } +.btn-ghost { background: transparent; color: var(--on-surface-variant); } +.btn-ghost:hover { background: var(--surface-container-low); } +.btn-sm { padding: var(--space-2) var(--space-3); font-size: var(--font-size-xs); } +.btn-lg { padding: var(--space-4) var(--space-6); font-size: var(--font-size-md); } +.btn-group { display: inline-flex; gap: var(--space-2); } +.btn-icon-circle { width: 36px; height: 36px; border-radius: var(--radius-full); border: none; cursor: pointer; display: inline-flex; align-items: center; justify-content: center; } +.btn-icon-circle.accept { background: var(--primary); color: var(--on-primary); } +.btn-icon-circle.reject { background: var(--surface-container); color: var(--on-surface-variant); } +.btn-icon-sm { width: 32px; height: 32px; border-radius: var(--radius-full); border: none; background: transparent; color: var(--outline); cursor: pointer; display: inline-flex; align-items: center; justify-content: center; } +.btn-icon-sm:hover { background: var(--surface-container); color: var(--primary); } +.action-buttons { display: flex; gap: var(--space-2); } + +/* === BADGES === */ +.badge { display: inline-flex; align-items: center; padding: 2px 10px; border-radius: var(--radius-full); font-size: var(--font-size-2xs); font-weight: var(--font-weight-bold); text-transform: uppercase; letter-spacing: var(--letter-spacing-wide); } +.badge-primary { background: var(--primary-container); color: var(--on-primary); } +.badge-success { background: var(--success-light); color: var(--success); } +.badge-info { background: var(--info-light); color: var(--info); } +.badge-gray { background: var(--surface-container-high); color: var(--on-surface-variant); } +.badge-error { background: var(--error-container); color: var(--on-error-container); } + +/* === ALERTS === */ +.alert { padding: var(--space-4); border-radius: var(--radius-md); font-size: var(--font-size-sm); margin-bottom: var(--space-4); } +.alert-error { background: var(--error-container); color: var(--on-error-container); } +.alert-success { background: var(--success-light); color: var(--success); } +.alert-warning { background: var(--warning-light); color: var(--warning); } + +/* === FORMS === */ +.form { display: flex; flex-direction: column; gap: var(--space-4); } +.form-group, .input-group { display: flex; flex-direction: column; gap: var(--space-2); } +.form-label, .input-label { font-size: var(--font-size-xs); font-weight: var(--font-weight-semibold); color: var(--on-surface-variant); text-transform: uppercase; letter-spacing: var(--letter-spacing-wide); } +.form-section-title { font-size: var(--font-size-md); font-weight: var(--font-weight-bold); color: var(--on-surface); } +.form-actions { display: flex; gap: var(--space-3); } +.input { width: 100%; padding: var(--space-3) var(--space-4); border: none; border-radius: var(--radius-md); background: var(--surface-container-highest); color: var(--on-surface); font-size: var(--font-size-sm); font-family: var(--font-family); transition: background var(--transition-fast), box-shadow var(--transition-fast); } +.input:focus { outline: none; background: var(--surface-container-lowest); box-shadow: 0 0 0 2px rgba(0,63,171,0.3); } +.input::placeholder { color: var(--outline); } + +/* === TABLES === */ +.table-container { background: var(--surface-container-lowest); border-radius: var(--radius-md); padding: var(--space-2); box-shadow: var(--shadow-card); overflow-x: auto; } +.table { width: 100%; border-collapse: separate; border-spacing: 0; font-size: var(--font-size-sm); } +.table th { text-align: left; padding: var(--space-3) var(--space-4); font-size: var(--font-size-2xs); font-weight: var(--font-weight-bold); color: var(--outline); text-transform: uppercase; letter-spacing: var(--letter-spacing-wide); } +.table td { padding: var(--space-4); color: var(--on-surface); } +.table tr:hover td { background: var(--surface-container-low); } +.patient-cell { display: flex; align-items: center; gap: var(--space-3); } +.result-description-cell { max-width: 360px; } /* === AVATAR === */ -.avatar { - display: inline-flex; - align-items: center; - justify-content: center; - border-radius: 50%; - font-weight: var(--font-weight-semibold); - background: var(--gradient-primary); - color: var(--white); - flex-shrink: 0; - overflow: hidden; -} - -.avatar-xs { width: 24px; height: 24px; font-size: var(--font-size-2xs); } +.avatar { display: inline-flex; align-items: center; justify-content: center; border-radius: var(--radius-full); background: var(--primary-container); color: var(--on-primary); font-weight: var(--font-weight-bold); flex-shrink: 0; overflow: hidden; } +.avatar img { width: 100%; height: 100%; object-fit: cover; } .avatar-sm { width: 32px; height: 32px; font-size: var(--font-size-xs); } .avatar-md { width: 40px; height: 40px; font-size: var(--font-size-sm); } -.avatar-lg { width: 48px; height: 48px; font-size: var(--font-size-md); } -.avatar-xl { width: 64px; height: 64px; font-size: var(--font-size-xl); } -.avatar-2xl { width: 80px; height: 80px; font-size: var(--font-size-2xl); } - -.avatar img { - width: 100%; - height: 100%; - object-fit: cover; -} - -.avatar-teal { background: var(--gradient-teal); } -.avatar-warm { background: var(--gradient-warm); } -.avatar-violet { background: linear-gradient(135deg, var(--accent-violet) 0%, #6d28d9 100%); } -.avatar-blue { background: var(--primary-blue-subtle); color: var(--primary-blue-dark); } - -.avatar-group { - display: flex; -} - -.avatar-group .avatar { - border: 2px solid var(--white); - margin-left: -8px; -} - -.avatar-group .avatar:first-child { - margin-left: 0; -} - -/* === TABLE === */ -.table-container { - overflow-x: auto; - border-radius: var(--radius-xl); - background: var(--white); - box-shadow: var(--shadow-card); -} - -.table { - width: 100%; - border-collapse: collapse; -} - -.table th, -.table td { - padding: var(--space-4) var(--space-5); - text-align: left; - border-bottom: 1px solid var(--gray-100); -} - -.table th { - font-size: var(--font-size-sm); - font-weight: var(--font-weight-semibold); - color: var(--gray-600); - background: var(--gray-50); - text-transform: uppercase; - letter-spacing: var(--letter-spacing-wide); -} +.avatar-lg { width: 56px; height: 56px; font-size: var(--font-size-md); } + +/* === USER MENU / DROPDOWN === */ +.user-menu { position: relative; } +.user-menu-trigger { cursor: pointer; } +.user-dropdown { position: absolute; right: 0; top: calc(100% + 8px); background: var(--surface-container-lowest); border-radius: var(--radius-md); box-shadow: var(--shadow-lg); padding: var(--space-2); min-width: 240px; z-index: var(--z-modal); } +.user-dropdown-header { padding: var(--space-3) var(--space-4); } +.user-dropdown-name { font-size: var(--font-size-sm); font-weight: var(--font-weight-bold); color: var(--on-surface); } +.user-dropdown-email { font-size: var(--font-size-xs); color: var(--outline); } +.user-dropdown-divider { height: 1px; background: var(--outline-variant); opacity: 0.4; margin: var(--space-2) 0; } +.user-dropdown-item { display: flex; align-items: center; gap: var(--space-2); padding: var(--space-3) var(--space-4); border-radius: var(--radius-sm); color: var(--on-surface-variant); font-size: var(--font-size-sm); cursor: pointer; } +.user-dropdown-item:hover { background: var(--surface-container-low); } +.user-dropdown-logout { color: var(--error); } -.table th:first-child { - border-radius: var(--radius-xl) 0 0 0; -} +/* === MODAL === */ +.modal-backdrop { position: fixed; inset: 0; background: rgba(25,28,30,0.5); display: none; align-items: center; justify-content: center; z-index: var(--z-modal); } +.modal-backdrop.open { display: flex; } +.modal { background: var(--surface-container-lowest); border-radius: var(--radius-lg); box-shadow: var(--shadow-card-hover); max-width: 640px; width: 100%; max-height: 90vh; display: flex; flex-direction: column; } +.modal-header { padding: var(--space-6); display: flex; justify-content: space-between; align-items: center; } +.modal-title { font-size: var(--font-size-xl); font-weight: var(--font-weight-bold); color: var(--on-surface); } +.modal-close { background: none; border: none; cursor: pointer; color: var(--outline); width: 32px; height: 32px; border-radius: var(--radius-full); display: flex; align-items: center; justify-content: center; } +.modal-close:hover { background: var(--surface-container); } +.modal-body { padding: 0 var(--space-6) var(--space-6); overflow-y: auto; } +.modal-footer { padding: var(--space-6); display: flex; justify-content: flex-end; gap: var(--space-3); } + +/* === LOGIN === */ +.login-page { min-height: 100vh; display: flex; align-items: center; justify-content: center; background: var(--surface); padding: var(--space-6); } +.login-card { background: var(--surface-container-lowest); border-radius: var(--radius-lg); padding: var(--space-10); box-shadow: var(--shadow-card-hover); max-width: 440px; width: 100%; } +.login-header { text-align: center; margin-bottom: var(--space-6); } +.login-logo-img { display: block; height: 56px; width: auto; margin: 0 auto var(--space-4); object-fit: contain; } +.login-header h1 { font-size: var(--font-size-xl); font-weight: var(--font-weight-bold); color: var(--on-surface); margin-bottom: var(--space-2); } +.login-header p { font-size: var(--font-size-sm); color: var(--outline); } +.login-error { padding: var(--space-3) var(--space-4); background: var(--error-container); color: var(--on-error-container); border-radius: var(--radius-md); font-size: var(--font-size-sm); margin-bottom: var(--space-4); } +.login-success { padding: var(--space-3) var(--space-4); background: var(--success-light); color: var(--success); border-radius: var(--radius-md); font-size: var(--font-size-sm); margin-bottom: var(--space-4); } +.login-btn { width: 100%; } +.login-footer { text-align: center; margin-top: var(--space-4); font-size: var(--space-sm); color: var(--outline); } -.table th:last-child { - border-radius: 0 var(--radius-xl) 0 0; +/* === CALENDAR === */ +.calendar-grid-container { padding: var(--space-4); } +.calendar-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: var(--space-4); } +.calendar-month { font-size: var(--font-size-lg); font-weight: var(--font-weight-bold); color: var(--on-surface); } +.calendar-nav { display: flex; gap: var(--space-2); } +.calendar-grid-header { background: var(--surface-container-low); border-radius: var(--radius-md); margin-bottom: var(--space-2); } +.calendar-header-cell { font-size: var(--font-size-2xs); font-weight: var(--font-weight-bold); color: var(--outline); text-transform: uppercase; padding: var(--space-3); } +.calendar-days, .calendar-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: var(--space-1); } +.calendar-cell { aspect-ratio: 1; padding: var(--space-2); border-radius: var(--radius-md); background: var(--surface-container-lowest); cursor: pointer; display: flex; flex-direction: column; gap: var(--space-1); transition: background var(--transition-fast); } +.calendar-cell:hover { background: var(--surface-container-low); } +.calendar-cell.empty { background: transparent; cursor: default; } +.calendar-cell.selected { background: var(--primary); color: var(--on-primary); } +.calendar-day-number { font-size: var(--font-size-sm); font-weight: var(--font-weight-semibold); color: var(--on-surface); } +.calendar-cell.selected .calendar-day-number { color: var(--on-primary); } +.calendar-more-indicator { font-size: 9px; color: var(--outline); } +.calendar-strip { display: flex; gap: var(--space-2); overflow-x: auto; padding: var(--space-2) 0; } +.calendar-weekdays { display: grid; grid-template-columns: repeat(7, 1fr); gap: var(--space-1); margin-bottom: var(--space-2); } +.calendar-weekday { text-align: center; font-size: var(--font-size-2xs); font-weight: var(--font-weight-bold); color: var(--outline); text-transform: uppercase; } +.calendar-picker { display: flex; flex-direction: column; gap: var(--space-3); } +.calendar-details-panel { padding: var(--space-6); } +.calendar-appointments-preview { display: flex; flex-direction: column; gap: var(--space-3); } +.calendar-appointment-item { background: var(--surface-container-low); } +.appointment-legend { display: flex; gap: var(--space-4); align-items: center; font-size: var(--font-size-xs); color: var(--outline); } +.legend-item { display: flex; align-items: center; gap: var(--space-2); } +.legend-dot { width: 10px; height: 10px; border-radius: var(--radius-full); } +.legend-dot.available { background: var(--tertiary); } +.legend-dot.selected { background: var(--primary); } +.legend-dot.unavailable { background: var(--outline-variant); } + +/* === DONUT / BAR CHARTS === */ +.donut-chart-container { display: flex; align-items: center; gap: var(--space-4); } +.donut-legend { display: flex; flex-direction: column; gap: var(--space-2); } +.donut-legend-item { display: flex; align-items: center; gap: var(--space-2); font-size: var(--font-size-xs); color: var(--on-surface-variant); } +.bar-chart { display: flex; align-items: flex-end; gap: var(--space-1); height: 48px; } +.bar-chart-item { flex: 1; background: var(--secondary); border-radius: var(--radius-sm); } +.bar { background: var(--primary); border-radius: var(--radius-sm); } +.breakdown-bar { display: flex; align-items: center; gap: var(--space-2); } +.breakdown-bar-item { flex: 1; height: 8px; border-radius: var(--radius-full); background: var(--surface-container); overflow: hidden; } +.breakdown-bar-value { font-size: var(--font-size-xs); font-weight: var(--font-weight-semibold); color: var(--on-surface); } +.patient-breakdown-bars { display: flex; flex-direction: column; gap: var(--space-2); } + +/* === QUICK ACTIONS (3 colored panels at bottom) === */ +.quick-actions-grid, .dashboard-grid.practitioners { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-6); } +@media (max-width: 768px) { .quick-actions-grid, .dashboard-grid.practitioners { grid-template-columns: 1fr; } } +.quick-actions-card { display: flex; flex-direction: column; justify-content: space-between; min-height: 160px; padding: var(--space-6); border-radius: var(--radius-md); color: var(--on-primary); } +.quick-action-btn { background: var(--gradient-primary); color: var(--on-primary); padding: var(--space-6); border-radius: var(--radius-md); border: none; cursor: pointer; min-height: 160px; display: flex; flex-direction: column; justify-content: space-between; align-items: flex-start; text-align: left; gap: var(--space-3); font-family: var(--font-family); } +.quick-action-btn.primary { background: var(--gradient-primary); } +.quick-action-btn.tertiary { background: var(--tertiary); } +.quick-action-btn.neutral { background: var(--surface-container-high); color: var(--on-surface); } +.quick-action-btn h4 { font-size: var(--font-size-lg); font-weight: var(--font-weight-bold); margin: 0; } +.quick-action-btn p { font-size: var(--font-size-xs); opacity: 0.8; margin: 0; } +.quick-action-btn .cta { background: rgba(255,255,255,0.2); color: inherit; padding: var(--space-2) var(--space-4); border-radius: var(--radius-md); font-size: var(--font-size-xs); font-weight: var(--font-weight-bold); } +.quick-action-btn.neutral .cta { background: var(--primary); color: var(--on-primary); } + +/* === PRACTITIONER CARDS === */ +.practitioner-card { display: flex; flex-direction: column; align-items: center; text-align: center; gap: var(--space-3); padding: var(--space-6); } +.practitioner-avatar { width: 80px; height: 80px; border-radius: var(--radius-full); background: var(--primary-container); color: var(--on-primary); display: flex; align-items: center; justify-content: center; font-size: var(--font-size-xl); font-weight: var(--font-weight-bold); overflow: hidden; } +.practitioner-name { font-size: var(--font-size-md); font-weight: var(--font-weight-bold); color: var(--on-surface); } +.practitioner-specialty { font-size: var(--font-size-sm); color: var(--outline); } +.practitioner-meta { font-size: var(--font-size-xs); color: var(--outline); } +.practitioner-edit-btn { margin-top: var(--space-2); } + +/* === EMPTY STATE / SKELETON === */ +.empty-state { text-align: center; padding: var(--space-12) var(--space-6); } +.empty-state-icon { width: 64px; height: 64px; margin: 0 auto var(--space-4); color: var(--outline-variant); } +.empty-state-title { font-size: var(--font-size-lg); font-weight: var(--font-weight-bold); color: var(--on-surface); } +.empty-state-description { font-size: var(--font-size-sm); color: var(--outline); } +.skeleton { background: linear-gradient(90deg, var(--surface-container-low), var(--surface-container), var(--surface-container-low)); background-size: 200% 100%; border-radius: var(--radius-md); height: 16px; animation: skeleton-shimmer 1.5s infinite; } +.skeleton-rows { display: flex; flex-direction: column; gap: var(--space-3); padding: var(--space-4); } +@keyframes skeleton-shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } } +.result-tooltip { position: absolute; background: var(--inverse-surface); color: var(--inverse-on-surface, #eff1f3); padding: var(--space-2) var(--space-3); border-radius: var(--radius-md); font-size: var(--font-size-xs); } + +/* === FOOTER === */ +.dashboard-footer { margin-top: var(--space-12); padding: var(--space-8); text-align: center; font-size: var(--font-size-2xs); font-weight: var(--font-weight-medium); color: var(--outline-variant); letter-spacing: var(--letter-spacing-wide); text-transform: uppercase; } + +/* === RESPONSIVE === */ +@media (max-width: 1024px) { + .main-wrapper { margin-left: var(--sidebar-collapsed-width); } + .sidebar { width: var(--sidebar-collapsed-width); } + .sidebar .sidebar-logo-text, .sidebar .nav-item-text, .sidebar .nav-section-title, .sidebar-logout-btn span { display: none; } +} +@media (max-width: 640px) { + .main-content { padding: var(--space-4); } + .header { padding: 0 var(--space-4); } + .page-header { flex-direction: column; align-items: flex-start; gap: var(--space-3); } } - -.table tbody tr { - transition: background var(--transition-fast); -} - -.table tbody tr:hover { - background: var(--gray-50); -} - -.table tbody tr:last-child td { - border-bottom: none; -} - -.table tbody tr:last-child td:first-child { - border-radius: 0 0 0 var(--radius-xl); -} - -.table tbody tr:last-child td:last-child { - border-radius: 0 0 var(--radius-xl) 0; -} - -.table-compact th, -.table-compact td { - padding: var(--space-3) var(--space-4); -} - -.table-striped tbody tr:nth-child(even) { - background: var(--gray-25); -} - -.table-action { - display: flex; - gap: var(--space-2); - justify-content: flex-end; -} - -/* === TABS === */ -.tabs { - display: flex; - gap: var(--space-1); - background: var(--gray-100); - padding: var(--space-1); - border-radius: var(--radius-lg); - width: fit-content; -} - -.tab { - padding: var(--space-2) var(--space-4); - font-size: var(--font-size-sm); - font-weight: var(--font-weight-medium); - color: var(--gray-600); - background: transparent; - border: none; - border-radius: var(--radius-md); - cursor: pointer; - transition: all var(--transition-fast); -} - -.tab:hover { - color: var(--gray-900); -} - -.tab.active { - color: var(--gray-900); - background: var(--white); - box-shadow: var(--shadow-sm); -} - -.tabs-underline { - background: transparent; - padding: 0; - border-bottom: 1px solid var(--gray-200); - border-radius: 0; - gap: var(--space-6); -} - -.tabs-underline .tab { - padding: var(--space-3) var(--space-1); - border-radius: 0; - border-bottom: 2px solid transparent; - margin-bottom: -1px; -} - -.tabs-underline .tab.active { - background: transparent; - color: var(--primary-blue); - border-bottom-color: var(--primary-blue); - box-shadow: none; -} - -/* === DROPDOWN === */ -.dropdown { - position: relative; - display: inline-block; -} - -.dropdown-menu { - position: absolute; - top: calc(100% + var(--space-2)); - right: 0; - min-width: 200px; - background: var(--white); - border-radius: var(--radius-xl); - box-shadow: var(--shadow-floating); - padding: var(--space-2); - z-index: var(--z-dropdown); - opacity: 0; - visibility: hidden; - transform: translateY(-8px) scale(0.95); - transition: all var(--transition-fast); -} - -.dropdown.open .dropdown-menu, -.dropdown:focus-within .dropdown-menu { - opacity: 1; - visibility: visible; - transform: translateY(0) scale(1); -} - -.dropdown-item { - display: flex; - align-items: center; - gap: var(--space-3); - padding: var(--space-2-5) var(--space-3); - font-size: var(--font-size-base); - color: var(--gray-700); - border-radius: var(--radius-md); - cursor: pointer; - transition: all var(--transition-fast); -} - -.dropdown-item:hover { - background: var(--gray-100); - color: var(--gray-900); -} - -.dropdown-item.danger { - color: var(--error); -} - -.dropdown-item.danger:hover { - background: var(--error-light); -} - -.dropdown-divider { - height: 1px; - background: var(--gray-100); - margin: var(--space-2) 0; -} - -/* === MODAL === */ -.modal-backdrop { - position: fixed; - inset: 0; - background: rgba(0, 0, 0, 0.4); - backdrop-filter: blur(8px); - z-index: var(--z-modal-backdrop); - display: flex; - align-items: center; - justify-content: center; - padding: var(--space-6); - opacity: 0; - visibility: hidden; - transition: all var(--transition-normal); -} - -.modal-backdrop.open { - opacity: 1; - visibility: visible; -} - -.modal { - background: var(--white); - border-radius: var(--radius-2xl); - box-shadow: var(--shadow-2xl); - max-width: 540px; - width: 100%; - max-height: 90vh; - overflow: hidden; - transform: translateY(20px) scale(0.95); - transition: all var(--transition-normal); -} - -.modal-backdrop.open .modal { - transform: translateY(0) scale(1); -} - -.modal-sm { max-width: 400px; } -.modal-lg { max-width: 720px; } -.modal-xl { max-width: 960px; } -.modal-full { max-width: calc(100vw - var(--space-12)); max-height: calc(100vh - var(--space-12)); } - -.modal-header { - display: flex; - align-items: center; - justify-content: space-between; - padding: var(--space-5) var(--space-6); - border-bottom: 1px solid var(--gray-100); -} - -.modal-title { - font-size: var(--font-size-xl); - font-weight: var(--font-weight-semibold); - color: var(--gray-900); -} - -.modal-close { - width: 36px; - height: 36px; - display: flex; - align-items: center; - justify-content: center; - background: var(--gray-100); - border: none; - border-radius: var(--radius-lg); - cursor: pointer; - color: var(--gray-500); - transition: all var(--transition-fast); -} - -.modal-close:hover { - background: var(--gray-200); - color: var(--gray-700); -} - -.modal-body { - padding: var(--space-6); - overflow-y: auto; - max-height: calc(90vh - 140px); -} - -.modal-footer { - display: flex; - justify-content: flex-end; - gap: var(--space-3); - padding: var(--space-4) var(--space-6); - border-top: 1px solid var(--gray-100); - background: var(--gray-50); -} - -/* === LOADING STATES === */ -.spinner { - width: 24px; - height: 24px; - border: 2px solid var(--gray-200); - border-top-color: var(--primary-blue); - border-radius: 50%; - animation: spin 0.7s linear infinite; -} - -.spinner-sm { width: 16px; height: 16px; border-width: 2px; } -.spinner-lg { width: 40px; height: 40px; border-width: 3px; } -.spinner-xl { width: 56px; height: 56px; border-width: 4px; } - -.spinner-white { - border-color: rgba(255,255,255,0.3); - border-top-color: var(--white); -} - -.skeleton { - background: linear-gradient(90deg, var(--gray-100) 25%, var(--gray-50) 50%, var(--gray-100) 75%); - background-size: 200% 100%; - animation: shimmer 1.5s infinite linear; - border-radius: var(--radius-md); -} - -.skeleton-text { - height: 16px; - margin-bottom: var(--space-2); -} - -.skeleton-title { - height: 24px; - width: 60%; - margin-bottom: var(--space-3); -} - -.skeleton-avatar { - width: 40px; - height: 40px; - border-radius: 50%; -} - -.skeleton-card { - height: 120px; - border-radius: var(--radius-xl); -} - -@keyframes shimmer { - 0% { background-position: 200% 0; } - 100% { background-position: -200% 0; } -} - -/* === EMPTY STATE === */ -.empty-state { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - padding: var(--space-16) var(--space-6); - text-align: center; -} - -.empty-state-icon { - width: 96px; - height: 96px; - margin-bottom: var(--space-6); - color: var(--gray-300); - opacity: 0.8; -} - -.empty-state-icon .icon, -.empty-state-icon svg { - width: 100%; - height: 100%; -} - -.empty-state-title { - font-size: var(--font-size-xl); - font-weight: var(--font-weight-semibold); - color: var(--gray-900); - margin-bottom: var(--space-2); -} - -.empty-state-description { - color: var(--gray-500); - max-width: 360px; - margin-bottom: var(--space-6); -} - -/* === TOOLTIP === */ -.tooltip { - position: relative; - display: inline-block; -} - -.tooltip-content { - position: absolute; - bottom: calc(100% + 8px); - left: 50%; - transform: translateX(-50%); - padding: var(--space-2) var(--space-3); - font-size: var(--font-size-sm); - color: var(--white); - background: var(--gray-900); - border-radius: var(--radius-md); - white-space: nowrap; - z-index: var(--z-tooltip); - opacity: 0; - visibility: hidden; - transition: all var(--transition-fast); - pointer-events: none; -} - -.tooltip-content::after { - content: ''; - position: absolute; - top: 100%; - left: 50%; - transform: translateX(-50%); - border: 6px solid transparent; - border-top-color: var(--gray-900); -} - -.tooltip:hover .tooltip-content { - opacity: 1; - visibility: visible; -} - -/* === PROGRESS BAR === */ -.progress { - width: 100%; - height: 8px; - background: var(--gray-100); - border-radius: var(--radius-full); - overflow: hidden; -} - -.progress-bar { - height: 100%; - background: var(--gradient-primary); - border-radius: var(--radius-full); - transition: width var(--transition-slow); -} - -.progress-bar.success { background: var(--gradient-teal); } -.progress-bar.warning { background: var(--gradient-warm); } -.progress-bar.error { background: linear-gradient(135deg, var(--error) 0%, var(--error-dark) 100%); } - -.progress-sm { height: 4px; } -.progress-lg { height: 12px; } - -/* === ALERT === */ -.alert { - display: flex; - align-items: flex-start; - gap: var(--space-3); - padding: var(--space-4) var(--space-5); - border-radius: var(--radius-lg); - border: 1px solid; -} - -.alert-icon { - flex-shrink: 0; - width: 20px; - height: 20px; -} - -.alert-content { - flex: 1; -} - -.alert-title { - font-weight: var(--font-weight-semibold); - margin-bottom: var(--space-1); -} - -.alert-description { - font-size: var(--font-size-sm); - opacity: 0.9; -} - -.alert-info { - background: var(--info-light); - border-color: var(--info); - color: var(--info-dark); -} - -.alert-success { - background: var(--success-light); - border-color: var(--success); - color: var(--success-dark); -} - -.alert-warning { - background: var(--warning-light); - border-color: var(--warning); - color: var(--warning-dark); -} - -.alert-error { - background: var(--error-light); - border-color: var(--error); - color: var(--error-dark); -} - -/* === TOGGLE === */ -.toggle { - position: relative; - display: inline-flex; - width: 44px; - height: 24px; - cursor: pointer; -} - -.toggle input { - opacity: 0; - width: 0; - height: 0; -} - -.toggle-slider { - position: absolute; - inset: 0; - background: var(--gray-300); - border-radius: var(--radius-full); - transition: all var(--transition-fast); -} - -.toggle-slider::before { - content: ''; - position: absolute; - width: 18px; - height: 18px; - left: 3px; - bottom: 3px; - background: var(--white); - border-radius: 50%; - transition: all var(--transition-fast); - box-shadow: var(--shadow-sm); -} - -.toggle input:checked + .toggle-slider { - background: var(--primary-blue); -} - -.toggle input:checked + .toggle-slider::before { - transform: translateX(20px); -} - -.toggle input:focus-visible + .toggle-slider { - box-shadow: 0 0 0 3px var(--primary-blue-glow); -} - -/* === DIVIDER === */ -.divider { - height: 1px; - background: var(--gray-200); - margin: var(--space-6) 0; -} - -.divider-vertical { - width: 1px; - height: auto; - align-self: stretch; - margin: 0 var(--space-4); -} - -/* === NOTIFICATION DOT === */ -.notification-dot { - position: absolute; - top: -2px; - right: -2px; - width: 10px; - height: 10px; - background: var(--error); - border: 2px solid var(--white); - border-radius: 50%; -} - -.notification-count { - position: absolute; - top: -6px; - right: -6px; - min-width: 18px; - height: 18px; - padding: 0 var(--space-1); - font-size: var(--font-size-2xs); - font-weight: var(--font-weight-bold); - color: var(--white); - background: var(--error); - border: 2px solid var(--white); - border-radius: var(--radius-full); - display: flex; - align-items: center; - justify-content: center; -} - -/* === ACTIVITY/LIST ITEM === */ -.activity-item { - display: flex; - align-items: flex-start; - gap: var(--space-4); - padding: var(--space-4) 0; - border-bottom: 1px solid var(--gray-100); -} - -.activity-item:last-child { - border-bottom: none; -} - -.activity-icon { - width: 40px; - height: 40px; - border-radius: var(--radius-lg); - display: flex; - align-items: center; - justify-content: center; - flex-shrink: 0; -} - -.activity-content { - flex: 1; - min-width: 0; -} - -.activity-title { - font-weight: var(--font-weight-medium); - color: var(--gray-900); - margin-bottom: var(--space-0-5); -} - -.activity-description { - font-size: var(--font-size-sm); - color: var(--gray-500); -} - -.activity-time { - font-size: var(--font-size-sm); - color: var(--gray-400); - white-space: nowrap; -} - -/* === QUICK ACTIONS === */ -.quick-action { - display: flex; - align-items: center; - justify-content: center; - gap: var(--space-2); - padding: var(--space-4) var(--space-5); - background: var(--white); - border: 1px solid var(--gray-200); - border-radius: var(--radius-xl); - font-weight: var(--font-weight-medium); - color: var(--gray-700); - cursor: pointer; - transition: all var(--transition-fast); -} - -.quick-action:hover { - border-color: var(--primary-blue); - color: var(--primary-blue); - box-shadow: var(--shadow-md); -} - -.quick-action-primary { - background: var(--gradient-primary); - border-color: transparent; - color: var(--white); -} - -.quick-action-primary:hover { - transform: translateY(-2px); - box-shadow: var(--shadow-lg); - color: var(--white); -} - -/* === CALENDAR === */ -.calendar-grid-container { - padding: var(--space-4); -} - -.calendar-grid-header { - margin-bottom: var(--space-2); -} - -.calendar-header-cell { - font-size: var(--font-size-sm); - font-weight: var(--font-weight-semibold); - color: var(--gray-500); - text-transform: uppercase; - letter-spacing: var(--letter-spacing-wide); -} - -.calendar-grid { - gap: var(--space-1); -} - -.calendar-cell { - min-height: 100px; - padding: var(--space-2); - background: var(--white); - border: 1px solid var(--gray-100); - border-radius: var(--radius-lg); - cursor: pointer; - transition: all var(--transition-fast); - display: flex; - flex-direction: column; -} - -.calendar-cell:hover { - border-color: var(--primary-blue); - box-shadow: var(--shadow-sm); -} - -.calendar-cell.empty { - background: var(--gray-50); - border-color: transparent; - cursor: default; -} - -.calendar-cell.empty:hover { - border-color: transparent; - box-shadow: none; -} - -.calendar-cell.today { - border-color: var(--primary-blue); - background: var(--primary-blue-subtle); -} - -.calendar-cell.selected { - border-color: var(--primary-blue); - box-shadow: 0 0 0 2px var(--primary-blue-glow); -} - -.calendar-cell.has-appointments .calendar-day-number { - font-weight: var(--font-weight-bold); -} - -.calendar-day-number { - font-size: var(--font-size-sm); - font-weight: var(--font-weight-medium); - color: var(--gray-700); - margin-bottom: var(--space-1); -} - -.calendar-cell.today .calendar-day-number { - color: var(--primary-blue-dark); - font-weight: var(--font-weight-bold); -} - -.calendar-appointments-preview { - display: flex; - flex-wrap: wrap; - gap: var(--space-1); - margin-top: auto; -} - -.calendar-dot { - width: 8px; - height: 8px; - border-radius: 50%; - flex-shrink: 0; -} - -.calendar-dot.blue { - background: var(--primary-blue); -} - -.calendar-dot.teal { - background: var(--teal-dark); -} - -.calendar-dot.green { - background: var(--success); -} - -.calendar-dot.red { - background: var(--error); -} - -.calendar-dot.gray { - background: var(--gray-400); -} - -.calendar-more-indicator { - font-size: var(--font-size-2xs); - color: var(--gray-500); - font-weight: var(--font-weight-medium); -} - -.calendar-details-panel { - padding: 0; - overflow: hidden; -} - -.calendar-appointment-item { - background: var(--gray-50); - transition: all var(--transition-fast); -} - -.calendar-appointment-item:hover { - background: var(--gray-100); -} - -.space-y-3 > * + * { - margin-top: var(--space-3); -} - -/* === LOGIN PAGE === */ -.login-page { - min-height: 100vh; - display: flex; - align-items: center; - justify-content: center; - background: linear-gradient(135deg, var(--primary-blue-subtle) 0%, var(--teal-soft) 50%, var(--white) 100%); - padding: var(--space-4); -} - -.login-card { - background: var(--white); - border-radius: var(--radius-2xl); - box-shadow: var(--shadow-xl); - padding: var(--space-8); - width: 100%; - max-width: 400px; -} - -.login-header { - text-align: center; - margin-bottom: var(--space-8); -} - -.login-logo { - width: 64px; - height: 64px; - background: linear-gradient(135deg, var(--primary-blue) 0%, var(--teal-bold) 100%); - border-radius: var(--radius-xl); - display: flex; - align-items: center; - justify-content: center; - margin: 0 auto var(--space-4); -} - -.login-logo .icon { - width: 32px; - height: 32px; - color: var(--white); -} - -.login-header h1 { - font-size: var(--font-size-xl); - font-weight: var(--font-weight-semibold); - color: var(--gray-900); - margin: 0 0 var(--space-2); -} - -.login-header p { - font-size: var(--font-size-sm); - color: var(--gray-500); - margin: 0; -} - -.login-error { - background: var(--error-bg); - border: 1px solid var(--error); - color: var(--error); - padding: var(--space-3) var(--space-4); - border-radius: var(--radius-lg); - margin-bottom: var(--space-4); - font-size: var(--font-size-sm); -} - -.login-success { - background: var(--success-bg); - border: 1px solid var(--success); - color: var(--success); - padding: var(--space-3) var(--space-4); - border-radius: var(--radius-lg); - margin-bottom: var(--space-4); - font-size: var(--font-size-sm); -} - -.login-btn { - width: 100%; - margin-top: var(--space-4); -} - -.login-footer { - text-align: center; - margin-top: var(--space-6); - padding-top: var(--space-6); - border-top: 1px solid var(--gray-100); -} - -.login-footer p { - font-size: var(--font-size-sm); - color: var(--gray-500); - margin: 0; -} - -.link-btn { - background: none; - border: none; - color: var(--primary-blue); - font-size: var(--font-size-sm); - font-weight: var(--font-weight-medium); - cursor: pointer; - padding: 0; - text-decoration: underline; -} - -.link-btn:hover { - color: var(--primary-blue-dark); -} - - -/* === USER MENU DROPDOWN === */ -.user-menu { - position: relative; -} - -.user-menu-trigger { - cursor: pointer; - border: 2px solid transparent; - transition: all var(--transition-fast); -} - -.user-menu-trigger:hover { - border-color: var(--primary-blue); -} - -.user-dropdown { - position: absolute; - top: calc(100% + var(--space-2)); - right: 0; - min-width: 220px; - background: var(--white); - border: 1px solid var(--gray-200); - border-radius: var(--radius-xl); - box-shadow: var(--shadow-lg); - z-index: 1000; - overflow: hidden; - animation: dropdownFadeIn 0.15s ease-out; -} - -@keyframes dropdownFadeIn { - from { - opacity: 0; - transform: translateY(-8px); - } - to { - opacity: 1; - transform: translateY(0); - } -} - -.user-dropdown-header { - padding: var(--space-4); - border-bottom: 1px solid var(--gray-100); -} - -.user-dropdown-name { - font-weight: var(--font-weight-semibold); - color: var(--gray-900); - font-size: var(--font-size-base); -} - -.user-dropdown-email { - font-size: var(--font-size-sm); - color: var(--gray-500); - margin-top: var(--space-1); -} - -.user-dropdown-divider { - height: 1px; - background: var(--gray-100); -} - -.user-dropdown-item { - display: flex; - align-items: center; - gap: var(--space-3); - width: 100%; - padding: var(--space-3) var(--space-4); - border: none; - background: none; - font-size: var(--font-size-base); - color: var(--gray-700); - cursor: pointer; - transition: all var(--transition-fast); - text-align: left; -} - -.user-dropdown-item:hover { - background: var(--gray-50); -} - -.user-dropdown-item .icon { - width: 18px; - height: 18px; -} - -.user-dropdown-logout { - color: var(--red-600, #dc2626); -} - -.user-dropdown-logout:hover { - background: var(--red-50, #fef2f2); -} - -/* === CLINICAL CODING PAGE === */ -.clinical-coding-page .page-header-icon { - color: var(--white); -} - -.clinical-coding-page .page-header-icon .icon { - width: 28px; - height: 28px; -} - -.search-input-lg { - position: relative; -} - -.search-input-lg .input { - padding-left: var(--space-12); - font-size: var(--font-size-lg); -} - -.search-input-lg .search-icon { - position: absolute; - left: var(--space-4); - top: 50%; - transform: translateY(-50%); - color: var(--gray-400); -} - -.search-input-lg .search-icon .icon { - width: 24px; - height: 24px; -} - -.code-results-grid { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(340px, 1fr)); - gap: var(--space-4); -} - -.code-card { - padding: var(--space-5); - transition: all var(--transition-fast); -} - -.code-card:hover { - transform: translateY(-4px); - box-shadow: var(--shadow-lg); -} - -.hover-lift { - transition: transform var(--transition-fast), box-shadow var(--transition-fast); -} - -.hover-lift:hover { - transform: translateY(-2px); -} - -.line-clamp-2 { - display: -webkit-box; - -webkit-line-clamp: 2; - -webkit-box-orient: vertical; - overflow: hidden; -} - -.whitespace-pre-wrap { - white-space: pre-wrap; -} - -.checkbox { - width: 18px; - height: 18px; - accent-color: var(--primary-blue); - cursor: pointer; -} - -@keyframes spin { - from { transform: rotate(0deg); } - to { transform: rotate(360deg); } -} - -/* === SEARCH RESULT TABLE ROW WITH HOVER TOOLTIP === */ -.search-result-row { - cursor: pointer; - transition: background var(--transition-fast); -} - -.search-result-row:hover { - background: var(--primary-blue-subtle); -} - -.result-description-cell { - position: relative; - max-width: 400px; -} - -.result-description-cell > span { - display: block; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.result-tooltip { - position: absolute; - left: 0; - top: 100%; - z-index: 100; - min-width: 320px; - max-width: 400px; - padding: var(--space-4); - background: var(--white); - border: 1px solid var(--gray-200); - border-radius: var(--radius-lg); - box-shadow: var(--shadow-lg); - opacity: 0; - visibility: hidden; - transform: translateY(8px); - transition: all var(--transition-fast); - pointer-events: none; -} - -.result-description-cell:hover .result-tooltip { - opacity: 1; - visibility: visible; - transform: translateY(4px); -} - -.result-tooltip::before { - content: ''; - position: absolute; - top: -8px; - left: 24px; - border: 8px solid transparent; - border-bottom-color: var(--white); - border-top: none; -} - diff --git a/Dashboard/Dashboard.Web/wwwroot/css/layout.css b/Dashboard/Dashboard.Web/wwwroot/css/layout.css deleted file mode 100644 index 61db926..0000000 --- a/Dashboard/Dashboard.Web/wwwroot/css/layout.css +++ /dev/null @@ -1,1460 +0,0 @@ -/* Medical Dashboard - Premium Layout Styles */ -/* Inspired by Wellmetrix & CareIQ Designs */ - -/* === APP CONTAINER === */ -.app { - display: flex; - min-height: 100vh; -} - -/* === SIDEBAR === */ -.sidebar { - position: fixed; - left: 0; - top: 0; - bottom: 0; - width: var(--sidebar-width); - background: var(--white); - border-right: 1px solid var(--gray-100); - box-shadow: var(--shadow-lg); - display: flex; - flex-direction: column; - z-index: var(--z-fixed); - transition: all var(--transition-slow); -} - -.sidebar.collapsed { - width: var(--sidebar-collapsed-width); -} - -.sidebar-header { - display: flex; - align-items: center; - gap: var(--space-3); - padding: var(--space-5) var(--space-6); - border-bottom: 1px solid var(--gray-100); - min-height: var(--header-height); -} - -.sidebar-logo { - display: flex; - align-items: center; - gap: var(--space-3); - text-decoration: none; - color: var(--gray-900); -} - -.sidebar-logo-icon { - width: 44px; - height: 44px; - background: var(--gradient-primary); - border-radius: var(--radius-xl); - display: flex; - align-items: center; - justify-content: center; - color: var(--white); - font-size: var(--font-size-xl); - font-weight: var(--font-weight-bold); - flex-shrink: 0; - box-shadow: 0 4px 12px rgba(59, 130, 246, 0.3); -} - -.sidebar-logo-text { - font-size: var(--font-size-xl); - font-weight: var(--font-weight-bold); - white-space: nowrap; - overflow: hidden; - letter-spacing: var(--letter-spacing-tight); - background: var(--gradient-primary); - -webkit-background-clip: text; - -webkit-text-fill-color: transparent; - background-clip: text; -} - -.sidebar.collapsed .sidebar-logo-text { - display: none; -} - -.sidebar-nav { - flex: 1; - padding: var(--space-5) var(--space-4); - overflow-y: auto; -} - -.nav-section { - margin-bottom: var(--space-8); -} - -.nav-section-title { - font-size: var(--font-size-xs); - font-weight: var(--font-weight-semibold); - color: var(--gray-400); - text-transform: uppercase; - letter-spacing: var(--letter-spacing-wider); - padding: 0 var(--space-4); - margin-bottom: var(--space-3); -} - -.sidebar.collapsed .nav-section-title { - display: none; -} - -.nav-item { - position: relative; - display: flex; - align-items: center; - gap: var(--space-3); - padding: var(--space-3) var(--space-4); - border-radius: var(--radius-lg); - color: var(--gray-600); - text-decoration: none; - cursor: pointer; - transition: all var(--transition-fast); - margin-bottom: var(--space-1); - font-weight: var(--font-weight-medium); -} - -.nav-item:hover { - background: var(--gray-50); - color: var(--gray-900); -} - -.nav-item.active { - background: var(--primary-blue-subtle); - color: var(--primary-blue-dark); -} - -.nav-item.active::before { - content: ''; - position: absolute; - left: 0; - top: 50%; - transform: translateY(-50%); - width: 4px; - height: 24px; - background: var(--gradient-primary); - border-radius: 0 var(--radius-full) var(--radius-full) 0; -} - -.nav-item-icon { - width: 22px; - height: 22px; - flex-shrink: 0; - display: flex; - align-items: center; - justify-content: center; -} - -.nav-item-text { - font-size: var(--font-size-base); - white-space: nowrap; - overflow: hidden; -} - -.sidebar.collapsed .nav-item-text { - display: none; -} - -.nav-item-badge { - margin-left: auto; - padding: var(--space-0-5) var(--space-2); - font-size: var(--font-size-xs); - font-weight: var(--font-weight-bold); - background: var(--error); - color: var(--white); - border-radius: var(--radius-full); - min-width: 20px; - text-align: center; -} - -.sidebar.collapsed .nav-item-badge { - display: none; -} - -.sidebar-footer { - padding: var(--space-4); - padding-bottom: var(--space-6); - border-top: 1px solid var(--gray-100); - margin-top: auto; -} - -.sidebar-user { - display: flex; - align-items: center; - gap: var(--space-3); - padding: var(--space-3); - border-radius: var(--radius-xl); - cursor: pointer; - transition: all var(--transition-fast); - background: var(--gray-50); -} - -.sidebar-user:hover { - background: var(--gray-100); -} - -.sidebar-user-info { - flex: 1; - overflow: hidden; -} - -.sidebar.collapsed .sidebar-user-info { - display: none; -} - -.sidebar-user-name { - font-size: var(--font-size-base); - font-weight: var(--font-weight-semibold); - color: var(--gray-900); - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.sidebar-user-role { - font-size: var(--font-size-sm); - color: var(--gray-500); -} - -.sidebar-logout-btn { - margin-top: var(--space-3); - width: 100%; - display: flex; - align-items: center; - justify-content: center; - gap: var(--space-2); - background: var(--red-50, #fef2f2); - color: var(--red-600, #dc2626); - border: 1px solid var(--red-200, #fecaca); - padding: var(--space-2) var(--space-3); - border-radius: var(--radius-lg); - font-weight: var(--font-weight-medium); - cursor: pointer; - transition: all var(--transition-fast); -} - -.sidebar-logout-btn:hover { - background: var(--red-100, #fee2e2); - border-color: var(--red-300, #fca5a5); -} - -.sidebar.collapsed .sidebar-logout-btn span { - display: none; -} - -.sidebar.collapsed .sidebar-logout-btn { - padding: var(--space-2); -} - -.sidebar-toggle { - position: absolute; - right: -14px; - top: 50%; - transform: translateY(-50%); - width: 28px; - height: 28px; - background: var(--white); - border: 1px solid var(--gray-200); - border-radius: 50%; - display: flex; - align-items: center; - justify-content: center; - cursor: pointer; - box-shadow: var(--shadow-md); - transition: all var(--transition-fast); - z-index: 1; - color: var(--gray-500); -} - -.sidebar-toggle:hover { - background: var(--gray-50); - color: var(--gray-700); - box-shadow: var(--shadow-lg); -} - -/* === MAIN CONTENT === */ -.main-wrapper { - flex: 1; - margin-left: var(--sidebar-width); - min-width: 0; - transition: margin-left var(--transition-slow); - display: flex; - flex-direction: column; -} - -.sidebar.collapsed ~ .main-wrapper { - margin-left: var(--sidebar-collapsed-width); -} - -/* === HEADER === */ -.header { - position: sticky; - top: 0; - height: var(--header-height); - background: var(--glass-bg-strong); - backdrop-filter: blur(var(--glass-blur)); - -webkit-backdrop-filter: blur(var(--glass-blur)); - border-bottom: 1px solid var(--glass-border); - display: flex; - align-items: center; - justify-content: space-between; - padding: 0 var(--space-8); - z-index: var(--z-sticky); -} - -.header-left { - display: flex; - align-items: center; - gap: var(--space-6); -} - -.header-title { - font-size: var(--font-size-xl); - font-weight: var(--font-weight-semibold); - color: var(--gray-900); - letter-spacing: var(--letter-spacing-tight); -} - -.header-breadcrumb { - display: flex; - align-items: center; - gap: var(--space-2); - font-size: var(--font-size-sm); - color: var(--gray-500); -} - -.header-breadcrumb-separator { - color: var(--gray-300); -} - -.header-breadcrumb-link { - color: var(--gray-500); - text-decoration: none; - transition: color var(--transition-fast); -} - -.header-breadcrumb-link:hover { - color: var(--primary-blue); -} - -.header-breadcrumb-current { - color: var(--gray-900); - font-weight: var(--font-weight-medium); -} - -.header-right { - display: flex; - align-items: center; - gap: var(--space-4); -} - -.header-search { - position: relative; - width: 320px; - display: flex; - align-items: center; -} - -.header-search .icon { - position: absolute; - left: var(--space-4); - color: var(--gray-400); - pointer-events: none; - z-index: 1; -} - -.header-search .input { - padding-left: var(--space-11); - background: var(--white); - border: 1px solid var(--gray-200); - border-radius: var(--radius-xl); -} - -.header-search .input:focus { - background: var(--white); - border-color: var(--primary-blue); - box-shadow: 0 0 0 4px var(--primary-blue-glow); -} - -.header-actions { - display: flex; - align-items: center; - gap: var(--space-2); -} - -.header-action-btn { - position: relative; - width: 44px; - height: 44px; - display: flex; - align-items: center; - justify-content: center; - background: var(--white); - border: 1px solid var(--gray-200); - border-radius: var(--radius-xl); - color: var(--gray-600); - cursor: pointer; - transition: all var(--transition-fast); -} - -.header-action-btn:hover { - background: var(--gray-50); - border-color: var(--gray-300); - color: var(--gray-900); -} - -.header-action-badge { - position: absolute; - top: 8px; - right: 8px; - width: 10px; - height: 10px; - background: var(--error); - border-radius: 50%; - border: 2px solid var(--white); -} - -.header-user { - display: flex; - align-items: center; - gap: var(--space-3); - padding: var(--space-2) var(--space-3); - background: var(--white); - border: 1px solid var(--gray-200); - border-radius: var(--radius-xl); - cursor: pointer; - transition: all var(--transition-fast); -} - -.header-user:hover { - background: var(--gray-50); - border-color: var(--gray-300); -} - -/* === MAIN CONTENT AREA === */ -.main-content { - flex: 1; - padding: var(--space-8); - max-width: var(--content-max-width); -} - -.page-header { - margin-bottom: var(--space-8); -} - -.page-title { - font-size: var(--font-size-3xl); - font-weight: var(--font-weight-bold); - color: var(--gray-900); - margin-bottom: var(--space-2); - letter-spacing: var(--letter-spacing-tight); -} - -.page-description { - font-size: var(--font-size-md); - color: var(--gray-500); - margin-bottom: 0; -} - -.page-actions { - display: flex; - align-items: center; - gap: var(--space-3); - margin-top: var(--space-4); -} - -/* === DASHBOARD GRID === */ -.dashboard-grid { - display: grid; - gap: var(--space-6); -} - -.dashboard-grid.metrics { - grid-template-columns: repeat(4, 1fr); -} - -.dashboard-grid.charts { - grid-template-columns: repeat(2, 1fr); -} - -.dashboard-grid.mixed { - grid-template-columns: 2fr 1fr; -} - -.dashboard-grid.practitioners { - grid-template-columns: repeat(3, 1fr); -} - -.dashboard-section { - margin-bottom: var(--space-8); -} - -.dashboard-section-header { - display: flex; - align-items: center; - justify-content: space-between; - margin-bottom: var(--space-5); -} - -.dashboard-section-title { - font-size: var(--font-size-xl); - font-weight: var(--font-weight-semibold); - color: var(--gray-900); -} - -.dashboard-section-link { - font-size: var(--font-size-sm); - font-weight: var(--font-weight-medium); - color: var(--primary-blue); - text-decoration: none; - display: flex; - align-items: center; - gap: var(--space-1); - transition: color var(--transition-fast); -} - -.dashboard-section-link:hover { - color: var(--primary-blue-dark); -} - -/* === DASHBOARD PAGE === */ -.dashboard-page { - max-width: var(--content-max-width); -} - -.dashboard-welcome { - display: flex; - align-items: center; - justify-content: space-between; - margin-bottom: var(--space-8); -} - -.welcome-title { - font-size: var(--font-size-3xl); - font-weight: var(--font-weight-bold); - color: var(--gray-900); - letter-spacing: var(--letter-spacing-tight); -} - -.welcome-actions { - display: flex; - align-items: center; - gap: var(--space-4); -} - -.date-filter { - display: flex; - align-items: center; - gap: var(--space-2); - padding: var(--space-2-5) var(--space-4); - background: var(--white); - border: 1px solid var(--gray-200); - border-radius: var(--radius-xl); - font-size: var(--font-size-sm); - font-weight: var(--font-weight-medium); - color: var(--gray-700); - cursor: pointer; - transition: all var(--transition-fast); -} - -.date-filter:hover { - border-color: var(--gray-300); - box-shadow: var(--shadow-sm); -} - -/* === DASHBOARD METRICS ROW === */ -.dashboard-metrics-row { - display: grid; - grid-template-columns: repeat(4, 1fr); - gap: var(--space-6); - margin-bottom: var(--space-8); -} - -/* === RICH METRIC CARD === */ -.metric-card-rich { - background: var(--white); - border-radius: var(--radius-2xl); - padding: var(--space-6); - box-shadow: var(--shadow-card); - border: 1px solid var(--gray-100); - transition: all var(--transition-normal); -} - -.metric-card-rich:hover { - box-shadow: var(--shadow-card-hover); - transform: translateY(-2px); -} - -.metric-card-header { - display: flex; - align-items: center; - gap: var(--space-3); - margin-bottom: var(--space-4); -} - -.metric-card-icon { - width: 40px; - height: 40px; - display: flex; - align-items: center; - justify-content: center; - border-radius: var(--radius-lg); -} - -.metric-card-icon.blue { - background: var(--primary-blue-subtle); - color: var(--primary-blue); -} - -.metric-card-icon.teal { - background: var(--teal-soft); - color: var(--teal-dark); -} - -.metric-card-icon.coral { - background: var(--accent-coral-light); - color: var(--accent-coral); -} - -.metric-card-icon.violet { - background: var(--accent-violet-light); - color: var(--accent-violet); -} - -.metric-card-title { - flex: 1; - font-size: var(--font-size-sm); - font-weight: var(--font-weight-medium); - color: var(--gray-600); -} - -.metric-card-link { - font-size: var(--font-size-sm); - font-weight: var(--font-weight-medium); - color: var(--primary-blue); - text-decoration: none; - transition: color var(--transition-fast); -} - -.metric-card-link:hover { - color: var(--primary-blue-dark); -} - -.metric-card-body { - display: flex; - flex-direction: column; - gap: var(--space-3); -} - -.metric-card-value-row { - display: flex; - align-items: baseline; - gap: var(--space-3); -} - -.metric-card-value { - font-size: var(--font-size-4xl); - font-weight: var(--font-weight-bold); - color: var(--gray-900); - line-height: var(--line-height-none); - letter-spacing: var(--letter-spacing-tight); -} - -.metric-card-change { - display: inline-flex; - align-items: center; - gap: var(--space-1); - font-size: var(--font-size-sm); - font-weight: var(--font-weight-semibold); - padding: var(--space-1) var(--space-2); - border-radius: var(--radius-full); -} - -.metric-card-change.up { - background: var(--success-light); - color: var(--success); -} - -.metric-card-change.down { - background: var(--error-light); - color: var(--error); -} - -.metric-card-breakdown { - display: flex; - flex-wrap: wrap; - gap: var(--space-4); -} - -.metric-breakdown-item { - display: flex; - align-items: center; - gap: var(--space-2); - font-size: var(--font-size-sm); - color: var(--gray-600); -} - -.metric-breakdown-dot { - width: 10px; - height: 10px; - border-radius: 50%; -} - -/* === DASHBOARD MAIN GRID === */ -.dashboard-main-grid { - display: grid; - grid-template-columns: 2fr 1fr; - gap: var(--space-6); -} - -/* === CARD HEADER VARIANTS === */ -.card-header-left { - display: flex; - align-items: center; - gap: var(--space-3); -} - -.view-more-link { - font-size: var(--font-size-sm); - font-weight: var(--font-weight-medium); - color: var(--primary-blue); - text-decoration: none; -} - -.view-more-link:hover { - color: var(--primary-blue-dark); -} - -/* === CALENDAR STRIP === */ -.calendar-strip { - display: flex; - align-items: center; - gap: var(--space-2); - padding: var(--space-4) 0; - margin-bottom: var(--space-5); - border-bottom: 1px solid var(--gray-100); - overflow-x: auto; -} - -.calendar-nav { - width: 36px; - height: 36px; - display: flex; - align-items: center; - justify-content: center; - background: var(--white); - border: 1px solid var(--gray-200); - border-radius: 50%; - cursor: pointer; - color: var(--gray-600); - transition: all var(--transition-fast); - flex-shrink: 0; -} - -.calendar-nav:hover { - background: var(--gray-50); - border-color: var(--gray-300); - color: var(--gray-900); -} - -.calendar-day-btn { - width: 44px; - height: 44px; - display: flex; - align-items: center; - justify-content: center; - background: none; - border: none; - border-radius: 50%; - font-size: var(--font-size-sm); - font-weight: var(--font-weight-medium); - color: var(--gray-700); - cursor: pointer; - transition: all var(--transition-fast); - flex-shrink: 0; -} - -.calendar-day-btn:hover { - background: var(--gray-100); -} - -.calendar-day-btn.today { - background: var(--gradient-primary); - color: var(--white); - font-weight: var(--font-weight-semibold); -} - -.calendar-day-btn.selected { - background: var(--primary-blue-subtle); - color: var(--primary-blue-dark); -} - -.calendar-day-btn.has-events { - position: relative; -} - -.calendar-day-btn.has-events::after { - content: ''; - position: absolute; - bottom: 6px; - width: 5px; - height: 5px; - background: var(--primary-blue); - border-radius: 50%; -} - -/* === APPOINTMENT LEGEND === */ -.appointment-legend { - display: flex; - align-items: center; - gap: var(--space-5); - margin-left: auto; -} - -.legend-item { - display: flex; - align-items: center; - gap: var(--space-2); - font-size: var(--font-size-sm); - color: var(--gray-600); -} - -.legend-dot { - width: 10px; - height: 10px; - border-radius: 50%; -} - -.legend-dot.available { - background: var(--teal-soft); - border: 2px solid var(--teal-bold); -} - -.legend-dot.selected { - background: var(--primary-blue); -} - -.legend-dot.unavailable { - background: var(--gray-300); -} - -/* === APPOINTMENTS TABLE === */ -.appointments-table { - width: 100%; - border-collapse: collapse; -} - -.appointments-table th { - text-align: left; - padding: var(--space-4) var(--space-5); - font-size: var(--font-size-xs); - font-weight: var(--font-weight-semibold); - color: var(--gray-500); - text-transform: uppercase; - letter-spacing: var(--letter-spacing-wide); - border-bottom: 1px solid var(--gray-200); -} - -.appointments-table td { - padding: var(--space-4) var(--space-5); - font-size: var(--font-size-sm); - color: var(--gray-700); - border-bottom: 1px solid var(--gray-100); -} - -.appointments-table tbody tr { - transition: background var(--transition-fast); -} - -.appointments-table tbody tr:hover { - background: var(--gray-50); -} - -.patient-cell { - display: flex; - align-items: center; - gap: var(--space-3); - font-weight: var(--font-weight-medium); - color: var(--gray-900); -} - -.status-badge { - display: inline-flex; - align-items: center; - gap: var(--space-1); - padding: var(--space-1) var(--space-3); - border-radius: var(--radius-full); - font-size: var(--font-size-xs); - font-weight: var(--font-weight-semibold); -} - -.status-badge.confirmed { - background: var(--success-light); - color: var(--success); -} - -.status-badge.booked { - background: var(--primary-blue-subtle); - color: var(--primary-blue-dark); -} - -.status-badge.pending { - background: var(--warning-light); - color: var(--warning); -} - -.status-badge.cancelled { - background: var(--error-light); - color: var(--error); -} - -.action-buttons { - display: flex; - align-items: center; - gap: var(--space-2); -} - -.btn-icon-sm { - width: 36px; - height: 36px; - display: flex; - align-items: center; - justify-content: center; - background: var(--gray-100); - border: none; - border-radius: var(--radius-lg); - cursor: pointer; - font-size: var(--font-size-sm); - color: var(--gray-600); - transition: all var(--transition-fast); -} - -.btn-icon-sm:hover { - background: var(--gray-200); - color: var(--gray-900); -} - -.btn-icon-sm.call { - background: var(--primary-blue-subtle); - color: var(--primary-blue); -} - -.btn-icon-sm.call:hover { - background: var(--primary-blue); - color: var(--white); -} - -/* === APPOINTMENT REQUESTS === */ -.requests-list { - display: flex; - flex-direction: column; - gap: var(--space-4); -} - -.appointment-request { - display: flex; - justify-content: space-between; - align-items: center; - padding: var(--space-4); - background: var(--gray-50); - border-radius: var(--radius-xl); - transition: all var(--transition-fast); -} - -.appointment-request:hover { - background: var(--gray-100); -} - -.appointment-request-info { - display: flex; - align-items: center; - gap: var(--space-4); -} - -.appointment-request-details { - display: flex; - flex-direction: column; - gap: var(--space-1); -} - -.appointment-request-name { - font-weight: var(--font-weight-semibold); - color: var(--gray-900); -} - -.appointment-request-type { - font-size: var(--font-size-sm); - color: var(--gray-600); -} - -.appointment-request-time { - display: flex; - align-items: center; - gap: var(--space-1); - font-size: var(--font-size-sm); - color: var(--gray-500); -} - -.appointment-request-actions { - display: flex; - gap: var(--space-2); -} - -.btn-icon-circle { - width: 40px; - height: 40px; - display: flex; - align-items: center; - justify-content: center; - border: none; - border-radius: 50%; - font-size: var(--font-size-lg); - cursor: pointer; - transition: all var(--transition-fast); -} - -.btn-icon-circle.reject { - background: var(--gray-200); - color: var(--gray-600); -} - -.btn-icon-circle.reject:hover { - background: var(--error-light); - color: var(--error); -} - -.btn-icon-circle.accept { - background: var(--gradient-primary); - color: var(--white); -} - -.btn-icon-circle.accept:hover { - transform: scale(1.05); - box-shadow: 0 4px 12px rgba(59, 130, 246, 0.4); -} - -/* === QUICK ACTIONS === */ -.quick-actions-card { - margin-top: var(--space-5); -} - -.quick-actions-grid { - display: grid; - grid-template-columns: repeat(2, 1fr); - gap: var(--space-4); -} - -.quick-action-btn { - display: flex; - flex-direction: column; - align-items: center; - gap: var(--space-2); - padding: var(--space-5); - background: var(--white); - border: 1px solid var(--gray-200); - border-radius: var(--radius-xl); - font-size: var(--font-size-sm); - font-weight: var(--font-weight-medium); - color: var(--gray-700); - cursor: pointer; - transition: all var(--transition-fast); -} - -.quick-action-btn:hover { - border-color: var(--primary-blue); - color: var(--primary-blue); - box-shadow: var(--shadow-md); -} - -.quick-action-btn.primary { - background: var(--gradient-primary); - border-color: transparent; - color: var(--white); -} - -.quick-action-btn.primary:hover { - transform: translateY(-2px); - box-shadow: 0 4px 12px rgba(59, 130, 246, 0.4); -} - -.quick-action-btn .icon { - width: 28px; - height: 28px; -} - -/* === DASHBOARD CHARTS SECTION === */ -.dashboard-charts-section { - display: grid; - grid-template-columns: repeat(2, 1fr); - gap: var(--space-6); - margin-top: var(--space-8); -} - -.dashboard-charts-section .card { - background: var(--glass-bg-strong); - backdrop-filter: blur(var(--glass-blur)); -} - -.dashboard-charts-section .card-body { - padding: var(--space-4); -} - -/* Google Charts Container */ -.google-chart-container { - width: 100%; - min-height: 200px; - border-radius: var(--radius-lg); - overflow: hidden; -} - -.google-chart-container svg { - border-radius: var(--radius-lg); -} - -/* === CHART WRAPPER === */ -.chart-wrapper { - background: var(--white); - border-radius: var(--radius-2xl); - padding: var(--space-6); - box-shadow: var(--shadow-card); -} - -.chart-header { - display: flex; - align-items: center; - justify-content: space-between; - margin-bottom: var(--space-5); -} - -.chart-title { - font-size: var(--font-size-lg); - font-weight: var(--font-weight-semibold); - color: var(--gray-900); -} - -.chart-subtitle { - font-size: var(--font-size-sm); - color: var(--gray-500); - margin-top: var(--space-1); -} - -.chart-body { - min-height: 300px; -} - -.chart-footer { - margin-top: var(--space-4); - padding-top: var(--space-4); - border-top: 1px solid var(--gray-100); -} - -/* === DONUT CHART === */ -.donut-chart-container { - display: flex; - justify-content: center; - align-items: center; - margin: var(--space-4) 0; -} - -.donut-legend { - display: flex; - flex-wrap: wrap; - gap: var(--space-4); - justify-content: center; - margin-top: var(--space-4); -} - -.donut-legend-item { - display: flex; - flex-direction: column; - align-items: center; - gap: var(--space-1); -} - -.donut-legend-item span { - font-size: var(--font-size-sm); - font-weight: var(--font-weight-semibold); - color: var(--gray-700); -} - -/* === PATIENT BREAKDOWN BARS === */ -.patient-breakdown-bars { - display: flex; - flex-direction: column; - gap: var(--space-3); - margin-top: var(--space-4); -} - -.breakdown-bar-item { - display: flex; - align-items: center; - gap: var(--space-3); -} - -.breakdown-bar-label { - font-size: var(--font-size-sm); - color: var(--gray-600); - min-width: 100px; -} - -.breakdown-bar-value { - font-size: var(--font-size-sm); - font-weight: var(--font-weight-semibold); - color: var(--gray-900); - min-width: 40px; - text-align: right; -} - -.breakdown-bar { - flex: 1; - height: 8px; - background: var(--gray-100); - border-radius: var(--radius-full); - overflow: hidden; -} - -.breakdown-bar-fill { - height: 100%; - border-radius: var(--radius-full); - transition: width var(--transition-slow); -} - -/* === DATA LIST === */ -.data-list { - display: flex; - flex-direction: column; - gap: var(--space-3); -} - -.data-list-item { - display: flex; - align-items: center; - gap: var(--space-4); - padding: var(--space-5); - background: var(--white); - border-radius: var(--radius-xl); - box-shadow: var(--shadow-sm); - transition: all var(--transition-fast); - cursor: pointer; - border: 1px solid var(--gray-100); -} - -.data-list-item:hover { - box-shadow: var(--shadow-md); - transform: translateY(-2px); - border-color: var(--gray-200); -} - -.data-list-item-content { - flex: 1; - min-width: 0; -} - -.data-list-item-title { - font-weight: var(--font-weight-semibold); - color: var(--gray-900); - margin-bottom: var(--space-1); -} - -.data-list-item-subtitle { - font-size: var(--font-size-sm); - color: var(--gray-500); -} - -.data-list-item-meta { - font-size: var(--font-size-sm); - color: var(--gray-400); - text-align: right; -} - -/* === PRACTITIONER CARD === */ -.practitioner-card { - display: flex; - flex-direction: column; - align-items: center; - text-align: center; - padding: var(--space-6); -} - -.practitioner-avatar { - margin-bottom: var(--space-4); -} - -.practitioner-name { - font-size: var(--font-size-lg); - font-weight: var(--font-weight-semibold); - color: var(--gray-900); - margin-bottom: var(--space-1); -} - -.practitioner-specialty { - font-size: var(--font-size-sm); - color: var(--gray-600); - margin-bottom: var(--space-3); -} - -.practitioner-meta { - display: flex; - gap: var(--space-2); - flex-wrap: wrap; - justify-content: center; -} - -.practitioner-edit-btn { - position: absolute; - top: var(--space-3); - right: var(--space-3); - width: 32px; - height: 32px; - display: flex; - align-items: center; - justify-content: center; - background: var(--white); - border: 1px solid var(--gray-200); - border-radius: var(--radius-lg); - cursor: pointer; - color: var(--gray-500); - transition: all var(--transition-fast); - opacity: 0; -} - -.practitioner-card:hover .practitioner-edit-btn { - opacity: 1; -} - -.practitioner-edit-btn:hover { - background: var(--primary-blue-subtle); - border-color: var(--primary-blue); - color: var(--primary-blue); -} - -/* === RESPONSIVE === */ -@media (max-width: 1440px) { - .dashboard-metrics-row { - grid-template-columns: repeat(4, 1fr); - } -} - -@media (max-width: 1280px) { - .dashboard-metrics-row { - grid-template-columns: repeat(2, 1fr); - } - - .dashboard-grid.metrics { - grid-template-columns: repeat(2, 1fr); - } - - .dashboard-grid.charts, - .dashboard-grid.mixed { - grid-template-columns: 1fr; - } - - .dashboard-grid.practitioners { - grid-template-columns: repeat(2, 1fr); - } - - .dashboard-main-grid { - grid-template-columns: 1fr; - } -} - -@media (max-width: 1024px) { - .sidebar { - transform: translateX(-100%); - } - - .sidebar.open { - transform: translateX(0); - } - - .main-wrapper { - margin-left: 0; - } - - .sidebar.collapsed ~ .main-wrapper { - margin-left: 0; - } - - .header { - padding: 0 var(--space-4); - } - - .header-search { - display: none; - } -} - -@media (max-width: 768px) { - .dashboard-metrics-row, - .dashboard-grid.metrics, - .dashboard-grid.practitioners { - grid-template-columns: 1fr; - } - - .dashboard-welcome { - flex-direction: column; - align-items: flex-start; - gap: var(--space-4); - } - - .header { - padding: 0 var(--space-4); - height: 64px; - } - - .main-content { - padding: var(--space-4); - } - - .page-title { - font-size: var(--font-size-2xl); - } - - .quick-actions-grid { - grid-template-columns: 1fr; - } -} - -/* === MOBILE OVERLAY === */ -.sidebar-overlay { - display: none; - position: fixed; - inset: 0; - background: rgba(0, 0, 0, 0.5); - backdrop-filter: blur(4px); - z-index: calc(var(--z-fixed) - 1); - opacity: 0; - visibility: hidden; - transition: all var(--transition-normal); -} - -@media (max-width: 1024px) { - .sidebar-overlay { - display: block; - } - - .sidebar.open ~ .sidebar-overlay { - opacity: 1; - visibility: visible; - } -} - -/* === MOBILE MENU BUTTON === */ -.mobile-menu-btn { - display: none; - width: 44px; - height: 44px; - align-items: center; - justify-content: center; - background: var(--white); - border: 1px solid var(--gray-200); - border-radius: var(--radius-lg); - color: var(--gray-600); - cursor: pointer; -} - -@media (max-width: 1024px) { - .mobile-menu-btn { - display: flex; - } -} diff --git a/Dashboard/Dashboard.Web/wwwroot/css/variables.css b/Dashboard/Dashboard.Web/wwwroot/css/variables.css index 0c0a7f9..a99d515 100644 --- a/Dashboard/Dashboard.Web/wwwroot/css/variables.css +++ b/Dashboard/Dashboard.Web/wwwroot/css/variables.css @@ -1,201 +1,137 @@ -/* Medical Dashboard Design System - Premium CSS Variables */ -/* Inspired by Wellmetrix & CareIQ - Modern Healthcare Aesthetic */ +/* Nimblesite Clinical Coding Platform — Design Tokens */ +/* "Clinical Curator" — Material Design 3 tonal surfaces */ + +@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&display=swap'); :root { - /* === PRIMARY COLORS - Rich Blue Palette === */ - --primary-blue-dark: #1e40af; - --primary-blue: #3b82f6; - --primary-blue-light: #60a5fa; - --primary-blue-subtle: #eff6ff; - --primary-blue-glow: rgba(59, 130, 246, 0.25); - - /* === TEAL ACCENT - Fresh & Medical === */ - --teal-soft: #ccfbf1; - --teal-medium: #2dd4bf; - --teal-bold: #14b8a6; - --teal-dark: #0d9488; - --teal-glow: rgba(20, 184, 166, 0.2); - - /* === ACCENT COLORS - Visual Interest === */ - --accent-coral: #f97316; - --accent-coral-light: #ffedd5; - --accent-violet: #8b5cf6; - --accent-violet-light: #ede9fe; - --accent-rose: #f43f5e; - --accent-rose-light: #ffe4e6; - --accent-amber: #f59e0b; - --accent-amber-light: #fef3c7; - - /* === NEUTRALS - Refined Grays === */ + /* === M3 PRIMARY (deep blue) === */ + --primary: #003fab; + --primary-container: #0354dd; + --on-primary: #ffffff; + --on-primary-container: #d1daff; + + /* === M3 SECONDARY (slate) === */ + --secondary: #505f76; + --secondary-container: #d0e1fb; + --on-secondary: #ffffff; + --on-secondary-container: #54647a; + + /* === M3 TERTIARY (healing teal) === */ + --tertiary: #00524b; + --tertiary-container: #006c63; + --on-tertiary: #ffffff; + + /* === M3 ERROR === */ + --error: #ba1a1a; + --error-container: #ffdad6; + --on-error: #ffffff; + --on-error-container: #93000a; + + /* === M3 SURFACE TIERS === */ + --surface: #f7f9fb; + --surface-container-lowest: #ffffff; + --surface-container-low: #f2f4f6; + --surface-container: #eceef0; + --surface-container-high: #e6e8ea; + --surface-container-highest: #e0e3e5; + --on-surface: #191c1e; + --on-surface-variant: #424752; + --inverse-surface: #2d3133; + + --outline: #727783; + --outline-variant: #c2c6d4; + + /* === SEMANTIC === */ + --success: #00524b; + --success-light: #c5ede7; + --warning: #8a5a00; + --warning-light: #ffddb3; + --info: #003fab; + --info-light: #d1daff; + + /* === LEGACY ALIASES (so existing rules don't break) === */ --white: #ffffff; - --gray-25: #fcfcfd; - --gray-50: #f9fafb; - --gray-100: #f3f4f6; - --gray-200: #e5e7eb; - --gray-300: #d1d5db; - --gray-400: #9ca3af; - --gray-500: #6b7280; - --gray-600: #4b5563; - --gray-700: #374151; - --gray-800: #1f2937; - --gray-900: #111827; - --gray-950: #030712; - --black: #000000; - - /* === SEMANTIC COLORS - Enhanced === */ - --success: #22c55e; - --success-light: #dcfce7; - --success-dark: #16a34a; - --warning: #f59e0b; - --warning-light: #fef3c7; - --warning-dark: #d97706; - --error: #ef4444; - --error-light: #fee2e2; - --error-dark: #dc2626; - --info: #3b82f6; - --info-light: #dbeafe; - --info-dark: #2563eb; - - /* === PREMIUM GRADIENTS === */ - --gradient-primary: linear-gradient(135deg, #3b82f6 0%, #1e40af 100%); - --gradient-teal: linear-gradient(135deg, #14b8a6 0%, #0d9488 100%); - --gradient-warm: linear-gradient(135deg, #f97316 0%, #ea580c 100%); - --gradient-cool: linear-gradient(135deg, #06b6d4 0%, #0891b2 100%); - --gradient-subtle: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%); - --gradient-glass: linear-gradient(135deg, rgba(255,255,255,0.9) 0%, rgba(255,255,255,0.7) 100%); - --gradient-hero: linear-gradient(135deg, #667eea 0%, #764ba2 50%, #f093fb 100%); - --gradient-mesh: - radial-gradient(at 40% 20%, rgba(59, 130, 246, 0.15) 0px, transparent 50%), - radial-gradient(at 80% 0%, rgba(20, 184, 166, 0.1) 0px, transparent 50%), - radial-gradient(at 0% 50%, rgba(139, 92, 246, 0.08) 0px, transparent 50%), - radial-gradient(at 80% 50%, rgba(249, 115, 22, 0.06) 0px, transparent 50%), - radial-gradient(at 0% 100%, rgba(59, 130, 246, 0.1) 0px, transparent 50%); - - /* === GLASSMORPHISM - Premium Effects === */ - --glass-bg: rgba(255, 255, 255, 0.6); - --glass-bg-strong: rgba(255, 255, 255, 0.85); - --glass-bg-subtle: rgba(255, 255, 255, 0.4); - --glass-border: rgba(255, 255, 255, 0.5); - --glass-border-subtle: rgba(255, 255, 255, 0.2); - --glass-shadow: rgba(0, 0, 0, 0.04); - --glass-blur: 20px; - --glass-blur-strong: 40px; - - /* === SHADOWS - Layered Depth === */ - --shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.04); - --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.06), 0 1px 2px rgba(0, 0, 0, 0.04); - --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.07), 0 2px 4px -1px rgba(0, 0, 0, 0.04); - --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.08), 0 4px 6px -2px rgba(0, 0, 0, 0.04); - --shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.08), 0 10px 10px -5px rgba(0, 0, 0, 0.03); - --shadow-2xl: 0 25px 50px -12px rgba(0, 0, 0, 0.15); - --shadow-inner: inset 0 2px 4px 0 rgba(0, 0, 0, 0.04); - --shadow-glow-blue: 0 0 20px rgba(59, 130, 246, 0.3); - --shadow-glow-teal: 0 0 20px rgba(20, 184, 166, 0.3); - --shadow-card: 0 1px 3px rgba(0, 0, 0, 0.04), 0 6px 16px rgba(0, 0, 0, 0.06); - --shadow-card-hover: 0 4px 12px rgba(0, 0, 0, 0.08), 0 12px 28px rgba(0, 0, 0, 0.1); - --shadow-floating: 0 20px 40px rgba(0, 0, 0, 0.12), 0 8px 16px rgba(0, 0, 0, 0.08); + --black: #191c1e; + --gray-50: #f7f9fb; + --gray-100: #f2f4f6; + --gray-200: #eceef0; + --gray-300: #e0e3e5; + --gray-400: #c2c6d4; + --gray-500: #727783; + --gray-600: #424752; + --gray-700: #2d3133; + --gray-800: #191c1e; + --gray-900: #191c1e; + --primary-blue: #003fab; + --primary-blue-dark: #00174b; + --primary-blue-light: #0354dd; + --primary-blue-subtle: #dbe1ff; + + /* === GRADIENTS === */ + --gradient-primary: linear-gradient(135deg, var(--primary) 0%, var(--primary-container) 100%); + --gradient-tertiary: linear-gradient(135deg, var(--tertiary) 0%, var(--tertiary-container) 100%); + + /* === SHADOWS — ambient, tinted, never black === */ + --shadow-sm: 0 2px 6px rgba(25, 28, 30, 0.04); + --shadow-md: 0 4px 12px rgba(25, 28, 30, 0.04); + --shadow-lg: 0 8px 20px rgba(25, 28, 30, 0.05); + --shadow-card: 0 12px 32px rgba(25, 28, 30, 0.04); + --shadow-card-hover: 0 16px 40px rgba(25, 28, 30, 0.06); /* === SPACING (8px base) === */ --space-0: 0; - --space-px: 1px; - --space-0-5: 0.125rem; /* 2px */ - --space-1: 0.25rem; /* 4px */ - --space-1-5: 0.375rem; /* 6px */ - --space-2: 0.5rem; /* 8px */ - --space-2-5: 0.625rem; /* 10px */ - --space-3: 0.75rem; /* 12px */ - --space-3-5: 0.875rem; /* 14px */ - --space-4: 1rem; /* 16px */ - --space-5: 1.25rem; /* 20px */ - --space-6: 1.5rem; /* 24px */ - --space-7: 1.75rem; /* 28px */ - --space-8: 2rem; /* 32px */ - --space-9: 2.25rem; /* 36px */ - --space-10: 2.5rem; /* 40px */ - --space-11: 2.75rem; /* 44px */ - --space-12: 3rem; /* 48px */ - --space-14: 3.5rem; /* 56px */ - --space-16: 4rem; /* 64px */ - --space-20: 5rem; /* 80px */ - --space-24: 6rem; /* 96px */ - - /* === BORDER RADIUS - Softer Curves === */ - --radius-none: 0; - --radius-sm: 6px; - --radius-md: 10px; - --radius-lg: 14px; - --radius-xl: 18px; - --radius-2xl: 24px; - --radius-3xl: 32px; + --space-1: 0.25rem; + --space-1-5: 0.375rem; + --space-2: 0.5rem; + --space-3: 0.75rem; + --space-4: 1rem; + --space-5: 1.25rem; + --space-6: 1.5rem; + --space-8: 2rem; + --space-10: 2.5rem; + --space-12: 3rem; + --space-16: 4rem; + + /* === RADIUS (M3 scale, generous) === */ + --radius-sm: 0.5rem; + --radius-md: 1rem; + --radius-lg: 1.5rem; + --radius-xl: 2rem; --radius-full: 9999px; - /* === TYPOGRAPHY - System Font Stack === */ - --font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; - --font-mono: 'SF Mono', 'Fira Code', 'JetBrains Mono', Consolas, monospace; - - --font-size-2xs: 0.625rem; /* 10px */ - --font-size-xs: 0.6875rem; /* 11px */ - --font-size-sm: 0.8125rem; /* 13px */ - --font-size-base: 0.9375rem; /* 15px */ - --font-size-md: 1rem; /* 16px */ - --font-size-lg: 1.125rem; /* 18px */ - --font-size-xl: 1.25rem; /* 20px */ - --font-size-2xl: 1.5rem; /* 24px */ - --font-size-3xl: 1.875rem; /* 30px */ - --font-size-4xl: 2.25rem; /* 36px */ - --font-size-5xl: 3rem; /* 48px */ - --font-size-6xl: 3.75rem; /* 60px */ - - --font-weight-light: 300; + /* === TYPOGRAPHY (Inter) === */ + --font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; + + --font-size-2xs: 0.625rem; + --font-size-xs: 0.6875rem; + --font-size-sm: 0.8125rem; + --font-size-base: 0.875rem; + --font-size-md: 1rem; + --font-size-lg: 1.125rem; + --font-size-xl: 1.25rem; + --font-size-2xl: 1.5rem; + --font-size-3xl: 1.875rem; + --font-size-4xl: 2.25rem; + --font-weight-normal: 400; --font-weight-medium: 500; --font-weight-semibold: 600; --font-weight-bold: 700; --font-weight-extrabold: 800; + --font-weight-black: 900; - --line-height-none: 1; - --line-height-tight: 1.2; - --line-height-snug: 1.375; - --line-height-normal: 1.5; - --line-height-relaxed: 1.625; - --line-height-loose: 2; - - --letter-spacing-tighter: -0.05em; - --letter-spacing-tight: -0.025em; - --letter-spacing-normal: 0; - --letter-spacing-wide: 0.025em; - --letter-spacing-wider: 0.05em; - --letter-spacing-widest: 0.1em; + --letter-spacing-tight: -0.02em; + --letter-spacing-wide: 0.05em; + --letter-spacing-widest: 0.15em; /* === LAYOUT === */ - --sidebar-width: 280px; + --sidebar-width: 256px; --sidebar-collapsed-width: 80px; - --header-height: 72px; - --content-max-width: 1600px; - --card-min-height: 120px; + --header-height: 64px; - /* === TRANSITIONS - Smooth & Refined === */ --transition-fast: 150ms cubic-bezier(0.4, 0, 0.2, 1); --transition-normal: 250ms cubic-bezier(0.4, 0, 0.2, 1); - --transition-slow: 350ms cubic-bezier(0.4, 0, 0.2, 1); - --transition-slower: 500ms cubic-bezier(0.4, 0, 0.2, 1); - --transition-bounce: 500ms cubic-bezier(0.68, -0.55, 0.265, 1.55); - --transition-spring: 400ms cubic-bezier(0.175, 0.885, 0.32, 1.275); - - /* === Z-INDEX === */ - --z-base: 0; - --z-dropdown: 100; - --z-sticky: 200; - --z-fixed: 300; - --z-modal-backdrop: 400; - --z-modal: 500; - --z-popover: 600; - --z-tooltip: 700; - --z-notification: 800; - - /* === BORDERS === */ - --border-width: 1px; - --border-color: var(--gray-200); - --border-color-light: var(--gray-100); - --border-color-dark: var(--gray-300); + + --z-fixed: 50; + --z-modal: 100; } diff --git a/Dashboard/Dashboard.Web/wwwroot/img/favicon.webp b/Dashboard/Dashboard.Web/wwwroot/img/favicon.webp new file mode 100644 index 0000000000000000000000000000000000000000..5220dfd8c27e1d507ef60f609ec5dae3a2f5868c GIT binary patch literal 12432 zcmb`ubx<8$&^~x^*Whl!<>Kye3GN!4;O_1g9D=*MdvMp_8r<C>xZLIazWVJ}?f$!` zX6n>*&FSgs^VHKaH7e2|&`%%$peZS)q@l#4g$Muu&_7Qw#D9mVoYJ?VF8}~U?~qLg zCAX81=zL>PQ$7(v+P2bEAg=h4T5t`15+!jMa7{cAC}G&fdm|RLciyg(mA;Y8MT3vN zgI%_9DCU%BqW!%~gcnVOhHtHz_g|P(Jel0I))oxiLwN-_OZ8 vR$75o=G@*(^H zt_R1x`=5hNz@+~x0{3`Rx=N6!6Z2+h(iO9DY0(uQf@I30t0$8p4|%$986@$OGX}Cq z=$oaa**VRX@nNPG)_)kK8k<{v)Hf-fuyaoT#JWf;Z<8onIL5h1FW)(N?$4mN+!%B4 z11hCj9C?bCS)62^IR|cIR}^K}9@`HK0LLwk>Nk6JKWEFBXTzk~IfA=B+QMSa!(e3) zzrifj1WaMH2FV%91Wd5zkET1kyZ$VVZW2TNGK&L>zAT`C6ay~8VJK_0E>#+CO|1P| z*|(V=#U5(Kup26Q^g6%4&8QV)$yYF2T885=V{)jJM{`!>QJz*t;>0S03skD!Pq)=* zI0{1V0h}y072Jv|qn%I$bN#%h`l>cg>o?F=#<`Wjs?Gm!!mf-4?i9=|!<U#^Ar}Zz zY>e8lT{wN!XWMzLd}l5E$K5U&T{$RMxj`}c?SnX)^yh|LmK&$K@Oym>YGWx!8?sv3 z=I$_u!Dm?4bBb;ZkI79J5^zAFlK5$%)#9v9(KA#dUF9jo(2cQGZ_72JVQkaMj$cVj zF-AJd>s5pi7Hb%C3^G}+<QRl+vlmFXEy7DJ5toFKbS_K2A*RlDK3fO?o*Q3Mn`Ly+ zr>C&^&v?Yt8_K8YiEf7GA9O=@vVNIogR~mz-AP6gG_RV9ktYVRgwEL5xE}A*ZelLV z#PIZpw^CxY-4p8D5|5^DJExnBzfeP|&jx90vYG|w4o=wH^qJ!6ZRQg<+EM&SgliO> z>wISi;gmL+E=h)%7G7pv1eW;9gagy(3$!26>sKD99<ss&Uuorro2-{OtLk?irymRl z{9s|dy_;-t+z{z9h0-n(Kzbo#2ezxN$Q{sJA1IA_HY)gOT3K_$mhKL_u9L6lNM@dW zM;WT2pK7N}|6&V(msk3^C!7K&H$wWzFNj^C{YSVqJ>M)U-3gpAU|+3_S!-M&$=9AI zDr0X?&Hpa20a*(+=1~nBtq^$qo(2QIp!xrl?`i`CXEyo4^>X>YorWS^y+UVppavV6 z_WUsys1>$S9}un!T=DjH>3g5KQqj2^mY(Qtk>{4{vg4@-d6JsNokS+)PtT@s;{v@6 zlBYyozWe`(am6E={px=QVIXTc#z2_%Zhn%MDtJ*pj>(Js@#NnIIx+8a)u~^|543-C z=R4xLu1|7{X7$#ZljIgWuOCNT<}$1+N;Lbx)-6SO^a6UM$MRj*{At>D!GK+6p4B$l zqGxirU_|atL(TMBO1r(fH@x=Fal?O6mv}b8Ltdn@ToJRbcHEb+)=MK4o-Sp(0Rc1S zb9Bz2U8&oF{kYz05<3hV-1Tk|8Vfpw`K95oIk#nUzc;YcqUk>VZSaW>Ty?M_z0(yP zC!-qH)ykYS=}RCfcB{m7RcS`HbU+qTj@Nu?(n^(z@UaXG(&P&mBbQu8&>=Z(Rd<*6 zwWM9XxS^K|v!Yn4PEa7*HAyzF9>X56QK<ie9#o<qijrR8OdegMSFk`AqW2WK^;RTI zo>Hb2xRNGjfHre~IERHW5mtd!zHkKP(o@gKDtCmX9e(`NnRhA_*y$62Y3(vn3ae>4 z1MKE0?j_i8s#9;N_R1vbb+M0ww04>C?1+RuOl_gFkHrC<UPnu*!xdfvq-S$ZS<|j6 zBX@BS2#7ujZK+mm0pU{|i`5)UdubO`LZ4i}BE$4T8g$ogqk~_tl(wtECjzC2mTb&W zYOj%rlmkabv|%;l9fl;hkfFM|wx`bFXp~y5&~;^45Cto@Rn4vBEaz#m(9@&{@n^<+ zj;-p<u)vi`ho#^lYxl5BxHxUqUaSF`(Bbz|ds_Jn0Sa=9OeA69=DhfQyRS@zk6AX= zpFDCY`KBd{%Q@7cNo8j(75xJifq%w(8P)VM{CW~ybfzSgoWjy*l*`44!%6OsjHk%5 zh<<dp7@O~hL2|RGL)pgw&R9C1doRxGm~HqU%t}eh+vL%3wMr(dN}>7~=R^_Fp%H9| zSpz;vvnl18Hcm^rzi114=Oyvt*j5{L9wS_+Q@#hHD}y53r~6%!W-HXU(TsQr+rCJn zn<jY_K;gx*t-8&VZYnftFSKm)nUeIMm-k)Gbe9Y7hmA5?&8LaQ8S<6JJWhKI4B~kT zT8yL$-8QhA<{WpY8&(!&v%HFpd$}U1j0=X$ss>j!xox50XnEsv(fN$P3Cq^A3^*u6 zp}lQ4-zN~|*o~eTN%uWYr$t!ar@o4=!v9J%k}nOHQU0eA{)y#F(q}6c!^Gss=<?|P zEo39Mzx0-`3vdM>V&%z~cHc<hps`}&RpGn9CgP>8yGmcEz>4D_ArUy{d-vY$In)iH zYtLw?F&?s-q}0SZi)${L&HspJ-;X<=r6>GyD~{s}Ybra@8gn~EOFK`z%J&5BY=OW3 z>GPSDx*jl^p{YqOpYxMsbA|UE5Vs$dHD(;o^olFaOKvc`rjwiX9MQE~O5OY6>28)3 zmMBPRW*>J4hUXj-+5Y^GNtP!LRHQtGk(ur1O*=|d9#I$-PMQ)1W~EIg{H9f1)|*t@ zTLM>7TTj~4J0wvXmIuz!1mz!HTNik9p1J<#mYu2NRqcuHPI(%I?3mbR+(+YwPxWu- z>GlKXj{=gKmmxJ-L+5|iT#itWQ;n|kOIJLLQI!oJHc7JiPQ8R~7aN)E=c`qvzPpF+ z`UIqtdSzteB@qs$3DR0Feo_Z(;gSwFqcf+-3QPD{RFi4GYmm;D>Zp>L4TlvsR%E-m z$j~K=swKbRIV)bduw<W5g&B|P$J0n6=7r)eW4zAVqJN<vS?}6eO)F_))TbB!Mm5w# z8hfRG?@<I7exDKY^y^bSxIqOu(fX?Rn2rirmZeY8pivREkQIis=RAQWG`cHv=X(xk z0xyY|cM9DU9Q8{DmJPBt>3b4HJIVFTJXeH~n?!vr9J<FgDNl!W)Ms!l6qnIEy@U9% zv>9kv*(6pES?J4|AQO(ROKQ6f0dRVbgbtI!(h+~DzJ>4Eh5L^}7%=fjR4h;k58Yq& zgaMFxW9n4Eb<Hp79OoWZ4)=Aw1^|tbR#SRRJW}N!DBiFy@&1o+WH=U8({Mmy)m@o^ zh72lS$elKsG}ej72U^GG*f6P6B@*=wPAf#%E5B3HE=VmpXgcwQ-<|S-?q4`~R3e+r z>8*lN!-|ow@R|Q9?d>MrrhJFUsKCn1EFT>J6kW^{mT{N%@)CSXa_P_p`lnC1PM|qQ zl6XL0UMX81mT3P)8MPG`WS~;F6Tixqb+k%(RyvcPl5QAx$lgcxQc?^220M$&!-Xe; zE-YhUnQc`!H?S9oE21&Y5`?d7R#bcen0g%IXUqR)dPUT+TIV26-{++CHB`nKZ&5Uk z`eBJGT$RI@2;}uv^E*2j%6N;bwD<9;!clm2Nxf3VNabes|68_>sAR3BvS~90H%BS2 zmZ;-r<&b=PSmrL5&TxQFmHgESk*IKZ8{0~*E!jT4-UmuDP^yf5oYv=@aPf?C#~4xf z#1BOobYmZ<`5yFxS^JZwtQml$rcK7hkki{*(%7GDQwz7J46@cI&T?uQM3(-loTR*a zLLrw+@P=C5zU<72N14o_3`(fY4!y~0+0eg3RguOtP4cXT8|c%JMk@X2tM}TG#xICw zQ^YmmTg}flI3uO9UtjK4>gq0-(46YO_LBUrh?~t=9aR*m(_A7WlRe<zQB%;Rs<=~~ zpc2KT?ZH39>}o+<ve<R7{cn=qDr=n96S=W+Z_Q0Mi_vmCKRuG*OL=sG!Aiiah<cO2 zdZ#iRd+}*xQo$4N1oOqri=T@{Ns<b?qzs)Tg9aZ5W?3Y${48RJfp*|*F)^RvsYSW< z0g#|9(zzjXU>=m>ejHYl@_P{;gj?z&@w;7Ck2s6%*F1i9wL^&t9FVt2obUUo9IG6x z)h>E@<JZ`x4v54*{4Ub&!C&NE0Etnme5Sj0p-3o39Hl1x8>)|O$c4g^M=rkyJs+mi zjw>Ua&-san%nQWRh-P{1KSKV<ubaUqX1dH^==vSA@kWOwM-?f+g+~~%(Vi4-EWn$w z%t@C<*>O81syxQn%qef7wqA8eBNrMS(3kJ^N!Hl({;-dmdU0CrI3eMUuCblhe)Ov0 zc8ZBWjTv<Li#2scAfAS-zG8{3knkDzQ?r@d4Nfsx|BLza-NYovs8``DX|b6vA}8?4 zmxL#kbFTVlQ2B)CHNEFQr#iNwXo(CzgUv>f<h>}7;H(brJ<3k#87eSjrLI9dpVMm5 zt2Tw*F92mN#;~PT3dt&l`a!>t<&rR%g<7N1Wou%U%QUz9JB>vX^Thf;*g>2%z0cgD z!Mf`wP6;*W0}#!qegXi!R$x^T<$$b%&)EBDUcHP9H?Z+YlrI_hBq|ekEkZQ`;;%{H zAtq4i9<=Q9-pAG|D2s9+q8Sqh91P?K3B*UA>|U>@x@#C!ve4vWXkGBdX5Q*(-l4Qs znnB3(;)r^Ju-dqGB;S0Y`!p;=oyn0O7bQv{_Vpfd0c}16hf-MD;)hwL#|;0`&^%DM zXp}(DCJ%;iz$cFy)6%6yr{oO6N_R8Amq72*fnrK47wvz@;_%qx>b(W`4;!e9_kd{% zPH$TD>#$Te!Tm564@i?p7k685Ae7{ElFrVRSt4<92mdOge1IPk`p9*Kxht^UWW1vz zs01Wae<()>hC+|EYX;Gj377sp&<Fs5=uK3UZ@YurEdmv0ded$XEsTrUxO~9}n{Xm$ z)YvcPxHG+^1Y0RIpbex<dJ}$@^1w&p1s!gYGw4a(T3Y+qcFG}*O6KjF2(IkBv5JCD z*3%fQwORp-_d9<t(?SSHSQA76v1}THGFp?i=3{<3X?+!_lLF%L?<ao5j~jVe^CJT0 z?*M7+Z#bq{9_}!oiOkuIv%@p+Qo>jgA13D*P!g<J#u}=3oxT5H^aCdX%M{BK{*xmd z!FfmgqgNoa1P-YCmq^SwLxFKx2jnZg>R1tdGzomA!-&hwNH&>H_i_I^KdN8lSVq$2 z;lOOwePuKfqA9UU<|Y=E!tYpK&;wAC>80WxH-;s_ud+;$SO?6mTS{{I_RRf>Bh((& zMGMA+6q2(hY5&zmR?zlbP7W_-#RSDzp*<}Sg@F~c4>P&2C6^URk*6v$vq9d1c%LM? zzQ_I%;wb2@8BRi{B15;@fM~>_gbfp}$vtqJ32g5aAA|GbbjXeZcJLJMn|M6@wH@!3 zQ&`#AVE(Lf_=?UG^Zik1E*lUMeK|3hL&HmJoG{F!u>2Mt>pw>2$9qSqhr&xczG3%U zXhm>eH&2cWav3$WO5KcHKg@744;-&@9fXgh+SU6Hf0KKzl+Q(C=94HF$3s@P3`F<4 zLT8OWY}ytQFc3V0*W@yEy1-=ec#gi>nN{Q!{S3vn9{9wDr+{Kq`H+gHelOf>Y_M?; z9>`heCUq7eEcBqpws(K^>uR0c3^sk``%o7Ue?IavFLMdU$z<;TQ6|G*bd0WQt;dg) zX#TJ=9A{_nyY9W-EapWIl8do<Ie7Mu%}&e}KLmiL`zjcPeukBrD}%ZJnELxuRX>J- zfUQj66l?u-b0d&IgX#AjPi&`GDLxF}XkF8UJ{t8E!^-fo$uKupfd~!0&cW$6mRwF} zAD2Ro@Si)O`2a{_Q_DCRIAHsme#@=&#M|%-qD!)oWyELNo~D=8kR7~2QeG_*uKkxh zY$fl<_p8rxwH?tVBNWCdt$TE7lYh<GihjoNG7@*-I-aT9zXk4$ZpIb1J*kQhx8J6W z+LmDA;TsbS-%MSSwL46SbIZ$Tv07CqLX+{c7z$6nebCMS0j9BY+nF=Th&xDv8fD&B zz5c>J?Eo^yUnTrlCRv1cBJS@8e;ldpeQf>7z_Ai{4ZJE9P^jqVbmu8;tzX!%L9`ub zYSA}C0i`eaqc;OIs97FQ;v9aqP{h_{G%BAZ63dm+Oq@ZN!;Wum-g6g8`*J?KiLX$= z^AKG%ubu=qzf~@%n)kx<f{|~vyJnRWRL#oNzAWzE(Xf_t25~xRIg6KV_gOj>e3n@Y z1oH)yE<K)iHOJ`p|20ku=iX6|7q+b$|G`?Js!3XJlGGLuqPjS{1g#bl>u`X=s|f3R zLSB{`bU36&s{VL2fhg4_qlS;O24<PWb!aTifF+Wjc}crvwW}kpFHkhNka+d(!2{cQ zgtk!LWP-RbnrktQAB4}OWBET9)l01AL}kmGO%@4;n>=~yQP9rAbw!`k-4JffLur#` zf?@aXYq!<rZ$K#lK{fmfzNI6m35<bXEyN}@JSDb&(C-F6ex~?NJLHGA?ap=U{ewM> zZ*K}y0G1+4wc6D6gglopOJpLm;$Fo4pmz!KtXOKm;_DO8u*Ppv08Yy{*(EL^91cV* z#mwuNd{i|r-D7_i%g$F4gv0;u#@PSUD+7O^eRl82x`_aQx=27a1U&!}04c<Z7b)J8 zpHKdEfhYJH7Qw{s&1c??3l{JJk<>M!2XOA=-3;IVK4*W`t{EB5^3nGpe(nCx`gNIX zD+lcQ%KoJIk?_R-qWr;-9|7rq>h*Q@&;E!-;)8!L+6>s1MJ+>eEbdIW!)?^ZALT>p zq2re3C^gh;;g;JEO#UJNPUfThwZ~9!^*#4V@sDsu&tLxyKXre=3&fkr8%-VDb==O@ z8h8X80nUG~1b>c-T4n!s{XF4Je<g77hvFmn$o=iA0{qys;Ts^_;12@dfulC(-_60b zAGv_7oh}jK9Pr}3E7%j<`WkmtI*WFG1Xg_5x)uJ^^$P!?_n!Olcu@)lzio+--uZ)H z0e;{Q@LQrk;Qi&{YTJGr?$~}?ylr=^R}TnL0ZEVOd9qPeoxY+vt#Dy#Gc}&$<!;Sj z=B9Qx-=Y1Ty`eNGdv$yzJ6Yi0<&wt4dHGSPTSJSvsiGi%b8;g;{r_jNgGb_A8x_`= zE{VYZQNl1cvmDsJT{h<g5z$__`hQkeJaDqy{Nk!fX#8Tl^kXX!KH_0CTd3lHA7X0| zKweh7hfA6k|2Vc;r)nySr;zOh-u-T(OgGQGq4qxpi#o1`W=8wsbv7clWqDB-(d93K z&A}gx#a!(FS+>?>hkdBrii<ol=E;pnYyjSJ!W2E?kHD?YyZX<3!J&XgwCU()EO@dY z-gU^m566viFmXjj*?S0@d9Gs0=Uej8z9(hn`}lXJ$tZQqS!(M#EqP2UPJG!_@BDPf zc+0NpFB5Lm5NvU|Z~4bDZC_$O><xBYn6xFq;N4|sx=+U%tgQDVmU_PII<hc<!5?2C zYHTBvq`+b3t2?i*S#`Ce@Wp_X!tNhp)M$gbFOH?a#|Q~+fAG^W5n&SK{O@Q#L75bP z`k)*y2e(W~!sw0`2o+JjA^+K63i#Rw!!0=on(EJ88&Qmq+&6Lp*WUiXZ~5zCmVsa- znp5TWtMqy33;yTknI~y@4$XKC^*rC-WWMEoB4x|#TiWM#?hV%_x_n+bXxqka24Gt| znSE1|)d{->Kjc?nSVk%Q2ai71``H3KF4CqKDu#=gl~9g^CR!L+Fsaplu+TJ63fgd# zDT1yc|61JlD4f%;nxpdH7V{C{{Ql{VhB(e<K0z=(zM>1`WF-%`^*$44gbnkFrV*?n z8tWQ=@B<y>lkJ3trX|FFOtbfn0nh(}jC+wf!S`rs^$fADCHP9pB2xcV6cOJb9z*F9 zsG9-PB*qw2g?*koTmP%=KWus_bL~?I<S0D+`2QW%0Kms1W8UZYf&Y78664x~!TCJ~ zr8cXzIF^;RepH?{WLyFbga`<bp-om$P%QXKJ{O)|is@(vMtW|?UW7IargMu6yiMZ5 z{Oi}mjq<$hTNv7Yi)GpuN4XPfp#a>L+@ZJ0XDC(RFYlaDr}Eem|Ni{kYXG3&otOs! z_vJYeD-r=lO8PAYqWAdS)A)c+Ie?L61~-fAfm>Y26D9hC@p7{mYZ@9nitp??Ky*(+ zH-{aqvy}mN<FkC&TFy^>2~NSzDwwl2bOcT3+wN$;5)UIZ6LFjI7-<D;TGDw^AjV}D z4-ftnxP!$s3tG(ziP?FyE@6RR2tg!nlg)!jQR)_4n)lN7JHsmy3suYEItk5NC=eTm zr&ne0S`<es_L2453j{!ZxtUO+5ZUyKcHgtT2tWE$<whzKM!DyFppJ8$=&y~bGP$bp z_AxZ+Mc6)=98t^{sDmo@uR{R_!sXSf7S>53*6rg-9}`o>20iq&)k0somK{rhx==hl zUavxGu|XmI@9aDVDhop1)srP0?bor(=CwiR!-o&?{8Q%~KZL@*iHMP%YSO;uo#viC zd99ek8u%EM>g8El*D#}wgU2hEZy%&~%1J+9^<S!Q1pkDM#GbBBwmBu@SCWAct*!3> ziu<s~g_A9Yc8_IxR}!5pt*T3v8|o!L)u)1vHi^%0Qef@y`-B&)N;Rhn&am{YM!;YZ zX{2Wq0=5V7yWr@DnXZ60dwmWTeM8uh#C9zOBS@-8@h9>l?!bf%<Xn!GFXL!RevIv8 zLtpg%&4?{Ih+Ok8uW&$gxc=I%rD_Hn?QecqMOM-d2!I-;V;O4VEPKEMlvN!u!HtMg zTf&sNP9qj^D?5><<P7X}63>i2@dnj1sR$X)>KKW+d*AmAr}@<n(mOhLeiZ{baG~}k zmP~Q;vVN?eXy0-<G6qf#PR5S;OHgY5cKS78#0Zj%D*2ILuS?*^vMS?5P7{|RbyE3t zeAWvjR0=T1{d>)4MraWWg&}fd{bTq_r7tz6B6=O@9tq($+&A6jP8-<Zar#swf5N(o zRZg}qSi}2ZE)mL@qYyHd`NicRLDcsblXK_zJ`G{%d}~NO`hsCk1HtjWq((S7W!gf6 zDknogsE)fbRc)Si13=G@B+bhM0JRUc0BMjfGy}=9RjIG|gmwE3uWC)}cr=sACX;|I zGgDpz9c9Sr=#Utuc!+#v$Qr57_|=P!kZJ~Zn8`94uE1Cs<M-U3DQRV-uiB+)Qh`C0 z<}1~8aF1Xxjd=N+6He=*G+umiX=Lp=1XD#AxT#vO@CaCTJ&$1Xu+H6e-`8nFz42Xo zWht(j*#Ps^2eO@}{vkYFY3NeMHD0}!163km%c<W&75vfh2(R(a89nLY=Qds(at9+H zN$q&t^@%#1LnwAm4l{dz|4uUQTY#zSN*~b^@FL8zoMdvY6m>M?rYsG6%N254`}%8x zcaVU)zW-4ef`L^{n?vS@sQo>28b?CZ`;PO=F2?NlqoOwqLqnsglgThy>AZ!zFCWQ8 z3xqCERfcRkLL{?m%#HnAKqf`J!@LUUwvQ)8tJe*o9jD++vY%`BwvQG4W;fuPv!l>l z;~sbrwc(TY&{y}juJ|YpJ-l~sW8J`0V<JBwOc{&qAnG_f*~5@m`ZQ|mY>Y)C#sxFH zDB+8v_06IJeCmDTp~G}WHuqJ2Y$Y^i*moQq8)aJS%D7Qho(}I`3_`z_h~8dyhr@G3 zgb>{Nq5igV$<=*m)RAqI)W51mRYyOsyJQ;?#$qH#J$`3~dHytZE8+F<5@kQ3Z91;~ z9`wZLY-2hs=QPsk=>O-nr^xLUk?OkS!nGup5ouHc-bWalt=G`LJw(*mlPgFyN~%z& zl&WK{cwn2lo4CPtP?2R5TX~Ozn4cAX=%uR{fJ91N)LHL)c9*!{)_y}@h#gYXK`#Fq zeBwftLb`}ci~llPx8CV1S>|w2T@L$!lf{P8;(@R929>3$4qsC;X-hyR<Nb&><Bv^Q z=X5}tFSvmjSBMI|9+OQutE=MDg_RkoV&hm4Q?X5oBLvak@&|T--6^2SK^lE^a<kK7 zMrtBGKF7o)6uVyRPx0tF&h3b~y4h|9l>mDLc=z(h*YO~z4{2<jMaYN7)Z?3ndx0Dj z%x#=P%X5Wc9&Pt4DppIPKx<z99!-X=+tgxAQhixsgJIkr<TH`4BsTLbV$?09!^4xf z|Ja%kp78cjLeb<vaMt9VNyfYC?TwjOiEq@ubd^Ji(2xCWJZ;+8DE(;32qGNEGQk$D zZegQB6DXeM<H}kjBWOaZPm#d|F_C61-e7I-fv=?U(LoZVFVi+*6i5`o;}psPti-G; zx*y=$P9vlEo=u2bApJ^&xrJzrH=V%yT)gbyR}_9s#1s><tpw5Is5s*X)4I6Xy~sd6 z;dwCf)+iD)k(^iM^W&j&ldl+4dUwt60P50U@fvNCTlg)~U1=^MXDNJ)7L#wd(LlcP z(tr&r69ZY?KhWPU=vd>XSbdqm#3g9w^N3pk$Ko`mU7^9<2lW^XTZZjNCnc-I;VfXe zE@{ZOl{rV*=7;X0XNu+@MM>#(;*9y>5oh7t!_;Jgu$nvlOL2shdwOm=NF7Ym#OW;5 z=QMxZ+~VyB)OtKw1M0p~tsR@|_37S7I%#bwCA*nnd+$@H_oD4L!BK}Q`FrW~R?{zX zd~<ha$#zXyx*39Rot@ghZs1?C?fv%s@G8UIY;c)<8aD95zDDNgJL02f;D8h%gGCWH zqHMym7xq6LVj3w*o$M_(UHhqj<a3rsWI1VW!X9x0eEeQXs$bu06TWVw=XtrN8Z3*6 z@`TM1(lb&}VP2<4Q@wpi3MJ;pOBabYScsZvduZywbD&#d<#D{<ZJ4I1?AQp<X65pr zcZGuF08hd8G2HP?+(-Wob)JINZ7qUB^GCSbRXs!D%a+>S%uv)V*Itfn&U1}?I%lo< zd0i_0&KgI)wElJu7u*f~enXWTM+gPa10O63Y)`(1GlE^81`K%H8!E7!F&~@F_YP_O z(o*%P)^*^JmP4(fp+%1gwQ6iZkX9SHA&C}&kkB=qkj%1swtT_M1*?vlrB(JgBTQ}F z^1$qMGw9Zi*ly(6;S)D}qsM-s@x%Fz%XFzTG3NIdJrgs;$J~VY&lU9(O&JUKo?IvP z?{WXO(-;C=+?dsA$A;>8q$OeST_atKi0!pEau4t}u8KT_RgkoAKeWXO^eY=AbKPz_ zZiDsC{IelA`b%zl8sv>;-Ogt4{e>oH;DCooWNhV!Rg!;p{AFH`pMtsPN$ehv?lX*{ zkOOJN6Z#}+OVI?%%N&Bn>6DEs3Egm^A|ECy$1op^4~PAirO1Os{MNanq~;TG2;M1X zG+fyY7xJz*84GjA-JTye>D$Ug9OPuhT?Pvxv$eSxh19x{LqW|6|M+spp}e*M14vJJ z{&e655^Py}U*r?I=Xs7b_Lp>NRK5I4-@_BF5I1dIGJW>rM`2w^SVr~*e^Mw~kV$&P z{qjqSmx=Q4qSm2!)xpfA)v1`jG1Qkl3_Ay@i!+u+c$?=Zx#n3h3mWQK2tHS#b5J-g z86PR;c~Cm%t2z9=r48Q)qBv0cUSc5Xv!xnEC@fi<kHHu2+CFV<T$y!)D1ywCd5S2< z*gGN8S;nL*IA#a1p5%cmi|_oV(mhwV4oMV^aaY3*Y55n<)*JfWFM7M1LXDUrLufbd z7xO~zS=P8|0DJz|+C>w;U=;X_l094Rl+(IM+1J9pfkk)bx-8CYSELS8`xFvdxPmU6 zxq7^xkBpwZSjn0!Z=+_@0{Wj__sPOo@h^8NRg>*sWO)i6Zaj?m0j2>k@7<|;bK-bD z#&>!JWzys~-$UZiX)Jk`$_X!1SKNWQdFH{Kh2oX5h8(K`<h(CUCpab&WovIJ6px`| zA!C>Ve{(g}4qu|l8*EAVW_ADUNntheT2`VQRtMs%bvU9*ImFyb{N-68$HY4dDp^H$ zA2ljACcV&ePFFiYO(Xlu@X$GS$Kx0qwYNHa+}%7F^oXcsB1Gm7ZoN@13a3cpn2uD` z0zm{zm|RGywVsVD!1>x7^Jv_jry2^?jGm<kjt>5My{AYI-|r1`%&<IqXJ>(qL5KEP zFt`#B_3DEBBFrfuglV`02A>_Sq5N=eFJ8tFQ$M<}N*Desh_%{_J4;mPY_4EiWu@Tz z;%_m!ISo$5$izBTv3CSjbMj}fmDWi1(KirNW+k1skFc(Ym=M01?3TaX^zPoc9IlO| z?uyML$WZXLqXjerrUOnH{^rOfgYyl!oub!x*(KgOliY2*g@9Gv%e!hvsL6pJVp;vH z-#jK19VQCPt{?6m72I9iV8}>H?y>rn>8R%tSpIfuo$k!jpB+Re4YgR^`c}PMuNr~) zNxJ`Tq?BsdlwSuEEdS^+z0;;Dm35*uvd}?wpuh}(Hw7|O`%4I+O(=fMAEwU|K0Ep( zk(|>6Mz*m!3Z66uVnLZN`Yysi4iwqA3gY=uY#$u2=y9Xc?5|p++6j1-+Y5dJCVN7& zpPW(%8J+uib;acHSh<|$zkVAub&RFb{(jPz?-@1TG2aUBo8t-Pf)w!Lun9##Cplz4 zgVLO^JghMnSPz3zBRC56s6dT@x$yuG)zO46ZE{*~?K~tvyDKK$lLkP0N+VP}de|e> zSMn7oAmZaG!@MW|#`4Wuj7|E@5J~q|H*tyGz|Wqow+1=IK5T-tH4+cC4!t_Wj$?2x znl)p%D8$j03uRW1LT)y)0AQM<iKvj~=+Ev`YjDIVBY1i7w{P658P{PvpR1!0YmEF` zQbDI}U92*cN!m33J*9L>c;0BrHp3ZXAQQT@6@&)DquNGY)Bc}~ilqnHi(NX18zUhL z@{7_uYi^Q)w}}H?N$l*1H`R(E!Yb5))xF1f*<67@T$#$)j2K+IU+GaY8hlUHkF+l> ze$O>cHl8dFBb3nh(a?rxa$}o>UtJBWoSdst<P3nY!*Zwl#vG`5j<9sXlZ*MY_;nHX ziiM=!cV=21KW1ra63lgUQc+Ek)(+RkO*Z}QP4vphyniWPh7rTW(x}JIl}iY9X$A=u z35HgWA3OM&nJIfwXrs&m<I;j<|FDdR>b<D+JjZD6?Y1ql)NPtv8y#{I7!&gL7ySA4 z=XY$108CkY(jMfynymWua#R-S;7$t*rIr#yXRzHb*nh7#2(=EA>dU5HrymV_`b-|` zdVb~Jp#xcL$)nLb*~52L4)ouy3JK=exJ!d2T0g)ie7nu|ddt>{2kiV<@5y85>tNgV zEqG$Mfx=lWB&C6RwTA1gZ>{#`kkJ|QgtUu^CfE^83VR_wB)`HJ7bQo@vpo9hn@QvP z3(u%(`f@YY#sWmGj_5d=)CX8j2zBbmO2qGOgZqRIFS%PqfI@u|3A;+OU;h29$zBwT zX33*aO=%==O?1WkoyeGAwWOusITbnXBY65n5^Nz!3c+}Wd-?P)+=`69C&8Q9Pf#I{ z2H55ESf16!=FNL^EZKSKk37s0ytQB{7*!wvrl?ro`@N(RY%5vg7Jer>YGSx!!2&(k zA5UL{%5PP!nFvcaB4ux3aaxYdFa?!+okbnKR!f#&?4|LxxE?~vb%Jnsn?2wrsAS<> zy7HnyW^d25@QaehLWL$draT7zZvAaseRa96MAInwSzpEa!BMD|CaJpaW>6G*FEjFK z16$&}hFkqIMX{{VbAO@wPn-KS9Q|mAw$^eB1<8v9a2MEquZb7?;j8G}6@@%N#{mdj zQwd}h?9)aLK8?^ch$j(YM&a122!?&6b06!xmoIXnil!%CD#?Sxx!s?BpQzuG&I(-z zR2AZhf0g-j<w#1lzn)d+*zZW)j;K#F%KpS4aGZ3qD^l?LYzPw-5AkFuj<SzHBcdZD z@wj1OcTf{0V6`Rg02wx^gUVri<HB^YQY5R<nProyxdW({qMN5!&fLk<;QFof;rS^l zIMvl*U3C(FVU*K+h1CPNh9#`e^wPAaLk@?dDAMS1qQ0a~fg)0xbV2g5bT@>WFh69A zssFCqq1?6SFK+Q}GQNClva+aFl2sq}+yFxR>7jYY4g9&FolO=u+sdwt9WsL_#Xpub zdv$F@Dz{Xa&NFx$-TCj42h!(qi<Ds9=r`SCtuzk8@8rq9u8`$`lt5Anawi>9CoX@M zA_Yzp^F5mUg{{;t;c-X~M9T=nuCmxY-8e36ym7vzf~FCYkZogI<+~a!x_HJn_(*=R z2IFWzM@&<H*VSEp13Ttnv28<!p{dcsaiaD@=ypjrl;WF`Vt3nf`ktNi)zYD44T?nR z*{vuDOnZYM^ly3N9~_^ZthsaCO1?}5HLp?>W>eFriuFNI=g&C}2o-JQm=XTEXKU6# z5IBe>JeM28o}6VMq0k>;anMwph3=ZcF7Mg-gH|eNyZ$vB)dA&44Qzura9&Q;pKVeU z@w}(oWs3ASEsBdm#;y|w#6xFv=U8bRV<LmkNJ%eZk^b3>n1ZGCq8>RvBfk>TfGKnN z?IX0+$}c`(+#TjKWu$NVACI+c-~OXnJq8M;VkOAxSK<Nu{BnmrE*wFEs6|Ib2D^9V z3{J~;(btp<9@C+sHM?SddmQp6C&mL4Tf%PeK@2q==9?~md;N%^CvA)Fx6I2GT>@b< zkNJVcJ<;)V?k&%*D->ybvdvYPpSDbL)f9p=D6a_hMw$2T4W{XaH7zax$WT@EI!tXf z`>w0_#Hy8$T=xvoS;zSjs5hH?XSMm9{)#Jz^pH(-fc?SWJoTl;Jg=dI!zR2QP7nS7 z>?Et&sT(6$<m%si*YtcSsMq2rgY)2(yNf&IE;ZueY?cMmO)OSLRk7YmYs<hym_U$` z`zc0n6fvllu!fkudj~<mOjxPwTT2P}fE;ieqpJ8GW${XN!$P=<QD{~)__vM$O$qlf zDX>-0n78svjMf6y$~&gM1(%<Gyy#gLe@V5;Lb2&WS}u)iWrcIbg<I=jNG#Q{<L>HS zW@%?YcVn${_~=g7on?QUrap%O4r@lsPAxepgv3v>1mrXU#N7Apa)cw*Y8VxHOfca% z3DPJ)+9CBtd#Jy{0MJr106BEAF@u!8hx1G^faa%?i4~oM-W<~&z!qI%F=mi6KCsxi zS}bqd7WYS^<FeNLe$?1j2JjaVie6Z)Bj}`ix0}vaaki3ni2Yx&Sy8FoTfrNbuWZ}o z6!J}A3U_n9cdOmX#`(K)l}X9ltHIx2p5|OX!XgFcYrMO;&+a%sNKN@#E<F=%QG+@u zA`qm)6<39=^`I)ro39t4BiarlXV&$TFTyVuLw2GYnaqj{547DwP&hp{9NxIqGr#Kl zj$e@O%JLr)4d;BF*kqF7@<4NIQ`F}@bC|Z<FI=2gMN+;C9$`C(uX)<?VX<$D<fGFs zhd!r-u6y}1_Da=^{?uAH0pM8pYV=p~XYqh63Y%Oz9`QZ2U$Pc05myj#Jb(z+bxX^z zgAe1}P=~G)H0OL~qnrH!H{=}h<6ZDgI;ZUBPh+<xz#E-cT0vkeLzV^B+P3T~5x&Nv zQmSi#fxr1n@4N-wVPr8jBt_%%+!*I3*`9zp3fMAH%?j3j11%&zKnhVSM?hSX&1By6 z8{V4Sy2ge@wUnaqq-&GE4hWVYZzXswB$u!kcUb5Wn$zh^3@XDfYedP7#41vt5lABP z-YiNjtMz+&JSJo}GcvLp*Rqg|oBYcnOy7f2)TMQLk5glJS09I=%^g`-(;^>5p)=j= z0|w0q6@FxVo~_xS;oN(NHa@+}1%{M~8;=N<JPN{YxjvJk;@JY_jN(6fW_rpbJk;Y) zcMyhslFhQ*UTh-cark3aDo@877)nFC6|4CT_gtDbDX|!Emqn@+6S`e17`H2oNT|Em z)*Uuo^+EoN`&y77#*hV>w{kUXN_I_+v5!oDP;JZPjqp)yXy?fPTPmaXJVJnJ^{uJo zZ`?cFsc8rJDN&d7Qk|mZU*R7LFE48H>0%k}cqDlaJgk+FDG!a@u!_^Y7o(vfpGM(C zUV%uEI2tH1X&&qJ&oGhb8kfvnl62|#`;N?vDuc}=Zb}piV@GI(yo_f?!kX7sL}%a= z!(cqLT_I*x8qP5lm2V~Rd?fjmd!<4uv@1E%dRIu})P6t=bQC!@ES7r+s~*iG>X180 XwUro*v-CXg6r`AFe*Smx{~rGr9WaI8 literal 0 HcmV?d00001 diff --git a/Dashboard/Dashboard.Web/wwwroot/img/nimblesite-logo-white.webp b/Dashboard/Dashboard.Web/wwwroot/img/nimblesite-logo-white.webp new file mode 100644 index 0000000000000000000000000000000000000000..67f4d1c8f508ec41da3deb0ede67cc02be5f98bd GIT binary patch literal 1478 zcmV;%1v&asNk&G#1pok7MM6+kP&il$0000G0001A003VA06|PpNI?Yv00E#yYuoWg zyOY$mGac3)+qP}nQ;cofwr$(2?f$53JqJy`_sg4{&RP*M0r=aZOro(&8;w|b;>Nu< z&u&~lx?;GSwuZ49ay+V>1Q&f+)zn0DG(8+gVkQjM6wS^Rl9*v@<j{<+$BRhJpW{sd zKw|IdrmtSo*=ZzZ_(UTBb;qCmo|u>Yskb^gTp=-YH&_COgRZ5M;?m<*YST2B6jllQ z)&?+}5ln)=xTs0{BvN>%gHNG=W2V5M0Ah`(rxs08Nnv3v;DM52KfwNE6|sl7sDWz| zDK6~<-S3JL`T*U-NYoHHcV=HmdBW~zr0|;uq`pNY@&^mv4wH!2Y+!kj#6KkAYhXEB z$!c9Vza<rxb>_-EfSAL218qZzIpOK<d4oH3?C*0Ym)>ac)Pq<H57`3KvxqVIWPdv- z_ul{2fhXgYS%NAaw*`#%5o5TI0~jrIcmf(+%u|wnxuXnd_>P4C=W7lC_I>>h-For! z>w~=$J;8CuUI0*c#FmQ>?;o4w48X`glZ0Qd3&4EDjT91?d#8tt7wtD?{(2CsGw=rq z&zLI#>TQT2*2*^>IcZT!^m(AZGRyIwiSc7Yz+rDDi5X<T#~!L4u&JlJqn&;KBMHQM z#uSoqF(h(VE)0Vd5K(DfZXPk0E!9P>>m>RKE*h386E%4dFfg9Pk22w59;x!VEA+RP zk_yWj@^DTC<+}{w@|;vVg9EKE;$@8h1}Bn=4{{*&Ef?!iBj|1@Bi4$b8ym*;?m1%V zxo<_)o=H^)j7bya-}zdwy-uw0yILAUsh-#BK%y`M9?<v+Th8IyK<hwa44q{IMx${- z#d0nnn-VT8cBdC0o1a6%lYC48K+kQc&-z`f{YJTH1F-O^p}J=4JOG#sJ`|KwMpT;p z>rj6)04{e)c;yLa0Qx<S1r?Fv!f%T#!R25|@ihbhomy@C^=T#70Ra6u$s|0y9{@Z5 zfGQFmF<G03HswUWCm2Dn?#Lg+c-av!T@p_szG}#Ua{&=iz}nW<igaD(ekI0YKP^ax zhLE`LwN+;vTaAcf9v|4Se%Fm}xx^aR2aum5u^&oQCwZhq^oMnT0kI_dUU0ZtHRW6N zVZ5W1#2?2)>k3sQ4FqaGB^Bn#c`%7l!7CS_TMVi4rHlvc6s>Tr9x%Izn2X{*+`sc8 zvbfr6aA|!<q<}7f#W7+{y)fC`SPPIEHChuvl`Z&y_TnrNQdgM+&3+MM;37GMnr(V- zzzN`ey?`NdLv27hGmV5tOf!LEi2}eD95*@?Tc#xC&S(n&F4swT!4?|;(wcoYU%CI{ z)|sUpOu@1Ba5KQP_2`9*7Wqu=Q3C)hR;Q5gFD(Jc7rxFS<ss9x_%ZntG0hT!otH$C z@bcYeK)r+ilJKV-p<5M2UmVx6wz-zXq;{KW*ZwEQ)X{*^iZo(O_W;kkiHOQlV}k>t zQY(r1R}-MoTVh@Wu1!CZ3a{D%<1&c(t`=YLNEWSPqc-%nRuXfVGkEWwC({3;0Qo&q znpdVIr5X4ilrPE~PoPyODLv!VCSE~WC#d6;61Mb(`oM%VQd-&w*k3K96V!7=K11nw zH^6XT1u3sw0P_z-l-M2W+960t?z#2=ntdR_#ZLo>=#4kj*LFv?g0kREo&d~OWf6P+ zCS$0z_u8xHw@zwi2tapC2#NTtH8iEoq)#N`_p!Rrj9Pt9B@lbj%P|Jfl)7t!%2_hs ztZOKRCe?EpzwdcOdO<-!UgDQ4YkE7%pn)Yu)=o}N4kkMIt0DkaP&gn~0001R1^}G_ zDqsL$06sAkh(e+vAs2)IAOi%nfB-qw!RB5E;$EXJBG0Sc=w|3HhHig3AhnBpVo>|) glQ4h){{DQFo&WzN=HLJMCjbBd0A&CFlPUlJ0EZ&4(*OVf literal 0 HcmV?d00001 diff --git a/Dashboard/Dashboard.Web/wwwroot/img/nimblesite-logo.webp b/Dashboard/Dashboard.Web/wwwroot/img/nimblesite-logo.webp new file mode 100644 index 0000000000000000000000000000000000000000..2b6de97f1fc4ef6d1b289d2d740b2ff6b692471e GIT binary patch literal 2358 zcmV-63CZ?SNk&F42><|BMM6+kP&il$0000G0001A003VA06|PpNFW6O00EGOZQJoS zcak=#ZQJf_+qP|Q<!sxwZQHhORjb?QN0RS-^Co|H91$@A_;09jK-KP3maRLmWBIc2 z-K%&Q8k5Qs?_`nW--mk!C=Exz#7D&QZ6iYwIPVYfd_OZ#ZWvsq{Ux4H`Z+?~%F9jP zTD~Ek?+01|aBV*O)Vs9bM@s3F<-#K3n76<cFsixcD{0P}Y^FE<7m4Si8i1<f4U&A+ zMNeWLlg1OZM`lad=m6BYMyyv|^&;RcY0L=*c4{e1mce#WA+cX`(*u`>q&crVa8lEc z)<Bs%#Py<$aLS{k{Z-2LVhxYufxel<`G88a3B>V;D=d~1|M7yA&t)r`X#$rMq{FNz zp;Q-$`F(RB<~}ihKfiKxo0>ISk2{r5dt@S&Bi5n~o<RGb#Q0-<3s-0_z4pGjNajiD z($3ceR8xyd`m0f%V01DP35eX9sU>q?JtH9GI7$DRXa@ie)rQR8u<z`NO;cKWLEw@N z03e|4%spq$Z0Z{XKsn$$N#7d;z^eI<FC_8r=CZ=bb{8g^K(f64MUtLANCx<he?hGI zM@kA3ltpy4iHSC=W~YepW<20D^#}31pb#U0)bEa~8tm%qQhmltV%=f`w0=c=^J9fj zT-HEDIe&irCgy^%N_cD`?o)*D&D6&AYcrtXYvO;$NQ4%o%d;U+PAniDX8DRRO9#dC z&ER*OblXIPll;=#0gc|1j#EVFnak@$JdDN{5Npx19VzV_)Neg{{lk2<?INJjH!eSh z8N+@XvA&sE)(l!z@spnsU6YG|&^>IK%l&~e_lfag9|tg6^?Lc+P6(jQ18Hw(g#)rd z=_LKb01E(6g|!$qdCu73Ed%5L9EUmSE@*rd0P}{6AEc?JJy_nv7J$!gl3ujJ1Atkb zm5*~tbJpcPmJqTWr6t<}fU$R}dUZ>BDFHy$=OamfS|5Phm`B9;sGUrNkQ|~Xy(}SF z+3FfGZgc|dl0Om0LqP&KekUS&KC!BUCZoXq*NHJ_D1bK4i0@$mjP9xt(dUyZr%hY1 z`%V_IzODs$ZzJBD1i%I@+z<Hy&EFIEF(UNTP2mJ%Sj;OT?!~o52+h&O+XjIDS<>NW zTM?9Zba2uisPmq5xf?=`<n}L73EA)*V$Obgdi&NRkMq=ei($Ts)9p%t-3DU)xU_kY z2>_^~5}r{`kQhL(uN=N6TLGo+665Xuj*x0S>zGUw_^e1{c%I@3$Ooj6^at%!V6}t5 zfm0tBX!*Xig*AYXeI)&Fq7?vzf7{u6PF*^*Ii;2b1h(no0+>WM?c1+k|4x;i0l;zc zACi7H20&oajZD)1q^C?A)x}RkT_M>g=`BgmpJ)O^ul-BXw+V#U9QwMye?>n>Q>CqM zr9p>&5##5^fc3OYV*Ka^krPP$-?tY}KV}j8l@OrpEn+Qh522NZ)OfG62Kr_Y^J)n0 z`ixtCf(+(MiT#G1Xo&sJ>0=|n?<{Hknyux9Kg6%{hszOvpvoK4I@dn_t%eV=(8s2K z**^C&0{Ui<)_gx;vD$}N=x5dM4B5+l0J{|=v3LL+ZWGbdSm<lSB`Lp`#Q~^vk0cjd zctu2eJ)pnlqrYj$zBbASfYZzzV*fQn0loGbw0M3(ix33>^WJZWy=Yqq45i1w2gLDs z9T-UCHv4`N`=9N#WH6Mf!57mQia+e_=L^H?UMFGu)t6tseED?u*rHygZDEjQW;Ql9 z)<*chB34j1Am{@C08khJodGIf0AK(<F%*YFq9F`EhO`g?f>?kxm;b*3_|43B(S7vc zqb@z5PT$1u{BKvEFdwczvcC2`ARn%sU><-TTwk%@0{^oAwch}r$iKN>7tmR}U(kc~ zB|AY3U*AH>*K6QOx0UKIkV_qB*YpnDZ{pO|P3m*PX-tR$P)3gwQmU@)iXX5Y+y0_v zzRe(elf4y^9$M9Qt4oPjneFmeKCbwYOspXP@io(0&w{nr^g+8HT*EU${Yo_fJ&4&J zwj_C_`B|U<0RI1A7!2S4<B3iG{3n@YT;Dh1ciT~6Yz7x!8Iri4`+o4>`wgWNKL6D> zhX2@YCZp~;lJji)-JnE(Gmwl`e=mv_EkXmP&SCmyxDzPS^;oNd6b(I_^4a_v`Euq^ zl7QiTG*oD`O!)>?hbB$`&YbL=YbIu;j_92Td-<D2DlDw|7{-e;go9?dWvNAT&Z_v& zSqFziV}jHB3aqnSrUP4$)j|2~&B)sv^HEp|uzLEC1Z*A;N=57**%<He`j{dgW6CjQ z|C}4W@T_Ajp~GA3nen~YUC1PEnU#K3!z$JFl3(TjTgjF-QmEc$#=m!qZ`g2&R+-%u zhMG4<C`RW~@OaAQ4bSp3NVHx&j;Rt;yQg{!SWiSwaFhowpAuweC|S_QqgIPt!Phsm z5LRn5x?wayOxdGSrW|b0y@`!0WN{_0WIJ!Lf`Vj3W7@plfR$z*>IdT^@f*+;O1eAO zW$2djojgP;IBY1*2YKxJ9^3!IgTbxD$lX*|e*k9?SA#AWm12dkYG0KAbOmck5<j(L z=Chx4&(SM2Zo)60=wK;M64~2_Ek1mEQ_$n|@l7CgmKnxv#4;^WuzM2__H)U=%%Ap9 zzX#NGtJPHfBH8h_s@FIYyT+PnZT$TFBm!DB#_Leg=oaqc4I%Wg{XNck0VCF+HdG*5 z^BHL#c#$X?vTOw#P}B;~$T@YTdsLJj)Pf@>u3)&41vn1*tqI7D=Yt`6f5&j7Le&?v zNBI9bJ1eSj<q7rPHc_89mr4zPvF0Z;%=a;C%pH%MnqD}-OMask%J};)a4)^Frq_^{ z)XAq*@xDokJO7@{Y5qcQ)^m32j_X8UsNLYcwJn*rz{{c8T3y<YmLD3210A(OigTX8 z3VF*sd4)uOpL~f{<pvi|EG+@?Wdk@KaG5Eg*y31vK0hLT%^EpH|14$1Tt$IkIqpr- zQ8vrKgLLW#xJ&B?|KkV?L!5XeYOYI)CE{dXcFIY7WJ@1v9SZ4;GhR%*|HA4M>rCRb cqB=EX84sK>&O$4u&zAtQTTg(10000004q<D-2eap literal 0 HcmV?d00001 diff --git a/Dashboard/Dashboard.Web/wwwroot/index.html b/Dashboard/Dashboard.Web/wwwroot/index.html index 2b551b3..ef892e8 100644 --- a/Dashboard/Dashboard.Web/wwwroot/index.html +++ b/Dashboard/Dashboard.Web/wwwroot/index.html @@ -3,17 +3,16 @@ <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> - <meta name="description" content="Healthcare Dashboard - Clinical and Scheduling Management"> - <title>Healthcare Dashboard + + Nimblesite Clinical Coding Platform - + - @@ -41,23 +40,13 @@ visibility: hidden; } - .loading-logo { - width: 80px; - height: 80px; - background: linear-gradient(135deg, var(--primary-blue) 0%, var(--teal-bold) 100%); - border-radius: 20px; - display: flex; - align-items: center; - justify-content: center; + .loading-logo-img { + height: 64px; + width: auto; margin-bottom: 24px; animation: pulse 2s ease-in-out infinite; } - .loading-logo svg { - width: 48px; - height: 48px; - } - .loading-text { font-size: 18px; font-weight: 500; @@ -78,12 +67,8 @@
- -
Healthcare Dashboard
+ Nimblesite +
Nimblesite Clinical Coding Platform
@@ -987,7 +972,7 @@ ) ); - // Dashboard Page - Professional Healthcare Design + // Dashboard Page - Nimblesite Clinical Coding Design const DashboardPage = ({ onNavigate }) => { const patients = useFetch(`${CLINICAL_API}/fhir/Patient`); const practitioners = useFetch(`${SCHEDULING_API}/Practitioner`); @@ -2673,8 +2658,8 @@ return React.createElement('div', { className: 'login-page', 'data-testid': 'login-page' }, React.createElement('div', { className: 'login-card' }, React.createElement('div', { className: 'login-header' }, - React.createElement('div', { className: 'login-logo' }, React.createElement(Icons.Activity)), - React.createElement('h1', null, 'Healthcare Dashboard'), + React.createElement('img', { src: 'img/nimblesite-logo.webp', alt: 'Nimblesite', className: 'login-logo-img' }), + React.createElement('h1', null, 'Nimblesite Clinical Coding Platform'), React.createElement('p', null, mode === 'login' ? 'Sign in with your passkey' : 'Create your account') ), error && React.createElement('div', { className: 'login-error' }, error), @@ -2734,10 +2719,8 @@ return React.createElement('aside', { className: `sidebar ${collapsed ? 'collapsed' : ''}` }, React.createElement('div', { className: 'sidebar-header' }, React.createElement('a', { className: 'sidebar-logo', href: '#' }, - React.createElement('div', { className: 'sidebar-logo-icon' }, - React.createElement(Icons.Activity) - ), - React.createElement('span', { className: 'sidebar-logo-text' }, 'Healthcare') + React.createElement('img', { src: 'img/nimblesite-logo.webp', alt: 'Nimblesite', className: 'sidebar-logo-img' }), + React.createElement('span', { className: 'sidebar-logo-text' }, 'Nimblesite') ) ), React.createElement('nav', { className: 'sidebar-nav' }, @@ -3517,7 +3500,7 @@ calendar: 'Schedule', sync: 'Sync Dashboard', settings: 'Settings' - }[activeView] || 'Healthcare'; + }[activeView] || 'Clinical Coding'; }; const handleEditPatient = (patientId) => { diff --git a/Dashboard/Dashboard.Web/wwwroot/js/Dashboard.js b/Dashboard/Dashboard.Web/wwwroot/js/Dashboard.js index 8c7b1d9..accf358 100644 --- a/Dashboard/Dashboard.Web/wwwroot/js/Dashboard.js +++ b/Dashboard/Dashboard.Web/wwwroot/js/Dashboard.js @@ -53370,7 +53370,7 @@ H5.assembly("Dashboard.Web", function ($asm, globals) { if (H5.referenceEquals(view, "settings")) { return "Settings"; } - return "Healthcare"; + return "Clinical Coding"; }, RenderPage: function (state, setState) { var view = state.ActiveView; @@ -56807,7 +56807,7 @@ H5.assembly("Dashboard.Web", function ($asm, globals) { var authToken = Dashboard.Program.GetConfigValue("AUTH_TOKEN", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkYXNoYm9hcmQtdXNlciIsImp0aSI6IjE1MTMwYTg0LTY4NTktNGNmMy05MjA3LTMyMGJhYWRiNzhjNSIsInJvbGVzIjpbImNsaW5pY2lhbiIsInNjaGVkdWxlciJdLCJleHAiOjIwODE5MjIxMDQsImlhdCI6MTc2NjM4OTMwNH0.mk66XyKaLWukzZOmGNwss74lSlXobt6Em0NoEbXRdKU"); Dashboard.Api.ApiClient.SetTokens(authToken, authToken); - Dashboard.Program.Log("Healthcare Dashboard starting..."); + Dashboard.Program.Log("Nimblesite Clinical Coding Platform starting..."); Dashboard.Program.Log("Clinical API: " + (clinicalUrl || "")); Dashboard.Program.Log("Scheduling API: " + (schedulingUrl || "")); Dashboard.Program.Log("ICD-10 API: " + (icd10Url || "")); diff --git a/Dashboard/Dashboard.Web/wwwroot/js/Dashboard.min.js b/Dashboard/Dashboard.Web/wwwroot/js/Dashboard.min.js index 762e6f6..2f7de53 100644 --- a/Dashboard/Dashboard.Web/wwwroot/js/Dashboard.min.js +++ b/Dashboard/Dashboard.Web/wwwroot/js/Dashboard.min.js @@ -10,4 +10,4 @@ * @copyright : Copyright 2008-2019 Object.NET, Inc., Copyright 2019-2026 Curiosity GmbH * @license : See https://github.com/curiosity-ai/h5/blob/master/LICENSE. */ -var $m=H5.setMetadata,$n=["System","System.Globalization","System.Threading","System.Collections.Generic","System.Runtime.Serialization","System.Collections.ObjectModel","System.Collections","H5","System.Text","System.Net.WebSockets","System.Threading.Tasks","System.Text.RegularExpressions","System.Reflection","System.Runtime.CompilerServices","System.IO","System.ComponentModel"];$m("System.ApplicationException",function(){return{att:1056769,a:2,at:[new System.SerializableAttribute],m:[{a:2,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].String],pi:[{n:"message",pt:$n[0].String,ps:0}],sn:"$ctor1"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[0].Exception],pi:[{n:"message",pt:$n[0].String,ps:0},{n:"innerException",pt:$n[0].Exception,ps:1}],sn:"$ctor2"}]}},$n);$m("System.ArgumentException",function(){return{att:1056769,a:2,at:[new System.SerializableAttribute],m:[{a:2,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].String],pi:[{n:"message",pt:$n[0].String,ps:0}],sn:"$ctor1"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[0].Exception],pi:[{n:"message",pt:$n[0].String,ps:0},{n:"innerException",pt:$n[0].Exception,ps:1}],sn:"$ctor2"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[0].String],pi:[{n:"message",pt:$n[0].String,ps:0},{n:"paramName",pt:$n[0].String,ps:1}],sn:"$ctor3"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[0].String,$n[0].Exception],pi:[{n:"message",pt:$n[0].String,ps:0},{n:"paramName",pt:$n[0].String,ps:1},{n:"innerException",pt:$n[0].Exception,ps:2}],sn:"$ctor4"},{ov:!0,a:2,n:"Message",t:16,rt:$n[0].String,g:{ov:!0,a:2,n:"get_Message",t:8,rt:$n[0].String,fg:"Message"},fn:"Message"},{v:!0,a:2,n:"ParamName",t:16,rt:$n[0].String,g:{v:!0,a:2,n:"get_ParamName",t:8,rt:$n[0].String,fg:"ParamName"},fn:"ParamName"},{a:1,n:"_paramName",t:4,rt:$n[0].String,sn:"_paramName"}]}},$n);$m("System.ArgumentNullException",function(){return{att:1056769,a:2,at:[new System.SerializableAttribute],m:[{a:2,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].String],pi:[{n:"paramName",pt:$n[0].String,ps:0}],sn:"$ctor1"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[0].Exception],pi:[{n:"message",pt:$n[0].String,ps:0},{n:"innerException",pt:$n[0].Exception,ps:1}],sn:"$ctor2"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[0].String],pi:[{n:"paramName",pt:$n[0].String,ps:0},{n:"message",pt:$n[0].String,ps:1}],sn:"$ctor3"}]}},$n);$m("System.ArgumentOutOfRangeException",function(){return{att:1056769,a:2,at:[new System.SerializableAttribute],m:[{a:2,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].String],pi:[{n:"paramName",pt:$n[0].String,ps:0}],sn:"$ctor1"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[0].Exception],pi:[{n:"message",pt:$n[0].String,ps:0},{n:"innerException",pt:$n[0].Exception,ps:1}],sn:"$ctor2"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[0].String],pi:[{n:"paramName",pt:$n[0].String,ps:0},{n:"message",pt:$n[0].String,ps:1}],sn:"$ctor4"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[0].Object,$n[0].String],pi:[{n:"paramName",pt:$n[0].String,ps:0},{n:"actualValue",pt:$n[0].Object,ps:1},{n:"message",pt:$n[0].String,ps:2}],sn:"$ctor3"},{v:!0,a:2,n:"ActualValue",t:16,rt:$n[0].Object,g:{v:!0,a:2,n:"get_ActualValue",t:8,rt:$n[0].Object,fg:"ActualValue"},fn:"ActualValue"},{ov:!0,a:2,n:"Message",t:16,rt:$n[0].String,g:{ov:!0,a:2,n:"get_Message",t:8,rt:$n[0].String,fg:"Message"},fn:"Message"},{a:1,n:"_actualValue",t:4,rt:$n[0].Object,sn:"_actualValue"}]}},$n);$m("System.ArithmeticException",function(){return{att:1056769,a:2,at:[new System.SerializableAttribute],m:[{a:2,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].String],pi:[{n:"message",pt:$n[0].String,ps:0}],sn:"$ctor1"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[0].Exception],pi:[{n:"message",pt:$n[0].String,ps:0},{n:"innerException",pt:$n[0].Exception,ps:1}],sn:"$ctor2"}]}},$n);$m("System.ArrayTypeMismatchException",function(){return{att:1056769,a:2,at:[new System.SerializableAttribute],m:[{a:2,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].String],pi:[{n:"message",pt:$n[0].String,ps:0}],sn:"$ctor1"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[0].Exception],pi:[{n:"message",pt:$n[0].String,ps:0},{n:"innerException",pt:$n[0].Exception,ps:1}],sn:"$ctor2"}]}},$n);$m("System.CharEnumerator",function(){return{att:1048833,a:2,m:[{a:4,n:".ctor",t:1,p:[$n[0].String],pi:[{n:"str",pt:$n[0].String,ps:0}],sn:"ctor"},{a:2,n:"Clone",t:8,sn:"clone",rt:$n[0].Object},{a:2,n:"Dispose",t:8,sn:"Dispose",rt:$n[0].Void},{a:2,n:"MoveNext",t:8,sn:"moveNext",rt:$n[0].Boolean,box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Reset",t:8,sn:"reset",rt:$n[0].Void},{a:2,n:"Current",t:16,rt:$n[0].Char,g:{a:2,n:"get_Current",t:8,rt:$n[0].Char,fg:"Current",box:function($v){return H5.box($v,System.Char,String.fromCharCode,System.Char.getHashCode)}},fn:"Current"},{a:1,n:"_currentElement",t:4,rt:$n[0].Char,sn:"_currentElement",box:function($v){return H5.box($v,System.Char,String.fromCharCode,System.Char.getHashCode)}},{a:1,n:"_index",t:4,rt:$n[0].Int32,sn:"_index",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"_str",t:4,rt:$n[0].String,sn:"_str"}]}},$n);$m("System.Base64FormattingOptions",function(){return{att:257,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:"InsertLineBreaks",is:!0,t:4,rt:$n[0].Base64FormattingOptions,sn:"InsertLineBreaks",box:function($v){return H5.box($v,System.Base64FormattingOptions,System.Enum.toStringFn(System.Base64FormattingOptions))}},{a:2,n:"None",is:!0,t:4,rt:$n[0].Base64FormattingOptions,sn:"None",box:function($v){return H5.box($v,System.Base64FormattingOptions,System.Enum.toStringFn(System.Base64FormattingOptions))}}]}},$n);$m("System.DateTimeKind",function(){return{att:8449,a:2,at:[new System.SerializableAttribute],m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:"Local",is:!0,t:4,rt:$n[0].DateTimeKind,sn:"Local",box:function($v){return H5.box($v,System.DateTimeKind,System.Enum.toStringFn(System.DateTimeKind))}},{a:2,n:"Unspecified",is:!0,t:4,rt:$n[0].DateTimeKind,sn:"Unspecified",box:function($v){return H5.box($v,System.DateTimeKind,System.Enum.toStringFn(System.DateTimeKind))}},{a:2,n:"Utc",is:!0,t:4,rt:$n[0].DateTimeKind,sn:"Utc",box:function($v){return H5.box($v,System.DateTimeKind,System.Enum.toStringFn(System.DateTimeKind))}}]}},$n);$m("System.DateTimeOffset",function(){return{att:1057025,a:2,at:[new System.SerializableAttribute],m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].DateTime],pi:[{n:"dateTime",pt:$n[0].DateTime,ps:0}],sn:"$ctor1"},{a:2,n:".ctor",t:1,p:[$n[0].DateTime,$n[0].TimeSpan],pi:[{n:"dateTime",pt:$n[0].DateTime,ps:0},{n:"offset",pt:$n[0].TimeSpan,ps:1}],sn:"$ctor2"},{a:2,n:".ctor",t:1,p:[$n[0].Int64,$n[0].TimeSpan],pi:[{n:"ticks",pt:$n[0].Int64,ps:0},{n:"offset",pt:$n[0].TimeSpan,ps:1}],sn:"$ctor5"},{a:2,n:".ctor",t:1,p:[$n[0].Int32,$n[0].Int32,$n[0].Int32,$n[0].Int32,$n[0].Int32,$n[0].Int32,$n[0].TimeSpan],pi:[{n:"year",pt:$n[0].Int32,ps:0},{n:"month",pt:$n[0].Int32,ps:1},{n:"day",pt:$n[0].Int32,ps:2},{n:"hour",pt:$n[0].Int32,ps:3},{n:"minute",pt:$n[0].Int32,ps:4},{n:"second",pt:$n[0].Int32,ps:5},{n:"offset",pt:$n[0].TimeSpan,ps:6}],sn:"$ctor4"},{a:2,n:".ctor",t:1,p:[$n[0].Int32,$n[0].Int32,$n[0].Int32,$n[0].Int32,$n[0].Int32,$n[0].Int32,$n[0].Int32,$n[0].TimeSpan],pi:[{n:"year",pt:$n[0].Int32,ps:0},{n:"month",pt:$n[0].Int32,ps:1},{n:"day",pt:$n[0].Int32,ps:2},{n:"hour",pt:$n[0].Int32,ps:3},{n:"minute",pt:$n[0].Int32,ps:4},{n:"second",pt:$n[0].Int32,ps:5},{n:"millisecond",pt:$n[0].Int32,ps:6},{n:"offset",pt:$n[0].TimeSpan,ps:7}],sn:"$ctor3"},{a:2,n:"Add",t:8,pi:[{n:"timeSpan",pt:$n[0].TimeSpan,ps:0}],sn:"Add",rt:$n[0].DateTimeOffset,p:[$n[0].TimeSpan]},{a:2,n:"AddDays",t:8,pi:[{n:"days",pt:$n[0].Double,ps:0}],sn:"AddDays",rt:$n[0].DateTimeOffset,p:[$n[0].Double]},{a:2,n:"AddHours",t:8,pi:[{n:"hours",pt:$n[0].Double,ps:0}],sn:"AddHours",rt:$n[0].DateTimeOffset,p:[$n[0].Double]},{a:2,n:"AddMilliseconds",t:8,pi:[{n:"milliseconds",pt:$n[0].Double,ps:0}],sn:"AddMilliseconds",rt:$n[0].DateTimeOffset,p:[$n[0].Double]},{a:2,n:"AddMinutes",t:8,pi:[{n:"minutes",pt:$n[0].Double,ps:0}],sn:"AddMinutes",rt:$n[0].DateTimeOffset,p:[$n[0].Double]},{a:2,n:"AddMonths",t:8,pi:[{n:"months",pt:$n[0].Int32,ps:0}],sn:"AddMonths",rt:$n[0].DateTimeOffset,p:[$n[0].Int32]},{a:2,n:"AddSeconds",t:8,pi:[{n:"seconds",pt:$n[0].Double,ps:0}],sn:"AddSeconds",rt:$n[0].DateTimeOffset,p:[$n[0].Double]},{a:2,n:"AddTicks",t:8,pi:[{n:"ticks",pt:$n[0].Int64,ps:0}],sn:"AddTicks",rt:$n[0].DateTimeOffset,p:[$n[0].Int64]},{a:2,n:"AddYears",t:8,pi:[{n:"years",pt:$n[0].Int32,ps:0}],sn:"AddYears",rt:$n[0].DateTimeOffset,p:[$n[0].Int32]},{a:2,n:"Compare",is:!0,t:8,pi:[{n:"first",pt:$n[0].DateTimeOffset,ps:0},{n:"second",pt:$n[0].DateTimeOffset,ps:1}],sn:"Compare",rt:$n[0].Int32,p:[$n[0].DateTimeOffset,$n[0].DateTimeOffset],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"CompareTo",t:8,pi:[{n:"other",pt:$n[0].DateTimeOffset,ps:0}],sn:"compareTo",rt:$n[0].Int32,p:[$n[0].DateTimeOffset],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"Equals",t:8,pi:[{n:"other",pt:$n[0].DateTimeOffset,ps:0}],sn:"equalsT",rt:$n[0].Boolean,p:[$n[0].DateTimeOffset],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ov:!0,a:2,n:"Equals",t:8,pi:[{n:"obj",pt:$n[0].Object,ps:0}],sn:"equals",rt:$n[0].Boolean,p:[$n[0].Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Equals",is:!0,t:8,pi:[{n:"first",pt:$n[0].DateTimeOffset,ps:0},{n:"second",pt:$n[0].DateTimeOffset,ps:1}],sn:"Equals",rt:$n[0].Boolean,p:[$n[0].DateTimeOffset,$n[0].DateTimeOffset],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"EqualsExact",t:8,pi:[{n:"other",pt:$n[0].DateTimeOffset,ps:0}],sn:"EqualsExact",rt:$n[0].Boolean,p:[$n[0].DateTimeOffset],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"FromFileTime",is:!0,t:8,pi:[{n:"fileTime",pt:$n[0].Int64,ps:0}],sn:"FromFileTime",rt:$n[0].DateTimeOffset,p:[$n[0].Int64]},{a:2,n:"FromUnixTimeMilliseconds",is:!0,t:8,pi:[{n:"milliseconds",pt:$n[0].Int64,ps:0}],sn:"FromUnixTimeMilliseconds",rt:$n[0].DateTimeOffset,p:[$n[0].Int64]},{a:2,n:"FromUnixTimeSeconds",is:!0,t:8,pi:[{n:"seconds",pt:$n[0].Int64,ps:0}],sn:"FromUnixTimeSeconds",rt:$n[0].DateTimeOffset,p:[$n[0].Int64]},{ov:!0,a:2,n:"GetHashCode",t:8,sn:"getHashCode",rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"Parse",is:!0,t:8,pi:[{n:"input",pt:$n[0].String,ps:0}],sn:"Parse",rt:$n[0].DateTimeOffset,p:[$n[0].String]},{a:2,n:"Parse",is:!0,t:8,pi:[{n:"input",pt:$n[0].String,ps:0},{n:"formatProvider",pt:$n[0].IFormatProvider,ps:1}],sn:"Parse$1",rt:$n[0].DateTimeOffset,p:[$n[0].String,$n[0].IFormatProvider]},{a:2,n:"Parse",is:!0,t:8,pi:[{n:"input",pt:$n[0].String,ps:0},{n:"formatProvider",pt:$n[0].IFormatProvider,ps:1},{n:"styles",pt:$n[1].DateTimeStyles,ps:2}],sn:"Parse$2",rt:$n[0].DateTimeOffset,p:[$n[0].String,$n[0].IFormatProvider,$n[1].DateTimeStyles]},{a:2,n:"ParseExact",is:!0,t:8,pi:[{n:"input",pt:$n[0].String,ps:0},{n:"format",pt:$n[0].String,ps:1},{n:"formatProvider",pt:$n[0].IFormatProvider,ps:2}],sn:"ParseExact",rt:$n[0].DateTimeOffset,p:[$n[0].String,$n[0].String,$n[0].IFormatProvider]},{a:2,n:"ParseExact",is:!0,t:8,pi:[{n:"input",pt:$n[0].String,ps:0},{n:"format",pt:$n[0].String,ps:1},{n:"formatProvider",pt:$n[0].IFormatProvider,ps:2},{n:"styles",pt:$n[1].DateTimeStyles,ps:3}],sn:"ParseExact$1",rt:$n[0].DateTimeOffset,p:[$n[0].String,$n[0].String,$n[0].IFormatProvider,$n[1].DateTimeStyles]},{a:2,n:"Subtract",t:8,pi:[{n:"value",pt:$n[0].DateTimeOffset,ps:0}],sn:"Subtract$1",rt:$n[0].TimeSpan,p:[$n[0].DateTimeOffset]},{a:2,n:"Subtract",t:8,pi:[{n:"value",pt:$n[0].TimeSpan,ps:0}],sn:"Subtract",rt:$n[0].DateTimeOffset,p:[$n[0].TimeSpan]},{a:2,n:"ToFileTime",t:8,sn:"ToFileTime",rt:$n[0].Int64},{a:2,n:"ToLocalTime",t:8,sn:"ToLocalTime",rt:$n[0].DateTimeOffset},{a:4,n:"ToLocalTime",t:8,pi:[{n:"throwOnOverflow",pt:$n[0].Boolean,ps:0}],sn:"ToLocalTime$1",rt:$n[0].DateTimeOffset,p:[$n[0].Boolean]},{a:2,n:"ToOffset",t:8,pi:[{n:"offset",pt:$n[0].TimeSpan,ps:0}],sn:"ToOffset",rt:$n[0].DateTimeOffset,p:[$n[0].TimeSpan]},{ov:!0,a:2,n:"ToString",t:8,sn:"toString",rt:$n[0].String},{a:2,n:"ToString",t:8,pi:[{n:"formatProvider",pt:$n[0].IFormatProvider,ps:0}],sn:"ToString",rt:$n[0].String,p:[$n[0].IFormatProvider]},{a:2,n:"ToString",t:8,pi:[{n:"format",pt:$n[0].String,ps:0}],sn:"ToString$1",rt:$n[0].String,p:[$n[0].String]},{a:2,n:"ToString",t:8,pi:[{n:"format",pt:$n[0].String,ps:0},{n:"formatProvider",pt:$n[0].IFormatProvider,ps:1}],sn:"format",rt:$n[0].String,p:[$n[0].String,$n[0].IFormatProvider]},{a:2,n:"ToUniversalTime",t:8,sn:"ToUniversalTime",rt:$n[0].DateTimeOffset},{a:2,n:"ToUnixTimeMilliseconds",t:8,sn:"ToUnixTimeMilliseconds",rt:$n[0].Int64},{a:2,n:"ToUnixTimeSeconds",t:8,sn:"ToUnixTimeSeconds",rt:$n[0].Int64},{a:2,n:"TryParse",is:!0,t:8,pi:[{n:"input",pt:$n[0].String,ps:0},{n:"result",out:!0,pt:$n[0].DateTimeOffset,ps:1}],sn:"TryParse",rt:$n[0].Boolean,p:[$n[0].String,$n[0].DateTimeOffset],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"TryParse",is:!0,t:8,pi:[{n:"input",pt:$n[0].String,ps:0},{n:"formatProvider",pt:$n[0].IFormatProvider,ps:1},{n:"styles",pt:$n[1].DateTimeStyles,ps:2},{n:"result",out:!0,pt:$n[0].DateTimeOffset,ps:3}],sn:"TryParse$1",rt:$n[0].Boolean,p:[$n[0].String,$n[0].IFormatProvider,$n[1].DateTimeStyles,$n[0].DateTimeOffset],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"ValidateDate",is:!0,t:8,pi:[{n:"dateTime",pt:$n[0].DateTime,ps:0},{n:"offset",pt:$n[0].TimeSpan,ps:1}],sn:"ValidateDate",rt:$n[0].DateTime,p:[$n[0].DateTime,$n[0].TimeSpan],box:function($v){return H5.box($v,System.DateTime,System.DateTime.format)}},{a:1,n:"ValidateOffset",is:!0,t:8,pi:[{n:"offset",pt:$n[0].TimeSpan,ps:0}],sn:"ValidateOffset",rt:$n[0].Int16,p:[$n[0].TimeSpan],box:function($v){return H5.box($v,System.Int16)}},{a:2,n:"op_Addition",is:!0,t:8,pi:[{n:"dateTimeOffset",pt:$n[0].DateTimeOffset,ps:0},{n:"timeSpan",pt:$n[0].TimeSpan,ps:1}],sn:"op_Addition",rt:$n[0].DateTimeOffset,p:[$n[0].DateTimeOffset,$n[0].TimeSpan]},{a:2,n:"op_Equality",is:!0,t:8,pi:[{n:"left",pt:$n[0].DateTimeOffset,ps:0},{n:"right",pt:$n[0].DateTimeOffset,ps:1}],sn:"op_Equality",rt:$n[0].Boolean,p:[$n[0].DateTimeOffset,$n[0].DateTimeOffset],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"op_GreaterThan",is:!0,t:8,pi:[{n:"left",pt:$n[0].DateTimeOffset,ps:0},{n:"right",pt:$n[0].DateTimeOffset,ps:1}],sn:"op_GreaterThan",rt:$n[0].Boolean,p:[$n[0].DateTimeOffset,$n[0].DateTimeOffset],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"op_GreaterThanOrEqual",is:!0,t:8,pi:[{n:"left",pt:$n[0].DateTimeOffset,ps:0},{n:"right",pt:$n[0].DateTimeOffset,ps:1}],sn:"op_GreaterThanOrEqual",rt:$n[0].Boolean,p:[$n[0].DateTimeOffset,$n[0].DateTimeOffset],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"op_Implicit",is:!0,t:8,pi:[{n:"dateTime",pt:$n[0].DateTime,ps:0}],sn:"op_Implicit",rt:$n[0].DateTimeOffset,p:[$n[0].DateTime]},{a:2,n:"op_Inequality",is:!0,t:8,pi:[{n:"left",pt:$n[0].DateTimeOffset,ps:0},{n:"right",pt:$n[0].DateTimeOffset,ps:1}],sn:"op_Inequality",rt:$n[0].Boolean,p:[$n[0].DateTimeOffset,$n[0].DateTimeOffset],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"op_LessThan",is:!0,t:8,pi:[{n:"left",pt:$n[0].DateTimeOffset,ps:0},{n:"right",pt:$n[0].DateTimeOffset,ps:1}],sn:"op_LessThan",rt:$n[0].Boolean,p:[$n[0].DateTimeOffset,$n[0].DateTimeOffset],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"op_LessThanOrEqual",is:!0,t:8,pi:[{n:"left",pt:$n[0].DateTimeOffset,ps:0},{n:"right",pt:$n[0].DateTimeOffset,ps:1}],sn:"op_LessThanOrEqual",rt:$n[0].Boolean,p:[$n[0].DateTimeOffset,$n[0].DateTimeOffset],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"op_Subtraction",is:!0,t:8,pi:[{n:"left",pt:$n[0].DateTimeOffset,ps:0},{n:"right",pt:$n[0].DateTimeOffset,ps:1}],sn:"op_Subtraction$1",rt:$n[0].TimeSpan,p:[$n[0].DateTimeOffset,$n[0].DateTimeOffset]},{a:2,n:"op_Subtraction",is:!0,t:8,pi:[{n:"dateTimeOffset",pt:$n[0].DateTimeOffset,ps:0},{n:"timeSpan",pt:$n[0].TimeSpan,ps:1}],sn:"op_Subtraction",rt:$n[0].DateTimeOffset,p:[$n[0].DateTimeOffset,$n[0].TimeSpan]},{a:1,n:"ClockDateTime",t:16,rt:$n[0].DateTime,g:{a:1,n:"get_ClockDateTime",t:8,rt:$n[0].DateTime,fg:"ClockDateTime",box:function($v){return H5.box($v,System.DateTime,System.DateTime.format)}},fn:"ClockDateTime"},{a:2,n:"Date",t:16,rt:$n[0].DateTime,g:{a:2,n:"get_Date",t:8,rt:$n[0].DateTime,fg:"Date",box:function($v){return H5.box($v,System.DateTime,System.DateTime.format)}},fn:"Date"},{a:2,n:"DateTime",t:16,rt:$n[0].DateTime,g:{a:2,n:"get_DateTime",t:8,rt:$n[0].DateTime,fg:"DateTime",box:function($v){return H5.box($v,System.DateTime,System.DateTime.format)}},fn:"DateTime"},{a:2,n:"Day",t:16,rt:$n[0].Int32,g:{a:2,n:"get_Day",t:8,rt:$n[0].Int32,fg:"Day",box:function($v){return H5.box($v,System.Int32)}},fn:"Day"},{a:2,n:"DayOfWeek",t:16,rt:$n[0].DayOfWeek,g:{a:2,n:"get_DayOfWeek",t:8,rt:$n[0].DayOfWeek,fg:"DayOfWeek",box:function($v){return H5.box($v,System.DayOfWeek,System.Enum.toStringFn(System.DayOfWeek))}},fn:"DayOfWeek"},{a:2,n:"DayOfYear",t:16,rt:$n[0].Int32,g:{a:2,n:"get_DayOfYear",t:8,rt:$n[0].Int32,fg:"DayOfYear",box:function($v){return H5.box($v,System.Int32)}},fn:"DayOfYear"},{a:2,n:"Hour",t:16,rt:$n[0].Int32,g:{a:2,n:"get_Hour",t:8,rt:$n[0].Int32,fg:"Hour",box:function($v){return H5.box($v,System.Int32)}},fn:"Hour"},{a:2,n:"LocalDateTime",t:16,rt:$n[0].DateTime,g:{a:2,n:"get_LocalDateTime",t:8,rt:$n[0].DateTime,fg:"LocalDateTime",box:function($v){return H5.box($v,System.DateTime,System.DateTime.format)}},fn:"LocalDateTime"},{a:2,n:"Millisecond",t:16,rt:$n[0].Int32,g:{a:2,n:"get_Millisecond",t:8,rt:$n[0].Int32,fg:"Millisecond",box:function($v){return H5.box($v,System.Int32)}},fn:"Millisecond"},{a:2,n:"Minute",t:16,rt:$n[0].Int32,g:{a:2,n:"get_Minute",t:8,rt:$n[0].Int32,fg:"Minute",box:function($v){return H5.box($v,System.Int32)}},fn:"Minute"},{a:2,n:"Month",t:16,rt:$n[0].Int32,g:{a:2,n:"get_Month",t:8,rt:$n[0].Int32,fg:"Month",box:function($v){return H5.box($v,System.Int32)}},fn:"Month"},{a:2,n:"Now",is:!0,t:16,rt:$n[0].DateTimeOffset,g:{a:2,n:"get_Now",t:8,rt:$n[0].DateTimeOffset,fg:"Now",is:!0},fn:"Now"},{a:2,n:"Offset",t:16,rt:$n[0].TimeSpan,g:{a:2,n:"get_Offset",t:8,rt:$n[0].TimeSpan,fg:"Offset"},fn:"Offset"},{a:2,n:"Second",t:16,rt:$n[0].Int32,g:{a:2,n:"get_Second",t:8,rt:$n[0].Int32,fg:"Second",box:function($v){return H5.box($v,System.Int32)}},fn:"Second"},{a:2,n:"Ticks",t:16,rt:$n[0].Int64,g:{a:2,n:"get_Ticks",t:8,rt:$n[0].Int64,fg:"Ticks"},fn:"Ticks"},{a:2,n:"TimeOfDay",t:16,rt:$n[0].TimeSpan,g:{a:2,n:"get_TimeOfDay",t:8,rt:$n[0].TimeSpan,fg:"TimeOfDay"},fn:"TimeOfDay"},{a:2,n:"UtcDateTime",t:16,rt:$n[0].DateTime,g:{a:2,n:"get_UtcDateTime",t:8,rt:$n[0].DateTime,fg:"UtcDateTime",box:function($v){return H5.box($v,System.DateTime,System.DateTime.format)}},fn:"UtcDateTime"},{a:2,n:"UtcNow",is:!0,t:16,rt:$n[0].DateTimeOffset,g:{a:2,n:"get_UtcNow",t:8,rt:$n[0].DateTimeOffset,fg:"UtcNow",is:!0},fn:"UtcNow"},{a:2,n:"UtcTicks",t:16,rt:$n[0].Int64,g:{a:2,n:"get_UtcTicks",t:8,rt:$n[0].Int64,fg:"UtcTicks"},fn:"UtcTicks"},{a:2,n:"Year",t:16,rt:$n[0].Int32,g:{a:2,n:"get_Year",t:8,rt:$n[0].Int32,fg:"Year",box:function($v){return H5.box($v,System.Int32)}},fn:"Year"},{a:4,n:"MaxOffset",is:!0,t:4,rt:$n[0].Int64,sn:"MaxOffset"},{a:2,n:"MaxValue",is:!0,t:4,rt:$n[0].DateTimeOffset,sn:"MaxValue",ro:!0},{a:4,n:"MinOffset",is:!0,t:4,rt:$n[0].Int64,sn:"MinOffset"},{a:2,n:"MinValue",is:!0,t:4,rt:$n[0].DateTimeOffset,sn:"MinValue",ro:!0},{a:1,n:"UnixEpochMilliseconds",is:!0,t:4,rt:$n[0].Int64,sn:"UnixEpochMilliseconds"},{a:1,n:"UnixEpochSeconds",is:!0,t:4,rt:$n[0].Int64,sn:"UnixEpochSeconds"},{a:1,n:"UnixEpochTicks",is:!0,t:4,rt:$n[0].Int64,sn:"UnixEpochTicks"},{a:1,n:"m_dateTime",t:4,rt:$n[0].DateTime,sn:"m_dateTime",box:function($v){return H5.box($v,System.DateTime,System.DateTime.format)}},{a:1,n:"m_offsetMinutes",t:4,rt:$n[0].Int16,sn:"m_offsetMinutes",box:function($v){return H5.box($v,System.Int16)}}]}},$n);$m("System.DBNull",function(){return{att:1057025,a:2,at:[new System.SerializableAttribute],m:[{a:1,n:".ctor",t:1,sn:"ctor"},{a:2,n:"GetTypeCode",t:8,sn:"GetTypeCode",rt:$n[0].TypeCode,box:function($v){return H5.box($v,System.TypeCode,System.Enum.toStringFn(System.TypeCode))}},{ov:!0,a:2,n:"ToString",t:8,sn:"toString",rt:$n[0].String},{a:2,n:"ToString",t:8,pi:[{n:"provider",pt:$n[0].IFormatProvider,ps:0}],sn:"ToString",rt:$n[0].String,p:[$n[0].IFormatProvider]},{a:2,n:"Value",is:!0,t:4,rt:$n[0].DBNull,sn:"Value",ro:!0}]}},$n);$m("System.DivideByZeroException",function(){return{att:1056769,a:2,at:[new System.SerializableAttribute],m:[{a:2,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].String],pi:[{n:"message",pt:$n[0].String,ps:0}],sn:"$ctor1"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[0].Exception],pi:[{n:"message",pt:$n[0].String,ps:0},{n:"innerException",pt:$n[0].Exception,ps:1}],sn:"$ctor2"}]}},$n);$m("System.Empty",function(){return{att:1048832,a:4,m:[{a:1,n:".ctor",t:1,sn:"ctor"},{ov:!0,a:2,n:"ToString",t:8,sn:"toString",rt:$n[0].String},{a:2,n:"Value",is:!0,t:4,rt:$n[0].Empty,sn:"Value",ro:!0}]}},$n);$m("System.FormatException",function(){return{att:1056769,a:2,at:[new System.SerializableAttribute],m:[{a:2,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].String],pi:[{n:"message",pt:$n[0].String,ps:0}],sn:"$ctor1"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[0].Exception],pi:[{n:"message",pt:$n[0].String,ps:0},{n:"innerException",pt:$n[0].Exception,ps:1}],sn:"$ctor2"}]}},$n);$m("System.FormattableString",function(){return{att:1048705,a:2,m:[{a:3,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{ab:!0,a:2,n:"GetArgument",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0}],sn:"GetArgument",rt:$n[0].Object,p:[$n[0].Int32]},{ab:!0,a:2,n:"GetArguments",t:8,sn:"GetArguments",rt:$n[0].Array.type(System.Object)},{a:2,n:"Invariant",is:!0,t:8,pi:[{n:"formattable",pt:$n[0].FormattableString,ps:0}],sn:"Invariant",rt:$n[0].String,p:[$n[0].FormattableString]},{ov:!0,a:2,n:"ToString",t:8,sn:"toString",rt:$n[0].String},{ab:!0,a:2,n:"ToString",t:8,pi:[{n:"formatProvider",pt:$n[0].IFormatProvider,ps:0}],sn:"ToString",rt:$n[0].String,p:[$n[0].IFormatProvider]},{ab:!0,a:2,n:"ArgumentCount",t:16,rt:$n[0].Int32,g:{ab:!0,a:2,n:"get_ArgumentCount",t:8,rt:$n[0].Int32,fg:"ArgumentCount",box:function($v){return H5.box($v,System.Int32)}},fn:"ArgumentCount"},{ab:!0,a:2,n:"Format",t:16,rt:$n[0].String,g:{ab:!0,a:2,n:"get_Format",t:8,rt:$n[0].String,fg:"Format"},fn:"Format"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Int32,sn:"ArgumentCount",box:function($v){return H5.box($v,System.Int32)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"Format"}]}},$n);$m("System.DateTimeParse",function(){return{att:1048960,a:4,s:!0,m:[{a:4,n:"Parse",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0},{n:"dtfi",pt:$n[1].DateTimeFormatInfo,ps:1},{n:"styles",pt:$n[1].DateTimeStyles,ps:2}],sn:"Parse",rt:$n[0].DateTime,p:[$n[0].String,$n[1].DateTimeFormatInfo,$n[1].DateTimeStyles],box:function($v){return H5.box($v,System.DateTime,System.DateTime.format)}},{a:4,n:"Parse",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0},{n:"dtfi",pt:$n[1].DateTimeFormatInfo,ps:1},{n:"styles",pt:$n[1].DateTimeStyles,ps:2},{n:"offset",out:!0,pt:$n[0].TimeSpan,ps:3}],sn:"Parse$1",rt:$n[0].DateTime,p:[$n[0].String,$n[1].DateTimeFormatInfo,$n[1].DateTimeStyles,$n[0].TimeSpan],box:function($v){return H5.box($v,System.DateTime,System.DateTime.format)}},{a:4,n:"TryParse",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0},{n:"dtfi",pt:$n[1].DateTimeFormatInfo,ps:1},{n:"styles",pt:$n[1].DateTimeStyles,ps:2},{n:"result",out:!0,pt:$n[0].DateTime,ps:3}],sn:"TryParse",rt:$n[0].Boolean,p:[$n[0].String,$n[1].DateTimeFormatInfo,$n[1].DateTimeStyles,$n[0].DateTime],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:4,n:"TryParse",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0},{n:"dtfi",pt:$n[1].DateTimeFormatInfo,ps:1},{n:"styles",pt:$n[1].DateTimeStyles,ps:2},{n:"result",out:!0,pt:$n[0].DateTime,ps:3},{n:"offset",out:!0,pt:$n[0].TimeSpan,ps:4}],sn:"TryParse$1",rt:$n[0].Boolean,p:[$n[0].String,$n[1].DateTimeFormatInfo,$n[1].DateTimeStyles,$n[0].DateTime,$n[0].TimeSpan],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:4,n:"TryParseExact",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0},{n:"format",pt:$n[0].String,ps:1},{n:"dtfi",pt:$n[1].DateTimeFormatInfo,ps:2},{n:"style",pt:$n[1].DateTimeStyles,ps:3},{n:"result",out:!0,pt:$n[0].DateTime,ps:4}],sn:"TryParseExact",rt:$n[0].Boolean,p:[$n[0].String,$n[0].String,$n[1].DateTimeFormatInfo,$n[1].DateTimeStyles,$n[0].DateTime],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"TryParseOffset",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0},{n:"offset",out:!0,pt:$n[0].TimeSpan,ps:1}],sn:"TryParseOffset",rt:$n[0].Boolean,p:[$n[0].String,$n[0].TimeSpan],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}}]}},$n);$m("System.ParseFailureKind",function(){return{att:256,a:4,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:"ArgumentNull",is:!0,t:4,rt:$n[0].ParseFailureKind,sn:"ArgumentNull",box:function($v){return H5.box($v,System.ParseFailureKind,System.Enum.toStringFn(System.ParseFailureKind))}},{a:2,n:"Format",is:!0,t:4,rt:$n[0].ParseFailureKind,sn:"Format",box:function($v){return H5.box($v,System.ParseFailureKind,System.Enum.toStringFn(System.ParseFailureKind))}},{a:2,n:"FormatBadDateTimeCalendar",is:!0,t:4,rt:$n[0].ParseFailureKind,sn:"FormatBadDateTimeCalendar",box:function($v){return H5.box($v,System.ParseFailureKind,System.Enum.toStringFn(System.ParseFailureKind))}},{a:2,n:"FormatWithParameter",is:!0,t:4,rt:$n[0].ParseFailureKind,sn:"FormatWithParameter",box:function($v){return H5.box($v,System.ParseFailureKind,System.Enum.toStringFn(System.ParseFailureKind))}},{a:2,n:"None",is:!0,t:4,rt:$n[0].ParseFailureKind,sn:"None",box:function($v){return H5.box($v,System.ParseFailureKind,System.Enum.toStringFn(System.ParseFailureKind))}}]}},$n);$m("System.ParseFlags",function(){return{att:256,a:4,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:"CaptureOffset",is:!0,t:4,rt:$n[0].ParseFlags,sn:"CaptureOffset",box:function($v){return H5.box($v,System.ParseFlags,System.Enum.toStringFn(System.ParseFlags))}},{a:2,n:"HaveDate",is:!0,t:4,rt:$n[0].ParseFlags,sn:"HaveDate",box:function($v){return H5.box($v,System.ParseFlags,System.Enum.toStringFn(System.ParseFlags))}},{a:2,n:"HaveDay",is:!0,t:4,rt:$n[0].ParseFlags,sn:"HaveDay",box:function($v){return H5.box($v,System.ParseFlags,System.Enum.toStringFn(System.ParseFlags))}},{a:2,n:"HaveHour",is:!0,t:4,rt:$n[0].ParseFlags,sn:"HaveHour",box:function($v){return H5.box($v,System.ParseFlags,System.Enum.toStringFn(System.ParseFlags))}},{a:2,n:"HaveMinute",is:!0,t:4,rt:$n[0].ParseFlags,sn:"HaveMinute",box:function($v){return H5.box($v,System.ParseFlags,System.Enum.toStringFn(System.ParseFlags))}},{a:2,n:"HaveMonth",is:!0,t:4,rt:$n[0].ParseFlags,sn:"HaveMonth",box:function($v){return H5.box($v,System.ParseFlags,System.Enum.toStringFn(System.ParseFlags))}},{a:2,n:"HaveSecond",is:!0,t:4,rt:$n[0].ParseFlags,sn:"HaveSecond",box:function($v){return H5.box($v,System.ParseFlags,System.Enum.toStringFn(System.ParseFlags))}},{a:2,n:"HaveTime",is:!0,t:4,rt:$n[0].ParseFlags,sn:"HaveTime",box:function($v){return H5.box($v,System.ParseFlags,System.Enum.toStringFn(System.ParseFlags))}},{a:2,n:"HaveYear",is:!0,t:4,rt:$n[0].ParseFlags,sn:"HaveYear",box:function($v){return H5.box($v,System.ParseFlags,System.Enum.toStringFn(System.ParseFlags))}},{a:2,n:"ParsedMonthName",is:!0,t:4,rt:$n[0].ParseFlags,sn:"ParsedMonthName",box:function($v){return H5.box($v,System.ParseFlags,System.Enum.toStringFn(System.ParseFlags))}},{a:2,n:"Rfc1123Pattern",is:!0,t:4,rt:$n[0].ParseFlags,sn:"Rfc1123Pattern",box:function($v){return H5.box($v,System.ParseFlags,System.Enum.toStringFn(System.ParseFlags))}},{a:2,n:"TimeZoneUsed",is:!0,t:4,rt:$n[0].ParseFlags,sn:"TimeZoneUsed",box:function($v){return H5.box($v,System.ParseFlags,System.Enum.toStringFn(System.ParseFlags))}},{a:2,n:"TimeZoneUtc",is:!0,t:4,rt:$n[0].ParseFlags,sn:"TimeZoneUtc",box:function($v){return H5.box($v,System.ParseFlags,System.Enum.toStringFn(System.ParseFlags))}},{a:2,n:"UtcSortPattern",is:!0,t:4,rt:$n[0].ParseFlags,sn:"UtcSortPattern",box:function($v){return H5.box($v,System.ParseFlags,System.Enum.toStringFn(System.ParseFlags))}},{a:2,n:"YearDefault",is:!0,t:4,rt:$n[0].ParseFlags,sn:"YearDefault",box:function($v){return H5.box($v,System.ParseFlags,System.Enum.toStringFn(System.ParseFlags))}}]}},$n);$m("System.DateTimeResult",function(){return{att:1048840,a:4,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:4,n:"Init",t:8,sn:"Init",rt:$n[0].Void},{a:4,n:"SetDate",t:8,pi:[{n:"year",pt:$n[0].Int32,ps:0},{n:"month",pt:$n[0].Int32,ps:1},{n:"day",pt:$n[0].Int32,ps:2}],sn:"SetDate",rt:$n[0].Void,p:[$n[0].Int32,$n[0].Int32,$n[0].Int32]},{a:4,n:"SetFailure",t:8,pi:[{n:"failure",pt:$n[0].ParseFailureKind,ps:0},{n:"failureMessageID",pt:$n[0].String,ps:1},{n:"failureMessageFormatArgument",pt:$n[0].Object,ps:2}],sn:"SetFailure",rt:$n[0].Void,p:[$n[0].ParseFailureKind,$n[0].String,$n[0].Object]},{a:4,n:"SetFailure",t:8,pi:[{n:"failure",pt:$n[0].ParseFailureKind,ps:0},{n:"failureMessageID",pt:$n[0].String,ps:1},{n:"failureMessageFormatArgument",pt:$n[0].Object,ps:2},{n:"failureArgumentName",pt:$n[0].String,ps:3}],sn:"SetFailure$1",rt:$n[0].Void,p:[$n[0].ParseFailureKind,$n[0].String,$n[0].Object,$n[0].String]},{a:4,n:"Day",t:4,rt:$n[0].Int32,sn:"Day",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"Hour",t:4,rt:$n[0].Int32,sn:"Hour",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"Minute",t:4,rt:$n[0].Int32,sn:"Minute",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"Month",t:4,rt:$n[0].Int32,sn:"Month",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"Second",t:4,rt:$n[0].Int32,sn:"Second",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"Year",t:4,rt:$n[0].Int32,sn:"Year",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"calendar",t:4,rt:$n[1].Calendar,sn:"calendar"},{a:4,n:"era",t:4,rt:$n[0].Int32,sn:"era",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"failure",t:4,rt:$n[0].ParseFailureKind,sn:"failure",box:function($v){return H5.box($v,System.ParseFailureKind,System.Enum.toStringFn(System.ParseFailureKind))}},{a:4,n:"failureArgumentName",t:4,rt:$n[0].String,sn:"failureArgumentName"},{a:4,n:"failureMessageFormatArgument",t:4,rt:$n[0].Object,sn:"failureMessageFormatArgument"},{a:4,n:"failureMessageID",t:4,rt:$n[0].String,sn:"failureMessageID"},{a:4,n:"flags",t:4,rt:$n[0].ParseFlags,sn:"flags",box:function($v){return H5.box($v,System.ParseFlags,System.Enum.toStringFn(System.ParseFlags))}},{a:4,n:"fraction",t:4,rt:$n[0].Double,sn:"fraction",box:function($v){return H5.box($v,System.Double,System.Double.format,System.Double.getHashCode)}},{a:4,n:"parsedDate",t:4,rt:$n[0].DateTime,sn:"parsedDate",box:function($v){return H5.box($v,System.DateTime,System.DateTime.format)}},{a:4,n:"timeZoneOffset",t:4,rt:$n[0].TimeSpan,sn:"timeZoneOffset"}]}},$n);$m("System.TokenType",function(){return{att:256,a:4,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:"Am",is:!0,t:4,rt:$n[0].TokenType,sn:"Am",box:function($v){return H5.box($v,System.TokenType,System.Enum.toStringFn(System.TokenType))}},{a:2,n:"DateWordToken",is:!0,t:4,rt:$n[0].TokenType,sn:"DateWordToken",box:function($v){return H5.box($v,System.TokenType,System.Enum.toStringFn(System.TokenType))}},{a:2,n:"DayOfWeekToken",is:!0,t:4,rt:$n[0].TokenType,sn:"DayOfWeekToken",box:function($v){return H5.box($v,System.TokenType,System.Enum.toStringFn(System.TokenType))}},{a:2,n:"EndOfString",is:!0,t:4,rt:$n[0].TokenType,sn:"EndOfString",box:function($v){return H5.box($v,System.TokenType,System.Enum.toStringFn(System.TokenType))}},{a:2,n:"EraToken",is:!0,t:4,rt:$n[0].TokenType,sn:"EraToken",box:function($v){return H5.box($v,System.TokenType,System.Enum.toStringFn(System.TokenType))}},{a:2,n:"HebrewNumber",is:!0,t:4,rt:$n[0].TokenType,sn:"HebrewNumber",box:function($v){return H5.box($v,System.TokenType,System.Enum.toStringFn(System.TokenType))}},{a:2,n:"IgnorableSymbol",is:!0,t:4,rt:$n[0].TokenType,sn:"IgnorableSymbol",box:function($v){return H5.box($v,System.TokenType,System.Enum.toStringFn(System.TokenType))}},{a:2,n:"JapaneseEraToken",is:!0,t:4,rt:$n[0].TokenType,sn:"JapaneseEraToken",box:function($v){return H5.box($v,System.TokenType,System.Enum.toStringFn(System.TokenType))}},{a:2,n:"MonthToken",is:!0,t:4,rt:$n[0].TokenType,sn:"MonthToken",box:function($v){return H5.box($v,System.TokenType,System.Enum.toStringFn(System.TokenType))}},{a:2,n:"NumberToken",is:!0,t:4,rt:$n[0].TokenType,sn:"NumberToken",box:function($v){return H5.box($v,System.TokenType,System.Enum.toStringFn(System.TokenType))}},{a:2,n:"Pm",is:!0,t:4,rt:$n[0].TokenType,sn:"Pm",box:function($v){return H5.box($v,System.TokenType,System.Enum.toStringFn(System.TokenType))}},{a:2,n:"RegularTokenMask",is:!0,t:4,rt:$n[0].TokenType,sn:"RegularTokenMask",box:function($v){return H5.box($v,System.TokenType,System.Enum.toStringFn(System.TokenType))}},{a:2,n:"SEP_Am",is:!0,t:4,rt:$n[0].TokenType,sn:"SEP_Am",box:function($v){return H5.box($v,System.TokenType,System.Enum.toStringFn(System.TokenType))}},{a:2,n:"SEP_Date",is:!0,t:4,rt:$n[0].TokenType,sn:"SEP_Date",box:function($v){return H5.box($v,System.TokenType,System.Enum.toStringFn(System.TokenType))}},{a:2,n:"SEP_DateOrOffset",is:!0,t:4,rt:$n[0].TokenType,sn:"SEP_DateOrOffset",box:function($v){return H5.box($v,System.TokenType,System.Enum.toStringFn(System.TokenType))}},{a:2,n:"SEP_DaySuff",is:!0,t:4,rt:$n[0].TokenType,sn:"SEP_DaySuff",box:function($v){return H5.box($v,System.TokenType,System.Enum.toStringFn(System.TokenType))}},{a:2,n:"SEP_End",is:!0,t:4,rt:$n[0].TokenType,sn:"SEP_End",box:function($v){return H5.box($v,System.TokenType,System.Enum.toStringFn(System.TokenType))}},{a:2,n:"SEP_HourSuff",is:!0,t:4,rt:$n[0].TokenType,sn:"SEP_HourSuff",box:function($v){return H5.box($v,System.TokenType,System.Enum.toStringFn(System.TokenType))}},{a:2,n:"SEP_LocalTimeMark",is:!0,t:4,rt:$n[0].TokenType,sn:"SEP_LocalTimeMark",box:function($v){return H5.box($v,System.TokenType,System.Enum.toStringFn(System.TokenType))}},{a:2,n:"SEP_MinuteSuff",is:!0,t:4,rt:$n[0].TokenType,sn:"SEP_MinuteSuff",box:function($v){return H5.box($v,System.TokenType,System.Enum.toStringFn(System.TokenType))}},{a:2,n:"SEP_MonthSuff",is:!0,t:4,rt:$n[0].TokenType,sn:"SEP_MonthSuff",box:function($v){return H5.box($v,System.TokenType,System.Enum.toStringFn(System.TokenType))}},{a:2,n:"SEP_Pm",is:!0,t:4,rt:$n[0].TokenType,sn:"SEP_Pm",box:function($v){return H5.box($v,System.TokenType,System.Enum.toStringFn(System.TokenType))}},{a:2,n:"SEP_SecondSuff",is:!0,t:4,rt:$n[0].TokenType,sn:"SEP_SecondSuff",box:function($v){return H5.box($v,System.TokenType,System.Enum.toStringFn(System.TokenType))}},{a:2,n:"SEP_Space",is:!0,t:4,rt:$n[0].TokenType,sn:"SEP_Space",box:function($v){return H5.box($v,System.TokenType,System.Enum.toStringFn(System.TokenType))}},{a:2,n:"SEP_Time",is:!0,t:4,rt:$n[0].TokenType,sn:"SEP_Time",box:function($v){return H5.box($v,System.TokenType,System.Enum.toStringFn(System.TokenType))}},{a:2,n:"SEP_Unk",is:!0,t:4,rt:$n[0].TokenType,sn:"SEP_Unk",box:function($v){return H5.box($v,System.TokenType,System.Enum.toStringFn(System.TokenType))}},{a:2,n:"SEP_YearSuff",is:!0,t:4,rt:$n[0].TokenType,sn:"SEP_YearSuff",box:function($v){return H5.box($v,System.TokenType,System.Enum.toStringFn(System.TokenType))}},{a:2,n:"SeparatorTokenMask",is:!0,t:4,rt:$n[0].TokenType,sn:"SeparatorTokenMask",box:function($v){return H5.box($v,System.TokenType,System.Enum.toStringFn(System.TokenType))}},{a:2,n:"TEraToken",is:!0,t:4,rt:$n[0].TokenType,sn:"TEraToken",box:function($v){return H5.box($v,System.TokenType,System.Enum.toStringFn(System.TokenType))}},{a:2,n:"TimeZoneToken",is:!0,t:4,rt:$n[0].TokenType,sn:"TimeZoneToken",box:function($v){return H5.box($v,System.TokenType,System.Enum.toStringFn(System.TokenType))}},{a:2,n:"UnknownToken",is:!0,t:4,rt:$n[0].TokenType,sn:"UnknownToken",box:function($v){return H5.box($v,System.TokenType,System.Enum.toStringFn(System.TokenType))}},{a:2,n:"YearNumberToken",is:!0,t:4,rt:$n[0].TokenType,sn:"YearNumberToken",box:function($v){return H5.box($v,System.TokenType,System.Enum.toStringFn(System.TokenType))}}]}},$n);$m("System.HResults",function(){return{att:1048960,a:4,s:!0,m:[{a:4,n:"COR_E_ABANDONEDMUTEX",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_ABANDONEDMUTEX",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_AMBIGUOUSMATCH",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_AMBIGUOUSMATCH",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_APPDOMAINUNLOADED",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_APPDOMAINUNLOADED",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_APPLICATION",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_APPLICATION",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_ARGUMENT",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_ARGUMENT",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_ARGUMENTOUTOFRANGE",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_ARGUMENTOUTOFRANGE",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_ARITHMETIC",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_ARITHMETIC",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_ARRAYTYPEMISMATCH",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_ARRAYTYPEMISMATCH",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_BADEXEFORMAT",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_BADEXEFORMAT",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_BADIMAGEFORMAT",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_BADIMAGEFORMAT",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_CANNOTUNLOADAPPDOMAIN",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_CANNOTUNLOADAPPDOMAIN",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_COMEMULATE",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_COMEMULATE",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_CONTEXTMARSHAL",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_CONTEXTMARSHAL",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_CUSTOMATTRIBUTEFORMAT",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_CUSTOMATTRIBUTEFORMAT",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_DATAMISALIGNED",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_DATAMISALIGNED",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_DIRECTORYNOTFOUND",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_DIRECTORYNOTFOUND",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_DIVIDEBYZERO",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_DIVIDEBYZERO",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_DLLNOTFOUND",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_DLLNOTFOUND",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_DUPLICATEWAITOBJECT",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_DUPLICATEWAITOBJECT",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_ENDOFSTREAM",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_ENDOFSTREAM",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_ENTRYPOINTNOTFOUND",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_ENTRYPOINTNOTFOUND",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_EXCEPTION",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_EXCEPTION",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_EXECUTIONENGINE",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_EXECUTIONENGINE",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_FIELDACCESS",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_FIELDACCESS",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_FILELOAD",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_FILELOAD",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_FILENOTFOUND",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_FILENOTFOUND",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_FORMAT",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_FORMAT",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_HOSTPROTECTION",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_HOSTPROTECTION",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_INDEXOUTOFRANGE",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_INDEXOUTOFRANGE",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_INSUFFICIENTEXECUTIONSTACK",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_INSUFFICIENTEXECUTIONSTACK",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_INSUFFICIENTMEMORY",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_INSUFFICIENTMEMORY",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_INVALIDCAST",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_INVALIDCAST",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_INVALIDCOMOBJECT",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_INVALIDCOMOBJECT",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_INVALIDFILTERCRITERIA",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_INVALIDFILTERCRITERIA",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_INVALIDOLEVARIANTTYPE",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_INVALIDOLEVARIANTTYPE",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_INVALIDOPERATION",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_INVALIDOPERATION",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_INVALIDPROGRAM",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_INVALIDPROGRAM",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_IO",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_IO",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_KEYNOTFOUND",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_KEYNOTFOUND",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_MARSHALDIRECTIVE",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_MARSHALDIRECTIVE",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_MEMBERACCESS",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_MEMBERACCESS",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_METHODACCESS",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_METHODACCESS",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_MISSINGFIELD",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_MISSINGFIELD",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_MISSINGMANIFESTRESOURCE",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_MISSINGMANIFESTRESOURCE",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_MISSINGMEMBER",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_MISSINGMEMBER",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_MISSINGMETHOD",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_MISSINGMETHOD",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_MISSINGSATELLITEASSEMBLY",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_MISSINGSATELLITEASSEMBLY",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_NOTFINITENUMBER",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_NOTFINITENUMBER",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_NOTSUPPORTED",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_NOTSUPPORTED",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_NULLREFERENCE",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_NULLREFERENCE",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_OBJECTDISPOSED",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_OBJECTDISPOSED",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_OPERATIONCANCELED",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_OPERATIONCANCELED",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_OUTOFMEMORY",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_OUTOFMEMORY",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_OVERFLOW",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_OVERFLOW",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_PATHTOOLONG",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_PATHTOOLONG",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_PLATFORMNOTSUPPORTED",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_PLATFORMNOTSUPPORTED",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_RANK",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_RANK",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_REFLECTIONTYPELOAD",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_REFLECTIONTYPELOAD",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_RUNTIMEWRAPPED",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_RUNTIMEWRAPPED",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_SAFEARRAYRANKMISMATCH",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_SAFEARRAYRANKMISMATCH",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_SAFEARRAYTYPEMISMATCH",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_SAFEARRAYTYPEMISMATCH",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_SAFEHANDLEMISSINGATTRIBUTE",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_SAFEHANDLEMISSINGATTRIBUTE",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_SECURITY",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_SECURITY",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_SEMAPHOREFULL",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_SEMAPHOREFULL",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_SERIALIZATION",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_SERIALIZATION",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_STACKOVERFLOW",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_STACKOVERFLOW",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_SYNCHRONIZATIONLOCK",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_SYNCHRONIZATIONLOCK",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_SYSTEM",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_SYSTEM",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_TARGET",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_TARGET",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_TARGETINVOCATION",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_TARGETINVOCATION",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_TARGETPARAMCOUNT",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_TARGETPARAMCOUNT",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_THREADABORTED",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_THREADABORTED",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_THREADINTERRUPTED",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_THREADINTERRUPTED",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_THREADSTART",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_THREADSTART",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_THREADSTOP",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_THREADSTOP",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_TIMEOUT",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_TIMEOUT",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_TYPEACCESS",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_TYPEACCESS",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_TYPEINITIALIZATION",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_TYPEINITIALIZATION",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_TYPELOAD",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_TYPELOAD",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_TYPEUNLOADED",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_TYPEUNLOADED",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_UNAUTHORIZEDACCESS",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_UNAUTHORIZEDACCESS",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_UNSUPPORTEDFORMAT",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_UNSUPPORTEDFORMAT",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_VERIFICATION",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_VERIFICATION",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COR_E_WAITHANDLECANNOTBEOPENED",is:!0,t:4,rt:$n[0].Int32,sn:"COR_E_WAITHANDLECANNOTBEOPENED",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"COvR_E_THREADSTATE",is:!0,t:4,rt:$n[0].Int32,sn:"COvR_E_THREADSTATE",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"CvOR_E_MULTICASTNOTSUPPORTED",is:!0,t:4,rt:$n[0].Int32,sn:"CvOR_E_MULTICASTNOTSUPPORTED",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"DISP_E_OVERFLOW",is:!0,t:4,rt:$n[0].Int32,sn:"DISP_E_OVERFLOW",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"ERROR_MRM_MAP_NOT_FOUND",is:!0,t:4,rt:$n[0].Int32,sn:"ERROR_MRM_MAP_NOT_FOUND",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"E_BOUNDS",is:!0,t:4,rt:$n[0].Int32,sn:"E_BOUNDS",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"E_CHANGED_STATE",is:!0,t:4,rt:$n[0].Int32,sn:"E_CHANGED_STATE",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"E_FAIL",is:!0,t:4,rt:$n[0].Int32,sn:"E_FAIL",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"E_HANDLE",is:!0,t:4,rt:$n[0].Int32,sn:"E_HANDLE",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"E_INVALIDARG",is:!0,t:4,rt:$n[0].Int32,sn:"E_INVALIDARG",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"E_NOTIMPL",is:!0,t:4,rt:$n[0].Int32,sn:"E_NOTIMPL",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"E_POINTER",is:!0,t:4,rt:$n[0].Int32,sn:"E_POINTER",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"RO_E_CLOSED",is:!0,t:4,rt:$n[0].Int32,sn:"RO_E_CLOSED",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"TYPE_E_TYPEMISMATCH",is:!0,t:4,rt:$n[0].Int32,sn:"TYPE_E_TYPEMISMATCH",box:function($v){return H5.box($v,System.Int32)}}]}},$n);$m("System.IConvertible",function(){return{att:1048737,a:2,m:[{ab:!0,a:2,n:"GetTypeCode",t:8,sn:"System$IConvertible$GetTypeCode",rt:$n[0].TypeCode,box:function($v){return H5.box($v,System.TypeCode,System.Enum.toStringFn(System.TypeCode))}},{ab:!0,a:2,n:"ToBoolean",t:8,pi:[{n:"provider",pt:$n[0].IFormatProvider,ps:0}],sn:"System$IConvertible$ToBoolean",rt:$n[0].Boolean,p:[$n[0].IFormatProvider],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ab:!0,a:2,n:"ToByte",t:8,pi:[{n:"provider",pt:$n[0].IFormatProvider,ps:0}],sn:"System$IConvertible$ToByte",rt:$n[0].Byte,p:[$n[0].IFormatProvider],box:function($v){return H5.box($v,System.Byte)}},{ab:!0,a:2,n:"ToChar",t:8,pi:[{n:"provider",pt:$n[0].IFormatProvider,ps:0}],sn:"System$IConvertible$ToChar",rt:$n[0].Char,p:[$n[0].IFormatProvider],box:function($v){return H5.box($v,System.Char,String.fromCharCode,System.Char.getHashCode)}},{ab:!0,a:2,n:"ToDateTime",t:8,pi:[{n:"provider",pt:$n[0].IFormatProvider,ps:0}],sn:"System$IConvertible$ToDateTime",rt:$n[0].DateTime,p:[$n[0].IFormatProvider],box:function($v){return H5.box($v,System.DateTime,System.DateTime.format)}},{ab:!0,a:2,n:"ToDecimal",t:8,pi:[{n:"provider",pt:$n[0].IFormatProvider,ps:0}],sn:"System$IConvertible$ToDecimal",rt:$n[0].Decimal,p:[$n[0].IFormatProvider]},{ab:!0,a:2,n:"ToDouble",t:8,pi:[{n:"provider",pt:$n[0].IFormatProvider,ps:0}],sn:"System$IConvertible$ToDouble",rt:$n[0].Double,p:[$n[0].IFormatProvider],box:function($v){return H5.box($v,System.Double,System.Double.format,System.Double.getHashCode)}},{ab:!0,a:2,n:"ToInt16",t:8,pi:[{n:"provider",pt:$n[0].IFormatProvider,ps:0}],sn:"System$IConvertible$ToInt16",rt:$n[0].Int16,p:[$n[0].IFormatProvider],box:function($v){return H5.box($v,System.Int16)}},{ab:!0,a:2,n:"ToInt32",t:8,pi:[{n:"provider",pt:$n[0].IFormatProvider,ps:0}],sn:"System$IConvertible$ToInt32",rt:$n[0].Int32,p:[$n[0].IFormatProvider],box:function($v){return H5.box($v,System.Int32)}},{ab:!0,a:2,n:"ToInt64",t:8,pi:[{n:"provider",pt:$n[0].IFormatProvider,ps:0}],sn:"System$IConvertible$ToInt64",rt:$n[0].Int64,p:[$n[0].IFormatProvider]},{ab:!0,a:2,n:"ToSByte",t:8,pi:[{n:"provider",pt:$n[0].IFormatProvider,ps:0}],sn:"System$IConvertible$ToSByte",rt:$n[0].SByte,p:[$n[0].IFormatProvider],box:function($v){return H5.box($v,System.SByte)}},{ab:!0,a:2,n:"ToSingle",t:8,pi:[{n:"provider",pt:$n[0].IFormatProvider,ps:0}],sn:"System$IConvertible$ToSingle",rt:$n[0].Single,p:[$n[0].IFormatProvider],box:function($v){return H5.box($v,System.Single,System.Single.format,System.Single.getHashCode)}},{ab:!0,a:2,n:"ToString",t:8,pi:[{n:"provider",pt:$n[0].IFormatProvider,ps:0}],sn:"System$IConvertible$ToString",rt:$n[0].String,p:[$n[0].IFormatProvider]},{ab:!0,a:2,n:"ToType",t:8,pi:[{n:"conversionType",pt:$n[0].Type,ps:0},{n:"provider",pt:$n[0].IFormatProvider,ps:1}],sn:"System$IConvertible$ToType",rt:$n[0].Object,p:[$n[0].Type,$n[0].IFormatProvider]},{ab:!0,a:2,n:"ToUInt16",t:8,pi:[{n:"provider",pt:$n[0].IFormatProvider,ps:0}],sn:"System$IConvertible$ToUInt16",rt:$n[0].UInt16,p:[$n[0].IFormatProvider],box:function($v){return H5.box($v,System.UInt16)}},{ab:!0,a:2,n:"ToUInt32",t:8,pi:[{n:"provider",pt:$n[0].IFormatProvider,ps:0}],sn:"System$IConvertible$ToUInt32",rt:$n[0].UInt32,p:[$n[0].IFormatProvider],box:function($v){return H5.box($v,System.UInt32)}},{ab:!0,a:2,n:"ToUInt64",t:8,pi:[{n:"provider",pt:$n[0].IFormatProvider,ps:0}],sn:"System$IConvertible$ToUInt64",rt:$n[0].UInt64,p:[$n[0].IFormatProvider]}]}},$n);$m("System.IndexOutOfRangeException",function(){return{att:1057025,a:2,at:[new System.SerializableAttribute],m:[{a:2,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].String],pi:[{n:"message",pt:$n[0].String,ps:0}],sn:"$ctor1"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[0].Exception],pi:[{n:"message",pt:$n[0].String,ps:0},{n:"innerException",pt:$n[0].Exception,ps:1}],sn:"$ctor2"}]}},$n);$m("System.InvalidCastException",function(){return{att:1056769,a:2,at:[new System.SerializableAttribute],m:[{a:2,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].String],pi:[{n:"message",pt:$n[0].String,ps:0}],sn:"$ctor1"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[0].Exception],pi:[{n:"message",pt:$n[0].String,ps:0},{n:"innerException",pt:$n[0].Exception,ps:1}],sn:"$ctor2"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[0].Int32],pi:[{n:"message",pt:$n[0].String,ps:0},{n:"errorCode",pt:$n[0].Int32,ps:1}],sn:"$ctor3"}]}},$n);$m("System.InvalidOperationException",function(){return{att:1056769,a:2,at:[new System.SerializableAttribute],m:[{a:2,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].String],pi:[{n:"message",pt:$n[0].String,ps:0}],sn:"$ctor1"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[0].Exception],pi:[{n:"message",pt:$n[0].String,ps:0},{n:"innerException",pt:$n[0].Exception,ps:1}],sn:"$ctor2"}]}},$n);$m("System.InvalidProgramException",function(){return{att:1057025,a:2,at:[new System.SerializableAttribute],m:[{a:2,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].String],pi:[{n:"message",pt:$n[0].String,ps:0}],sn:"$ctor1"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[0].Exception],pi:[{n:"message",pt:$n[0].String,ps:0},{n:"inner",pt:$n[0].Exception,ps:1}],sn:"$ctor2"}]}},$n);$m("System.NotImplemented",function(){return{att:1048960,a:4,s:!0,m:[{a:4,n:"ByDesignWithMessage",is:!0,t:8,pi:[{n:"message",pt:$n[0].String,ps:0}],sn:"ByDesignWithMessage",rt:$n[0].Exception,p:[$n[0].String]},{a:4,n:"ByDesign",is:!0,t:16,rt:$n[0].Exception,g:{a:4,n:"get_ByDesign",t:8,rt:$n[0].Exception,fg:"ByDesign",is:!0},fn:"ByDesign"}]}},$n);$m("System.NotImplementedException",function(){return{att:1056769,a:2,at:[new System.SerializableAttribute],m:[{a:2,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].String],pi:[{n:"message",pt:$n[0].String,ps:0}],sn:"$ctor1"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[0].Exception],pi:[{n:"message",pt:$n[0].String,ps:0},{n:"inner",pt:$n[0].Exception,ps:1}],sn:"$ctor2"}]}},$n);$m("System.NotSupportedException",function(){return{att:1056769,a:2,at:[new System.SerializableAttribute],m:[{a:2,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].String],pi:[{n:"message",pt:$n[0].String,ps:0}],sn:"$ctor1"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[0].Exception],pi:[{n:"message",pt:$n[0].String,ps:0},{n:"innerException",pt:$n[0].Exception,ps:1}],sn:"$ctor2"}]}},$n);$m("System.NullReferenceException",function(){return{att:1056769,a:2,at:[new System.SerializableAttribute],m:[{a:2,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].String],pi:[{n:"message",pt:$n[0].String,ps:0}],sn:"$ctor1"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[0].Exception],pi:[{n:"message",pt:$n[0].String,ps:0},{n:"innerException",pt:$n[0].Exception,ps:1}],sn:"$ctor2"}]}},$n);$m("System.ObjectDisposedException",function(){return{att:1056769,a:2,at:[new System.SerializableAttribute],m:[{a:1,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].String],pi:[{n:"objectName",pt:$n[0].String,ps:0}],sn:"$ctor1"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[0].Exception],pi:[{n:"message",pt:$n[0].String,ps:0},{n:"innerException",pt:$n[0].Exception,ps:1}],sn:"$ctor2"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[0].String],pi:[{n:"objectName",pt:$n[0].String,ps:0},{n:"message",pt:$n[0].String,ps:1}],sn:"$ctor3"},{ov:!0,a:2,n:"Message",t:16,rt:$n[0].String,g:{ov:!0,a:2,n:"get_Message",t:8,rt:$n[0].String,fg:"Message"},fn:"Message"},{a:2,n:"ObjectName",t:16,rt:$n[0].String,g:{a:2,n:"get_ObjectName",t:8,rt:$n[0].String,fg:"ObjectName"},fn:"ObjectName"},{a:1,n:"_objectName",t:4,rt:$n[0].String,sn:"_objectName"}]}},$n);$m("System.OperationCanceledException",function(){return{att:1056769,a:2,at:[new System.SerializableAttribute],m:[{a:2,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].String],pi:[{n:"message",pt:$n[0].String,ps:0}],sn:"$ctor1"},{a:2,n:".ctor",t:1,p:[$n[2].CancellationToken],pi:[{n:"token",pt:$n[2].CancellationToken,ps:0}],sn:"$ctor5"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[0].Exception],pi:[{n:"message",pt:$n[0].String,ps:0},{n:"innerException",pt:$n[0].Exception,ps:1}],sn:"$ctor2"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[2].CancellationToken],pi:[{n:"message",pt:$n[0].String,ps:0},{n:"token",pt:$n[2].CancellationToken,ps:1}],sn:"$ctor4"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[0].Exception,$n[2].CancellationToken],pi:[{n:"message",pt:$n[0].String,ps:0},{n:"innerException",pt:$n[0].Exception,ps:1},{n:"token",pt:$n[2].CancellationToken,ps:2}],sn:"$ctor3"},{a:2,n:"CancellationToken",t:16,rt:$n[2].CancellationToken,g:{a:2,n:"get_CancellationToken",t:8,rt:$n[2].CancellationToken,fg:"CancellationToken"},s:{a:1,n:"set_CancellationToken",t:8,p:[$n[2].CancellationToken],rt:$n[0].Void,fs:"CancellationToken"},fn:"CancellationToken"},{a:1,n:"_cancellationToken",t:4,rt:$n[2].CancellationToken,sn:"_cancellationToken"}]}},$n);$m("System.OutOfMemoryException",function(){return{att:1056769,a:2,at:[new System.SerializableAttribute],m:[{a:2,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].String],pi:[{n:"message",pt:$n[0].String,ps:0}],sn:"$ctor1"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[0].Exception],pi:[{n:"message",pt:$n[0].String,ps:0},{n:"innerException",pt:$n[0].Exception,ps:1}],sn:"$ctor2"}]}},$n);$m("System.OverflowException",function(){return{att:1056769,a:2,at:[new System.SerializableAttribute],m:[{a:2,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].String],pi:[{n:"message",pt:$n[0].String,ps:0}],sn:"$ctor1"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[0].Exception],pi:[{n:"message",pt:$n[0].String,ps:0},{n:"innerException",pt:$n[0].Exception,ps:1}],sn:"$ctor2"}]}},$n);$m("System.Random",function(){return{att:1048577,a:2,m:[{a:2,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].Int32],pi:[{n:"seed",pt:$n[0].Int32,ps:0}],sn:"$ctor1"},{a:1,n:"GetSampleForLargeRange",t:8,sn:"GetSampleForLargeRange",rt:$n[0].Double,box:function($v){return H5.box($v,System.Double,System.Double.format,System.Double.getHashCode)}},{a:1,n:"InternalSample",t:8,sn:"InternalSample",rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}},{v:!0,a:2,n:"Next",t:8,sn:"Next",rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}},{v:!0,a:2,n:"Next",t:8,pi:[{n:"maxValue",pt:$n[0].Int32,ps:0}],sn:"Next$1",rt:$n[0].Int32,p:[$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{v:!0,a:2,n:"Next",t:8,pi:[{n:"minValue",pt:$n[0].Int32,ps:0},{n:"maxValue",pt:$n[0].Int32,ps:1}],sn:"Next$2",rt:$n[0].Int32,p:[$n[0].Int32,$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{v:!0,a:2,n:"NextBytes",t:8,pi:[{n:"buffer",pt:$n[0].Array.type(System.Byte),ps:0}],sn:"NextBytes",rt:$n[0].Void,p:[$n[0].Array.type(System.Byte)]},{v:!0,a:2,n:"NextDouble",t:8,sn:"NextDouble",rt:$n[0].Double,box:function($v){return H5.box($v,System.Double,System.Double.format,System.Double.getHashCode)}},{v:!0,a:2,n:"NextInt64",t:8,sn:"NextInt64",rt:$n[0].Int64},{v:!0,a:2,n:"NextInt64",t:8,pi:[{n:"maxValue",pt:$n[0].Int64,ps:0}],sn:"NextInt64$1",rt:$n[0].Int64,p:[$n[0].Int64]},{v:!0,a:2,n:"NextInt64",t:8,pi:[{n:"minValue",pt:$n[0].Int64,ps:0},{n:"maxValue",pt:$n[0].Int64,ps:1}],sn:"NextInt64$2",rt:$n[0].Int64,p:[$n[0].Int64,$n[0].Int64]},{v:!0,a:2,n:"NextSingle",t:8,sn:"NextSingle",rt:$n[0].Single,box:function($v){return H5.box($v,System.Single,System.Single.format,System.Single.getHashCode)}},{v:!0,a:3,n:"Sample",t:8,sn:"Sample",rt:$n[0].Double,box:function($v){return H5.box($v,System.Double,System.Double.format,System.Double.getHashCode)}},{a:2,n:"Shared",is:!0,t:16,rt:$n[0].Random,g:{a:2,n:"get_Shared",t:8,rt:$n[0].Random,fg:"Shared",is:!0},fn:"Shared"},{a:1,n:"MBIG",is:!0,t:4,rt:$n[0].Int32,sn:"MBIG",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"MSEED",is:!0,t:4,rt:$n[0].Int32,sn:"MSEED",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"MZ",is:!0,t:4,rt:$n[0].Int32,sn:"MZ",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"SeedArray",t:4,rt:$n[0].Array.type(System.Int32),sn:"SeedArray"},{a:1,n:"inext",t:4,rt:$n[0].Int32,sn:"inext",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"inextp",t:4,rt:$n[0].Int32,sn:"inextp",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"t_shared",is:!0,t:4,rt:$n[0].Random,sn:"t_shared"}]}},$n);$m("System.RankException",function(){return{att:1056769,a:2,at:[new System.SerializableAttribute],m:[{a:2,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].String],pi:[{n:"message",pt:$n[0].String,ps:0}],sn:"$ctor1"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[0].Exception],pi:[{n:"message",pt:$n[0].String,ps:0},{n:"innerException",pt:$n[0].Exception,ps:1}],sn:"$ctor2"}]}},$n);$m("System.SerializableAttribute",function(){return{att:1048833,a:2,m:[{a:2,n:".ctor",t:1,sn:"ctor"}],ni:!0}},$n);$m("System.SR",function(){return{att:1048960,a:4,s:!0,m:[{a:4,n:"Format",is:!0,t:8,pi:[{n:"resourceFormat",pt:$n[0].String,ps:0},{n:"p1",pt:$n[0].Object,ps:1}],sn:"Format",rt:$n[0].String,p:[$n[0].String,$n[0].Object]},{a:4,n:"Format",is:!0,t:8,pi:[{n:"resourceFormat",pt:$n[0].String,ps:0},{n:"args",ip:!0,pt:$n[0].Array.type(System.Object),ps:1}],sn:"Format$3",rt:$n[0].String,p:[$n[0].String,$n[0].Array.type(System.Object)]},{a:4,n:"Format",is:!0,t:8,pi:[{n:"resourceFormat",pt:$n[0].String,ps:0},{n:"p1",pt:$n[0].Object,ps:1},{n:"p2",pt:$n[0].Object,ps:2}],sn:"Format$1",rt:$n[0].String,p:[$n[0].String,$n[0].Object,$n[0].Object]},{a:4,n:"Format",is:!0,t:8,pi:[{n:"resourceFormat",pt:$n[0].String,ps:0},{n:"p1",pt:$n[0].Object,ps:1},{n:"p2",pt:$n[0].Object,ps:2},{n:"p3",pt:$n[0].Object,ps:3}],sn:"Format$2",rt:$n[0].String,p:[$n[0].String,$n[0].Object,$n[0].Object,$n[0].Object]},{a:4,n:"GetResourceString",is:!0,t:8,pi:[{n:"resourceKey",pt:$n[0].String,ps:0}],sn:"GetResourceString",rt:$n[0].String,p:[$n[0].String]},{a:4,n:"GetResourceString",is:!0,t:8,pi:[{n:"resourceKey",pt:$n[0].String,ps:0},{n:"defaultString",pt:$n[0].String,ps:1}],sn:"GetResourceString$1",rt:$n[0].String,p:[$n[0].String,$n[0].String]},{a:1,n:"InternalGetResourceString",is:!0,t:8,pi:[{n:"key",pt:$n[0].String,ps:0}],sn:"InternalGetResourceString",rt:$n[0].String,p:[$n[0].String]},{a:1,n:"UsingResourceKeys",is:!0,t:8,sn:"UsingResourceKeys",rt:$n[0].Boolean,box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"ResourceManager",is:!0,t:16,rt:System.Object,g:{a:1,n:"get_ResourceManager",t:8,rt:System.Object,fg:"ResourceManager",is:!0},s:{a:1,n:"set_ResourceManager",t:8,p:[System.Object],rt:$n[0].Void,fs:"ResourceManager",is:!0},fn:"ResourceManager"},{a:2,n:"ArgumentException_ValueTupleIncorrectType",is:!0,t:4,rt:$n[0].String,sn:"ArgumentException_ValueTupleIncorrectType"},{a:2,n:"ArgumentException_ValueTupleLastArgumentNotAValueTuple",is:!0,t:4,rt:$n[0].String,sn:"ArgumentException_ValueTupleLastArgumentNotAValueTuple"},{a:1,backing:!0,n:"k__BackingField",is:!0,t:4,rt:System.Object,sn:"ResourceManager"}]}},$n);$m("System.StringComparison",function(){return{att:257,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:"CurrentCulture",is:!0,t:4,rt:$n[0].StringComparison,sn:"CurrentCulture",box:function($v){return H5.box($v,System.StringComparison,System.Enum.toStringFn(System.StringComparison))}},{a:2,n:"CurrentCultureIgnoreCase",is:!0,t:4,rt:$n[0].StringComparison,sn:"CurrentCultureIgnoreCase",box:function($v){return H5.box($v,System.StringComparison,System.Enum.toStringFn(System.StringComparison))}},{a:2,n:"InvariantCulture",is:!0,t:4,rt:$n[0].StringComparison,sn:"InvariantCulture",box:function($v){return H5.box($v,System.StringComparison,System.Enum.toStringFn(System.StringComparison))}},{a:2,n:"InvariantCultureIgnoreCase",is:!0,t:4,rt:$n[0].StringComparison,sn:"InvariantCultureIgnoreCase",box:function($v){return H5.box($v,System.StringComparison,System.Enum.toStringFn(System.StringComparison))}},{a:2,n:"Ordinal",is:!0,t:4,rt:$n[0].StringComparison,sn:"Ordinal",box:function($v){return H5.box($v,System.StringComparison,System.Enum.toStringFn(System.StringComparison))}},{a:2,n:"OrdinalIgnoreCase",is:!0,t:4,rt:$n[0].StringComparison,sn:"OrdinalIgnoreCase",box:function($v){return H5.box($v,System.StringComparison,System.Enum.toStringFn(System.StringComparison))}}]}},$n);$m("System.StringSplitOptions",function(){return{att:257,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:"None",is:!0,t:4,rt:$n[0].StringSplitOptions,sn:"None",box:function($v){return H5.box($v,System.StringSplitOptions,System.Enum.toStringFn(System.StringSplitOptions))}},{a:2,n:"RemoveEmptyEntries",is:!0,t:4,rt:$n[0].StringSplitOptions,sn:"RemoveEmptyEntries",box:function($v){return H5.box($v,System.StringSplitOptions,System.Enum.toStringFn(System.StringSplitOptions))}}]}},$n);$m("System.SystemException",function(){return{att:1056769,a:2,at:[new System.SerializableAttribute],m:[{a:2,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].String],pi:[{n:"message",pt:$n[0].String,ps:0}],sn:"$ctor1"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[0].Exception],pi:[{n:"message",pt:$n[0].String,ps:0},{n:"innerException",pt:$n[0].Exception,ps:1}],sn:"$ctor2"}]}},$n);$m("System.ThrowHelper",function(){return{att:1048960,a:4,s:!0,m:[{a:1,n:"GetAddingDuplicateWithKeyArgumentException",is:!0,t:8,pi:[{n:"key",pt:$n[0].Object,ps:0}],sn:"GetAddingDuplicateWithKeyArgumentException",rt:$n[0].ArgumentException,p:[$n[0].Object]},{a:1,n:"GetArgumentException",is:!0,t:8,pi:[{n:"resource",pt:$n[0].ExceptionResource,ps:0}],sn:"GetArgumentException",rt:$n[0].ArgumentException,p:[$n[0].ExceptionResource]},{a:1,n:"GetArgumentException",is:!0,t:8,pi:[{n:"resource",pt:$n[0].ExceptionResource,ps:0},{n:"argument",pt:$n[0].ExceptionArgument,ps:1}],sn:"GetArgumentException$1",rt:$n[0].ArgumentException,p:[$n[0].ExceptionResource,$n[0].ExceptionArgument]},{a:1,n:"GetArgumentName",is:!0,t:8,pi:[{n:"argument",pt:$n[0].ExceptionArgument,ps:0}],sn:"GetArgumentName",rt:$n[0].String,p:[$n[0].ExceptionArgument]},{a:1,n:"GetArgumentNullException",is:!0,t:8,pi:[{n:"argument",pt:$n[0].ExceptionArgument,ps:0}],sn:"GetArgumentNullException",rt:$n[0].ArgumentNullException,p:[$n[0].ExceptionArgument]},{a:4,n:"GetArgumentOutOfRangeException",is:!0,t:8,pi:[{n:"argument",pt:$n[0].ExceptionArgument,ps:0},{n:"resource",pt:$n[0].ExceptionResource,ps:1}],sn:"GetArgumentOutOfRangeException",rt:$n[0].ArgumentOutOfRangeException,p:[$n[0].ExceptionArgument,$n[0].ExceptionResource]},{a:1,n:"GetArgumentOutOfRangeException",is:!0,t:8,pi:[{n:"argument",pt:$n[0].ExceptionArgument,ps:0},{n:"paramNumber",pt:$n[0].Int32,ps:1},{n:"resource",pt:$n[0].ExceptionResource,ps:2}],sn:"GetArgumentOutOfRangeException$1",rt:$n[0].ArgumentOutOfRangeException,p:[$n[0].ExceptionArgument,$n[0].Int32,$n[0].ExceptionResource]},{a:1,n:"GetArraySegmentCtorValidationFailedException",is:!0,t:8,pi:[{n:"array",pt:Array,ps:0},{n:"offset",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2}],sn:"GetArraySegmentCtorValidationFailedException",rt:$n[0].Exception,p:[Array,$n[0].Int32,$n[0].Int32]},{a:4,n:"GetInvalidOperationException",is:!0,t:8,pi:[{n:"resource",pt:$n[0].ExceptionResource,ps:0}],sn:"GetInvalidOperationException",rt:$n[0].InvalidOperationException,p:[$n[0].ExceptionResource]},{a:1,n:"GetInvalidOperationException_EnumCurrent",is:!0,t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0}],sn:"GetInvalidOperationException_EnumCurrent",rt:$n[0].InvalidOperationException,p:[$n[0].Int32]},{a:1,n:"GetKeyNotFoundException",is:!0,t:8,pi:[{n:"key",pt:$n[0].Object,ps:0}],sn:"GetKeyNotFoundException",rt:$n[3].KeyNotFoundException,p:[$n[0].Object]},{a:1,n:"GetResourceString",is:!0,t:8,pi:[{n:"resource",pt:$n[0].ExceptionResource,ps:0}],sn:"GetResourceString",rt:$n[0].String,p:[$n[0].ExceptionResource]},{a:1,n:"GetWrongKeyTypeArgumentException",is:!0,t:8,pi:[{n:"key",pt:$n[0].Object,ps:0},{n:"targetType",pt:$n[0].Type,ps:1}],sn:"GetWrongKeyTypeArgumentException",rt:$n[0].ArgumentException,p:[$n[0].Object,$n[0].Type]},{a:1,n:"GetWrongValueTypeArgumentException",is:!0,t:8,pi:[{n:"value",pt:$n[0].Object,ps:0},{n:"targetType",pt:$n[0].Type,ps:1}],sn:"GetWrongValueTypeArgumentException",rt:$n[0].ArgumentException,p:[$n[0].Object,$n[0].Type]},{a:4,n:"IfNullAndNullsAreIllegalThenThrow",is:!0,t:8,pi:[{n:"value",pt:$n[0].Object,ps:0},{n:"argName",pt:$n[0].ExceptionArgument,ps:1}],tpc:1,tprm:["T"],sn:"IfNullAndNullsAreIllegalThenThrow",rt:$n[0].Void,p:[$n[0].Object,$n[0].ExceptionArgument]},{a:4,n:"ThrowAddingDuplicateWithKeyArgumentException",is:!0,t:8,pi:[{n:"key",pt:System.Object,ps:0}],tpc:1,tprm:["T"],sn:"ThrowAddingDuplicateWithKeyArgumentException",rt:$n[0].Void,p:[System.Object]},{a:4,n:"ThrowAggregateException",is:!0,t:8,pi:[{n:"exceptions",pt:$n[3].List$1(System.Exception),ps:0}],sn:"ThrowAggregateException",rt:$n[0].Void,p:[$n[3].List$1(System.Exception)]},{a:4,n:"ThrowArgumentException",is:!0,t:8,pi:[{n:"resource",pt:$n[0].ExceptionResource,ps:0}],sn:"ThrowArgumentException",rt:$n[0].Void,p:[$n[0].ExceptionResource]},{a:4,n:"ThrowArgumentException",is:!0,t:8,pi:[{n:"resource",pt:$n[0].ExceptionResource,ps:0},{n:"argument",pt:$n[0].ExceptionArgument,ps:1}],sn:"ThrowArgumentException$1",rt:$n[0].Void,p:[$n[0].ExceptionResource,$n[0].ExceptionArgument]},{a:4,n:"ThrowArgumentException_Argument_InvalidArrayType",is:!0,t:8,sn:"ThrowArgumentException_Argument_InvalidArrayType",rt:$n[0].Void},{a:4,n:"ThrowArgumentException_DestinationTooShort",is:!0,t:8,sn:"ThrowArgumentException_DestinationTooShort",rt:$n[0].Void},{a:4,n:"ThrowArgumentException_OverlapAlignmentMismatch",is:!0,t:8,sn:"ThrowArgumentException_OverlapAlignmentMismatch",rt:$n[0].Void},{a:4,n:"ThrowArgumentNullException",is:!0,t:8,pi:[{n:"argument",pt:$n[0].ExceptionArgument,ps:0}],sn:"ThrowArgumentNullException",rt:$n[0].Void,p:[$n[0].ExceptionArgument]},{a:4,n:"ThrowArgumentNullException",is:!0,t:8,pi:[{n:"resource",pt:$n[0].ExceptionResource,ps:0}],sn:"ThrowArgumentNullException$2",rt:$n[0].Void,p:[$n[0].ExceptionResource]},{a:4,n:"ThrowArgumentNullException",is:!0,t:8,pi:[{n:"argument",pt:$n[0].ExceptionArgument,ps:0},{n:"resource",pt:$n[0].ExceptionResource,ps:1}],sn:"ThrowArgumentNullException$1",rt:$n[0].Void,p:[$n[0].ExceptionArgument,$n[0].ExceptionResource]},{a:4,n:"ThrowArgumentOutOfRangeException",is:!0,t:8,sn:"ThrowArgumentOutOfRangeException",rt:$n[0].Void},{a:4,n:"ThrowArgumentOutOfRangeException",is:!0,t:8,pi:[{n:"argument",pt:$n[0].ExceptionArgument,ps:0}],sn:"ThrowArgumentOutOfRangeException$1",rt:$n[0].Void,p:[$n[0].ExceptionArgument]},{a:4,n:"ThrowArgumentOutOfRangeException",is:!0,t:8,pi:[{n:"argument",pt:$n[0].ExceptionArgument,ps:0},{n:"resource",pt:$n[0].ExceptionResource,ps:1}],sn:"ThrowArgumentOutOfRangeException$2",rt:$n[0].Void,p:[$n[0].ExceptionArgument,$n[0].ExceptionResource]},{a:4,n:"ThrowArgumentOutOfRangeException",is:!0,t:8,pi:[{n:"argument",pt:$n[0].ExceptionArgument,ps:0},{n:"paramNumber",pt:$n[0].Int32,ps:1},{n:"resource",pt:$n[0].ExceptionResource,ps:2}],sn:"ThrowArgumentOutOfRangeException$3",rt:$n[0].Void,p:[$n[0].ExceptionArgument,$n[0].Int32,$n[0].ExceptionResource]},{a:4,n:"ThrowArgumentOutOfRange_IndexException",is:!0,t:8,sn:"ThrowArgumentOutOfRange_IndexException",rt:$n[0].Void},{a:4,n:"ThrowArraySegmentCtorValidationFailedExceptions",is:!0,t:8,pi:[{n:"array",pt:Array,ps:0},{n:"offset",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2}],sn:"ThrowArraySegmentCtorValidationFailedExceptions",rt:$n[0].Void,p:[Array,$n[0].Int32,$n[0].Int32]},{a:4,n:"ThrowArrayTypeMismatchException",is:!0,t:8,sn:"ThrowArrayTypeMismatchException",rt:$n[0].Void},{a:4,n:"ThrowCountArgumentOutOfRange_ArgumentOutOfRange_Count",is:!0,t:8,sn:"ThrowCountArgumentOutOfRange_ArgumentOutOfRange_Count",rt:$n[0].Void},{a:4,n:"ThrowIndexArgumentOutOfRange_NeedNonNegNumException",is:!0,t:8,sn:"ThrowIndexArgumentOutOfRange_NeedNonNegNumException",rt:$n[0].Void},{a:4,n:"ThrowIndexOutOfRangeException",is:!0,t:8,sn:"ThrowIndexOutOfRangeException",rt:$n[0].Void},{a:4,n:"ThrowInvalidOperationException",is:!0,t:8,pi:[{n:"resource",pt:$n[0].ExceptionResource,ps:0}],sn:"ThrowInvalidOperationException",rt:$n[0].Void,p:[$n[0].ExceptionResource]},{a:4,n:"ThrowInvalidOperationException",is:!0,t:8,pi:[{n:"resource",pt:$n[0].ExceptionResource,ps:0},{n:"e",pt:$n[0].Exception,ps:1}],sn:"ThrowInvalidOperationException$1",rt:$n[0].Void,p:[$n[0].ExceptionResource,$n[0].Exception]},{a:4,n:"ThrowInvalidOperationException_EnumCurrent",is:!0,t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0}],sn:"ThrowInvalidOperationException_EnumCurrent",rt:$n[0].Void,p:[$n[0].Int32]},{a:4,n:"ThrowInvalidOperationException_InvalidOperation_EnumEnded",is:!0,t:8,sn:"ThrowInvalidOperationException_InvalidOperation_EnumEnded",rt:$n[0].Void},{a:4,n:"ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion",is:!0,t:8,sn:"ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion",rt:$n[0].Void},{a:4,n:"ThrowInvalidOperationException_InvalidOperation_EnumNotStarted",is:!0,t:8,sn:"ThrowInvalidOperationException_InvalidOperation_EnumNotStarted",rt:$n[0].Void},{a:4,n:"ThrowInvalidOperationException_InvalidOperation_EnumOpCantHappen",is:!0,t:8,sn:"ThrowInvalidOperationException_InvalidOperation_EnumOpCantHappen",rt:$n[0].Void},{a:4,n:"ThrowInvalidOperationException_InvalidOperation_NoValue",is:!0,t:8,sn:"ThrowInvalidOperationException_InvalidOperation_NoValue",rt:$n[0].Void},{a:4,n:"ThrowInvalidOperationException_OutstandingReferences",is:!0,t:8,sn:"ThrowInvalidOperationException_OutstandingReferences",rt:$n[0].Void},{a:4,n:"ThrowInvalidTypeWithPointersNotSupported",is:!0,t:8,pi:[{n:"targetType",pt:$n[0].Type,ps:0}],sn:"ThrowInvalidTypeWithPointersNotSupported",rt:$n[0].Void,p:[$n[0].Type]},{a:4,n:"ThrowKeyNotFoundException",is:!0,t:8,pi:[{n:"key",pt:System.Object,ps:0}],tpc:1,tprm:["T"],sn:"ThrowKeyNotFoundException",rt:$n[0].Void,p:[System.Object]},{a:4,n:"ThrowLengthArgumentOutOfRange_ArgumentOutOfRange_NeedNonNegNum",is:!0,t:8,sn:"ThrowLengthArgumentOutOfRange_ArgumentOutOfRange_NeedNonNegNum",rt:$n[0].Void},{a:4,n:"ThrowNotSupportedException",is:!0,t:8,sn:"ThrowNotSupportedException",rt:$n[0].Void},{a:4,n:"ThrowNotSupportedException",is:!0,t:8,pi:[{n:"resource",pt:$n[0].ExceptionResource,ps:0}],sn:"ThrowNotSupportedException$1",rt:$n[0].Void,p:[$n[0].ExceptionResource]},{a:4,n:"ThrowNotSupportedExceptionIfNonNumericType",is:!0,t:8,tpc:1,tprm:["T"],sn:"ThrowNotSupportedExceptionIfNonNumericType",rt:$n[0].Void},{a:4,n:"ThrowObjectDisposedException",is:!0,t:8,pi:[{n:"resource",pt:$n[0].ExceptionResource,ps:0}],sn:"ThrowObjectDisposedException",rt:$n[0].Void,p:[$n[0].ExceptionResource]},{a:4,n:"ThrowObjectDisposedException",is:!0,t:8,pi:[{n:"objectName",pt:$n[0].String,ps:0},{n:"resource",pt:$n[0].ExceptionResource,ps:1}],sn:"ThrowObjectDisposedException$1",rt:$n[0].Void,p:[$n[0].String,$n[0].ExceptionResource]},{a:4,n:"ThrowObjectDisposedException_MemoryDisposed",is:!0,t:8,sn:"ThrowObjectDisposedException_MemoryDisposed",rt:$n[0].Void},{a:4,n:"ThrowOutOfMemoryException",is:!0,t:8,sn:"ThrowOutOfMemoryException",rt:$n[0].Void},{a:4,n:"ThrowRankException",is:!0,t:8,pi:[{n:"resource",pt:$n[0].ExceptionResource,ps:0}],sn:"ThrowRankException",rt:$n[0].Void,p:[$n[0].ExceptionResource]},{a:4,n:"ThrowSecurityException",is:!0,t:8,pi:[{n:"resource",pt:$n[0].ExceptionResource,ps:0}],sn:"ThrowSecurityException",rt:$n[0].Void,p:[$n[0].ExceptionResource]},{a:4,n:"ThrowSerializationException",is:!0,t:8,pi:[{n:"resource",pt:$n[0].ExceptionResource,ps:0}],sn:"ThrowSerializationException",rt:$n[0].Void,p:[$n[0].ExceptionResource]},{a:4,n:"ThrowStartIndexArgumentOutOfRange_ArgumentOutOfRange_Index",is:!0,t:8,sn:"ThrowStartIndexArgumentOutOfRange_ArgumentOutOfRange_Index",rt:$n[0].Void},{a:4,n:"ThrowUnauthorizedAccessException",is:!0,t:8,pi:[{n:"resource",pt:$n[0].ExceptionResource,ps:0}],sn:"ThrowUnauthorizedAccessException",rt:$n[0].Void,p:[$n[0].ExceptionResource]},{a:4,n:"ThrowWrongKeyTypeArgumentException",is:!0,t:8,pi:[{n:"key",pt:System.Object,ps:0},{n:"targetType",pt:$n[0].Type,ps:1}],tpc:1,tprm:["T"],sn:"ThrowWrongKeyTypeArgumentException",rt:$n[0].Void,p:[System.Object,$n[0].Type]},{a:4,n:"ThrowWrongValueTypeArgumentException",is:!0,t:8,pi:[{n:"value",pt:System.Object,ps:0},{n:"targetType",pt:$n[0].Type,ps:1}],tpc:1,tprm:["T"],sn:"ThrowWrongValueTypeArgumentException",rt:$n[0].Void,p:[System.Object,$n[0].Type]}]}},$n);$m("System.ExceptionArgument",function(){return{att:256,a:4,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:"action",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"action",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"array",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"array",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"arrayIndex",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"arrayIndex",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"asyncResult",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"asyncResult",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"beginMethod",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"beginMethod",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"callBack",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"callBack",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"cancellationToken",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"cancellationToken",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"capacity",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"capacity",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"collection",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"collection",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"comparable",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"comparable",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"comparer",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"comparer",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"comparison",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"comparison",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"concurrencyLevel",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"concurrencyLevel",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"continuationAction",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"continuationAction",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"continuationFunction",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"continuationFunction",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"continuationOptions",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"continuationOptions",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"converter",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"converter",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"count",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"count",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"creationOptions",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"creationOptions",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"culture",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"culture",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"delay",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"delay",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"destinationArray",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"destinationArray",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"destinationIndex",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"destinationIndex",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"dictionary",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"dictionary",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"elementType",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"elementType",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"endFunction",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"endFunction",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"endIndex",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"endIndex",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"endMethod",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"endMethod",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"exception",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"exception",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"exceptions",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"exceptions",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"format",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"format",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"function",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"function",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"index",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"index",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"index1",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"index1",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"index2",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"index2",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"index3",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"index3",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"indices",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"indices",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"info",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"info",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"input",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"input",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"item",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"item",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"key",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"key",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"keyValuePair",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"keyValuePair",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"keys",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"keys",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"len",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"len",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"length",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"$length",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"length1",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"length1",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"length2",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"length2",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"length3",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"length3",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"lengths",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"lengths",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"list",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"list",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"lowerBounds",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"lowerBounds",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"match",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"match",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"millisecondsDelay",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"millisecondsDelay",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"millisecondsTimeout",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"millisecondsTimeout",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"name",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"$name",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"newSize",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"newSize",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"obj",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"obj",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"offset",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"offset",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"options",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"options",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"other",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"other",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"ownedMemory",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"ownedMemory",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"pHandle",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"pHandle",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"pointer",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"pointer",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"s",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"s",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"scheduler",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"scheduler",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"source",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"source",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"sourceArray",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"sourceArray",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"sourceBytesToCopy",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"sourceBytesToCopy",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"sourceIndex",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"sourceIndex",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"start",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"start",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"startIndex",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"startIndex",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"state",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"state",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"stateMachine",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"stateMachine",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"task",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"task",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"tasks",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"tasks",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"text",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"text",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"timeout",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"timeout",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"type",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"type",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"value",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"value",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"values",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"values",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}},{a:2,n:"view",is:!0,t:4,rt:$n[0].ExceptionArgument,sn:"view",box:function($v){return H5.box($v,System.ExceptionArgument,System.Enum.toStringFn(System.ExceptionArgument))}}]}},$n);$m("System.ExceptionResource",function(){return{att:256,a:4,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:"Arg_ArrayPlusOffTooSmall",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"Arg_ArrayPlusOffTooSmall",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"Arg_BogusIComparer",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"Arg_BogusIComparer",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"Arg_LowerBoundsMustMatch",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"Arg_LowerBoundsMustMatch",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"Arg_MustBeType",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"Arg_MustBeType",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"Arg_Need1DArray",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"Arg_Need1DArray",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"Arg_Need2DArray",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"Arg_Need2DArray",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"Arg_Need3DArray",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"Arg_Need3DArray",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"Arg_NeedAtLeast1Rank",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"Arg_NeedAtLeast1Rank",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"Arg_NonZeroLowerBound",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"Arg_NonZeroLowerBound",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"Arg_RankIndices",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"Arg_RankIndices",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"Arg_RankMultiDimNotSupported",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"Arg_RankMultiDimNotSupported",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"Arg_RanksAndBounds",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"Arg_RanksAndBounds",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"Arg_RegKeyDelHive",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"Arg_RegKeyDelHive",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"Arg_RegKeyStrLenBug",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"Arg_RegKeyStrLenBug",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"Arg_RegSetMismatchedKind",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"Arg_RegSetMismatchedKind",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"Arg_RegSetStrArrNull",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"Arg_RegSetStrArrNull",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"Arg_RegSubKeyAbsent",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"Arg_RegSubKeyAbsent",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"Arg_RegSubKeyValueAbsent",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"Arg_RegSubKeyValueAbsent",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"ArgumentException_OtherNotArrayOfCorrectLength",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"ArgumentException_OtherNotArrayOfCorrectLength",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"ArgumentNull_SafeHandle",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"ArgumentNull_SafeHandle",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"ArgumentOutOfRange_BiggerThanCollection",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"ArgumentOutOfRange_BiggerThanCollection",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"ArgumentOutOfRange_Count",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"ArgumentOutOfRange_Count",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"ArgumentOutOfRange_EndIndexStartIndex",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"ArgumentOutOfRange_EndIndexStartIndex",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"ArgumentOutOfRange_Enum",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"ArgumentOutOfRange_Enum",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"ArgumentOutOfRange_HugeArrayNotSupported",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"ArgumentOutOfRange_HugeArrayNotSupported",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"ArgumentOutOfRange_Index",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"ArgumentOutOfRange_Index",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"ArgumentOutOfRange_InvalidThreshold",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"ArgumentOutOfRange_InvalidThreshold",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"ArgumentOutOfRange_ListInsert",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"ArgumentOutOfRange_ListInsert",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"ArgumentOutOfRange_NeedNonNegNum",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"ArgumentOutOfRange_NeedNonNegNum",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"ArgumentOutOfRange_SmallCapacity",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"ArgumentOutOfRange_SmallCapacity",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"Argument_AddingDuplicate",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"Argument_AddingDuplicate",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"Argument_ImplementIComparable",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"Argument_ImplementIComparable",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"Argument_InvalidArgumentForComparison",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"Argument_InvalidArgumentForComparison",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"Argument_InvalidArrayType",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"Argument_InvalidArrayType",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"Argument_InvalidOffLen",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"Argument_InvalidOffLen",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"Argument_InvalidRegistryKeyPermissionCheck",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"Argument_InvalidRegistryKeyPermissionCheck",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"Argument_InvalidRegistryOptionsCheck",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"Argument_InvalidRegistryOptionsCheck",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"Argument_InvalidRegistryViewCheck",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"Argument_InvalidRegistryViewCheck",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"Argument_InvalidType",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"Argument_InvalidType",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"Argument_ItemNotExist",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"Argument_ItemNotExist",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"AsyncMethodBuilder_InstanceNotInitialized",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"AsyncMethodBuilder_InstanceNotInitialized",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"ConcurrentCollection_SyncRoot_NotSupported",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"ConcurrentCollection_SyncRoot_NotSupported",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"ConcurrentDictionary_ArrayIncorrectType",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"ConcurrentDictionary_ArrayIncorrectType",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"ConcurrentDictionary_ArrayNotLargeEnough",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"ConcurrentDictionary_ArrayNotLargeEnough",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"ConcurrentDictionary_CapacityMustNotBeNegative",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"ConcurrentDictionary_CapacityMustNotBeNegative",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"ConcurrentDictionary_ConcurrencyLevelMustBePositive",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"ConcurrentDictionary_ConcurrencyLevelMustBePositive",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"ConcurrentDictionary_IndexIsNegative",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"ConcurrentDictionary_IndexIsNegative",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"ConcurrentDictionary_ItemKeyIsNull",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"ConcurrentDictionary_ItemKeyIsNull",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"ConcurrentDictionary_KeyAlreadyExisted",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"ConcurrentDictionary_KeyAlreadyExisted",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"ConcurrentDictionary_TypeOfKeyIncorrect",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"ConcurrentDictionary_TypeOfKeyIncorrect",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"ConcurrentDictionary_TypeOfValueIncorrect",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"ConcurrentDictionary_TypeOfValueIncorrect",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"InvalidOperation_CannotRemoveFromStackOrQueue",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"InvalidOperation_CannotRemoveFromStackOrQueue",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"InvalidOperation_EmptyQueue",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"InvalidOperation_EmptyQueue",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"InvalidOperation_EmptyStack",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"InvalidOperation_EmptyStack",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"InvalidOperation_EnumEnded",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"InvalidOperation_EnumEnded",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"InvalidOperation_EnumFailedVersion",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"InvalidOperation_EnumFailedVersion",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"InvalidOperation_EnumNotStarted",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"InvalidOperation_EnumNotStarted",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"InvalidOperation_EnumOpCantHappen",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"InvalidOperation_EnumOpCantHappen",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"InvalidOperation_HandleIsNotInitialized",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"InvalidOperation_HandleIsNotInitialized",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"InvalidOperation_IComparerFailed",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"InvalidOperation_IComparerFailed",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"InvalidOperation_NoValue",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"InvalidOperation_NoValue",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"InvalidOperation_NullArray",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"InvalidOperation_NullArray",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"InvalidOperation_RegRemoveSubKey",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"InvalidOperation_RegRemoveSubKey",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"InvalidOperation_WrongAsyncResultOrEndCalledMultiple",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"InvalidOperation_WrongAsyncResultOrEndCalledMultiple",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"MemoryDisposed",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"MemoryDisposed",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"Memory_OutstandingReferences",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"Memory_OutstandingReferences",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"NotSupported_FixedSizeCollection",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"NotSupported_FixedSizeCollection",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"NotSupported_InComparableType",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"NotSupported_InComparableType",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"NotSupported_KeyCollectionSet",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"NotSupported_KeyCollectionSet",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"NotSupported_ReadOnlyCollection",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"NotSupported_ReadOnlyCollection",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"NotSupported_SortedListNestedWrite",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"NotSupported_SortedListNestedWrite",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"NotSupported_ValueCollectionSet",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"NotSupported_ValueCollectionSet",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"ObjectDisposed_RegKeyClosed",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"ObjectDisposed_RegKeyClosed",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"Rank_MultiDimNotSupported",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"Rank_MultiDimNotSupported",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"Security_RegistryPermission",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"Security_RegistryPermission",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"Serialization_InvalidOnDeser",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"Serialization_InvalidOnDeser",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"Serialization_MissingKeys",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"Serialization_MissingKeys",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"Serialization_NullKey",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"Serialization_NullKey",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"TaskCompletionSourceT_TrySetException_NoExceptions",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"TaskCompletionSourceT_TrySetException_NoExceptions",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"TaskCompletionSourceT_TrySetException_NullException",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"TaskCompletionSourceT_TrySetException_NullException",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"TaskT_TransitionToFinal_AlreadyCompleted",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"TaskT_TransitionToFinal_AlreadyCompleted",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"Task_ContinueWith_ESandLR",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"Task_ContinueWith_ESandLR",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"Task_ContinueWith_NotOnAnything",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"Task_ContinueWith_NotOnAnything",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"Task_Delay_InvalidDelay",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"Task_Delay_InvalidDelay",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"Task_Delay_InvalidMillisecondsDelay",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"Task_Delay_InvalidMillisecondsDelay",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"Task_Dispose_NotCompleted",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"Task_Dispose_NotCompleted",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"Task_MultiTaskContinuation_EmptyTaskList",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"Task_MultiTaskContinuation_EmptyTaskList",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"Task_MultiTaskContinuation_NullTask",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"Task_MultiTaskContinuation_NullTask",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"Task_RunSynchronously_AlreadyStarted",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"Task_RunSynchronously_AlreadyStarted",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"Task_RunSynchronously_Continuation",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"Task_RunSynchronously_Continuation",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"Task_RunSynchronously_Promise",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"Task_RunSynchronously_Promise",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"Task_RunSynchronously_TaskCompleted",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"Task_RunSynchronously_TaskCompleted",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"Task_Start_AlreadyStarted",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"Task_Start_AlreadyStarted",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"Task_Start_ContinuationTask",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"Task_Start_ContinuationTask",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"Task_Start_Promise",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"Task_Start_Promise",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"Task_Start_TaskCompleted",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"Task_Start_TaskCompleted",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"Task_ThrowIfDisposed",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"Task_ThrowIfDisposed",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"Task_WaitMulti_NullTask",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"Task_WaitMulti_NullTask",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"Task_ctor_LRandSR",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"Task_ctor_LRandSR",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}},{a:2,n:"UnauthorizedAccess_RegistryNoWrite",is:!0,t:4,rt:$n[0].ExceptionResource,sn:"UnauthorizedAccess_RegistryNoWrite",box:function($v){return H5.box($v,System.ExceptionResource,System.Enum.toStringFn(System.ExceptionResource))}}]}},$n);$m("System.TimeoutException",function(){return{att:1056769,a:2,at:[new System.SerializableAttribute],m:[{a:2,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].String],pi:[{n:"message",pt:$n[0].String,ps:0}],sn:"$ctor1"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[0].Exception],pi:[{n:"message",pt:$n[0].String,ps:0},{n:"innerException",pt:$n[0].Exception,ps:1}],sn:"$ctor2"}]}},$n);$m("System.UnauthorizedAccessException",function(){return{att:1056769,a:2,at:[new System.SerializableAttribute],m:[{a:2,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].String],pi:[{n:"message",pt:$n[0].String,ps:0}],sn:"$ctor1"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[0].Exception],pi:[{n:"message",pt:$n[0].String,ps:0},{n:"inner",pt:$n[0].Exception,ps:1}],sn:"$ctor2"}]}},$n);$m("System.UnhandledExceptionEventArgs",function(){return{att:1048577,a:2,m:[{a:2,n:".ctor",t:1,p:[$n[0].Object,$n[0].Boolean],pi:[{n:"exception",pt:$n[0].Object,ps:0},{n:"isTerminating",pt:$n[0].Boolean,ps:1}],sn:"ctor"},{a:2,n:"ExceptionObject",t:16,rt:$n[0].Object,g:{a:2,n:"get_ExceptionObject",t:8,rt:$n[0].Object,fg:"ExceptionObject"},fn:"ExceptionObject"},{a:2,n:"IsTerminating",t:16,rt:$n[0].Boolean,g:{a:2,n:"get_IsTerminating",t:8,rt:$n[0].Boolean,fg:"IsTerminating",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},fn:"IsTerminating"},{a:1,n:"_exception",t:4,rt:$n[0].Object,sn:"_exception"},{a:1,n:"_isTerminating",t:4,rt:$n[0].Boolean,sn:"_isTerminating",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}}]}},$n);$m("System.UnitySerializationHolder",function(){return{att:1057024,a:4,at:[new System.SerializableAttribute],m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:"GetRealObject",t:8,pi:[{n:"context",pt:$n[4].StreamingContext,ps:0}],sn:"GetRealObject",rt:$n[0].Object,p:[$n[4].StreamingContext]},{a:4,n:"NullUnity",is:!0,t:4,rt:$n[0].Int32,sn:"NullUnity",box:function($v){return H5.box($v,System.Int32)}}]}},$n);$m("System.Void",function(){return{att:1048841,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"}]}},$n);$m("System.AggregateException",function(){return{att:1048577,a:2,m:[{a:2,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[3].IEnumerable$1(System.Exception)],pi:[{n:"innerExceptions",pt:$n[3].IEnumerable$1(System.Exception),ps:0}],def:function(innerExceptions){return new System.AggregateException(null,innerExceptions)}},{a:2,n:".ctor",t:1,p:[$n[0].Array.type(System.Exception)],pi:[{n:"innerExceptions",ip:!0,pt:$n[0].Array.type(System.Exception),ps:0}],def:function(innerExceptions){return new System.AggregateException(null,Array.prototype.slice.call((arguments,0)))}},{a:2,n:".ctor",t:1,p:[$n[0].String],pi:[{n:"message",pt:$n[0].String,ps:0}],sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[3].IEnumerable$1(System.Exception)],pi:[{n:"message",pt:$n[0].String,ps:0},{n:"innerExceptions",pt:$n[3].IEnumerable$1(System.Exception),ps:1}],sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[0].Array.type(System.Exception)],pi:[{n:"message",pt:$n[0].String,ps:0},{n:"innerExceptions",ip:!0,pt:$n[0].Array.type(System.Exception),ps:1}],def:function(message,innerExceptions){return new System.AggregateException(message,Array.prototype.slice.call((arguments,1)))}},{a:2,n:"Flatten",t:8,sn:"flatten",rt:$n[0].AggregateException},{a:2,n:"Handle",t:8,pi:[{n:"predicate",pt:Function,ps:0}],sn:"handle",rt:$n[0].Void,p:[Function]},{a:2,n:"InnerExceptions",t:16,rt:$n[5].ReadOnlyCollection$1(System.Exception),g:{a:2,n:"get_InnerExceptions",t:8,rt:$n[5].ReadOnlyCollection$1(System.Exception),fg:"innerExceptions"},fn:"innerExceptions"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[5].ReadOnlyCollection$1(System.Exception),sn:"innerExceptions"}]}},$n);$m("System.ArraySegment",function(){return{att:1048841,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[System.Array.type(System.Object)],pi:[{n:"array",pt:System.Array.type(System.Object),ps:0}],sn:"ctor"},{a:2,n:".ctor",t:1,p:[System.Array.type(System.Object),$n[0].Int32,$n[0].Int32],pi:[{n:"array",pt:System.Array.type(System.Object),ps:0},{n:"offset",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2}],sn:"ctor"},{a:2,n:"Array",t:16,rt:System.Array.type(System.Object),g:{a:2,n:"get_Array",t:8,tpc:0,def:function(){return this.getArray()},rt:System.Array.type(System.Object)}},{a:2,n:"Count",t:16,rt:$n[0].Int32,g:{a:2,n:"get_Count",t:8,tpc:0,def:function(){return this.getCount()},rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}}},{a:2,n:"Offset",t:16,rt:$n[0].Int32,g:{a:2,n:"get_Offset",t:8,tpc:0,def:function(){return this.getOffset()},rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:System.Array.type(System.Object),sn:"Array"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Int32,sn:"Count",box:function($v){return H5.box($v,System.Int32)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Int32,sn:"Offset",box:function($v){return H5.box($v,System.Int32)}}]}},$n);$m("System.BitConverter",function(){return{att:1048961,a:2,s:!0,m:[{a:1,n:"CheckArguments",is:!0,t:8,pi:[{n:"value",pt:$n[0].Array.type(System.Byte),ps:0},{n:"startIndex",pt:$n[0].Int32,ps:1},{n:"size",pt:$n[0].Int32,ps:2}],sn:"checkArguments",rt:$n[0].Void,p:[$n[0].Array.type(System.Byte),$n[0].Int32,$n[0].Int32]},{a:1,n:"CreateLong",is:!0,t:8,pi:[{n:"low",pt:$n[0].Int32,ps:0},{n:"high",pt:$n[0].Int32,ps:1}],tpc:0,def:function(low,high){return System.Int64([low,high])},rt:$n[0].Int64,p:[$n[0].Int32,$n[0].Int32]},{a:1,n:"CreateULong",is:!0,t:8,pi:[{n:"low",pt:$n[0].Int32,ps:0},{n:"high",pt:$n[0].Int32,ps:1}],tpc:0,def:function(low,high){return System.UInt64([low,high])},rt:$n[0].UInt64,p:[$n[0].Int32,$n[0].Int32]},{a:2,n:"DoubleToInt64Bits",is:!0,t:8,pi:[{n:"value",pt:$n[0].Double,ps:0}],sn:"doubleToInt64Bits",rt:$n[0].Int64,p:[$n[0].Double]},{a:2,n:"GetBytes",is:!0,t:8,pi:[{n:"value",pt:$n[0].Boolean,ps:0}],sn:"getBytes",rt:$n[0].Array.type(System.Byte),p:[$n[0].Boolean]},{a:2,n:"GetBytes",is:!0,t:8,pi:[{n:"value",pt:$n[0].Char,ps:0}],sn:"getBytes$1",rt:$n[0].Array.type(System.Byte),p:[$n[0].Char]},{a:2,n:"GetBytes",is:!0,t:8,pi:[{n:"value",pt:$n[0].Double,ps:0}],sn:"getBytes$2",rt:$n[0].Array.type(System.Byte),p:[$n[0].Double]},{a:2,n:"GetBytes",is:!0,t:8,pi:[{n:"value",pt:$n[0].Int16,ps:0}],sn:"getBytes$3",rt:$n[0].Array.type(System.Byte),p:[$n[0].Int16]},{a:2,n:"GetBytes",is:!0,t:8,pi:[{n:"value",pt:$n[0].Int32,ps:0}],sn:"getBytes$4",rt:$n[0].Array.type(System.Byte),p:[$n[0].Int32]},{a:2,n:"GetBytes",is:!0,t:8,pi:[{n:"value",pt:$n[0].Int64,ps:0}],sn:"getBytes$5",rt:$n[0].Array.type(System.Byte),p:[$n[0].Int64]},{a:2,n:"GetBytes",is:!0,t:8,pi:[{n:"value",pt:$n[0].Single,ps:0}],sn:"getBytes$6",rt:$n[0].Array.type(System.Byte),p:[$n[0].Single]},{a:2,n:"GetBytes",is:!0,t:8,pi:[{n:"value",pt:$n[0].UInt16,ps:0}],sn:"getBytes$7",rt:$n[0].Array.type(System.Byte),p:[$n[0].UInt16]},{a:2,n:"GetBytes",is:!0,t:8,pi:[{n:"value",pt:$n[0].UInt32,ps:0}],sn:"getBytes$8",rt:$n[0].Array.type(System.Byte),p:[$n[0].UInt32]},{a:2,n:"GetBytes",is:!0,t:8,pi:[{n:"value",pt:$n[0].UInt64,ps:0}],sn:"getBytes$9",rt:$n[0].Array.type(System.Byte),p:[$n[0].UInt64]},{a:1,n:"GetHexValue",is:!0,t:8,pi:[{n:"i",pt:$n[0].Int32,ps:0}],sn:"getHexValue",rt:$n[0].Char,p:[$n[0].Int32],box:function($v){return H5.box($v,System.Char,String.fromCharCode,System.Char.getHashCode)}},{a:1,n:"GetIsLittleEndian",is:!0,t:8,sn:"getIsLittleEndian",rt:$n[0].Boolean,box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"GetLongHigh",is:!0,t:8,pi:[{n:"value",pt:$n[0].Int64,ps:0}],tpc:0,def:function(value){return value.value.high},rt:$n[0].Int32,p:[$n[0].Int64],box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"GetLongLow",is:!0,t:8,pi:[{n:"value",pt:$n[0].Int64,ps:0}],tpc:0,def:function(value){return value.value.low},rt:$n[0].Int32,p:[$n[0].Int64],box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"GetView",is:!0,t:8,pi:[{n:"value",pt:$n[0].Int64,ps:0}],sn:"getView",rt:$n[0].Object,p:[$n[0].Int64]},{a:1,n:"GetViewBytes",is:!0,t:8,pi:[{n:"view",pt:$n[0].Object,ps:0},{n:"count",dv:-1,o:!0,pt:$n[0].Int32,ps:1},{n:"startIndex",dv:0,o:!0,pt:$n[0].Int32,ps:2}],sn:"getViewBytes",rt:$n[0].Array.type(System.Byte),p:[$n[0].Object,$n[0].Int32,$n[0].Int32]},{a:2,n:"Int32BitsToSingle",is:!0,t:8,pi:[{n:"value",pt:$n[0].Int32,ps:0}],sn:"int32BitsToSingle",rt:$n[0].Single,p:[$n[0].Int32],box:function($v){return H5.box($v,System.Single,System.Single.format,System.Single.getHashCode)}},{a:2,n:"Int64BitsToDouble",is:!0,t:8,pi:[{n:"value",pt:$n[0].Int64,ps:0}],sn:"int64BitsToDouble",rt:$n[0].Double,p:[$n[0].Int64],box:function($v){return H5.box($v,System.Double,System.Double.format,System.Double.getHashCode)}},{a:1,n:"SetViewBytes",is:!0,t:8,pi:[{n:"view",pt:$n[0].Object,ps:0},{n:"value",pt:$n[0].Array.type(System.Byte),ps:1},{n:"count",dv:-1,o:!0,pt:$n[0].Int32,ps:2},{n:"startIndex",dv:0,o:!0,pt:$n[0].Int32,ps:3}],sn:"setViewBytes",rt:$n[0].Void,p:[$n[0].Object,$n[0].Array.type(System.Byte),$n[0].Int32,$n[0].Int32]},{a:2,n:"SingleToInt32Bits",is:!0,t:8,pi:[{n:"value",pt:$n[0].Single,ps:0}],sn:"singleToInt32Bits",rt:$n[0].Int32,p:[$n[0].Single],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"ToBoolean",is:!0,t:8,pi:[{n:"value",pt:$n[0].Array.type(System.Byte),ps:0},{n:"startIndex",pt:$n[0].Int32,ps:1}],sn:"toBoolean",rt:$n[0].Boolean,p:[$n[0].Array.type(System.Byte),$n[0].Int32],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"ToChar",is:!0,t:8,pi:[{n:"value",pt:$n[0].Array.type(System.Byte),ps:0},{n:"startIndex",pt:$n[0].Int32,ps:1}],sn:"toChar",rt:$n[0].Char,p:[$n[0].Array.type(System.Byte),$n[0].Int32],box:function($v){return H5.box($v,System.Char,String.fromCharCode,System.Char.getHashCode)}},{a:2,n:"ToDouble",is:!0,t:8,pi:[{n:"value",pt:$n[0].Array.type(System.Byte),ps:0},{n:"startIndex",pt:$n[0].Int32,ps:1}],sn:"toDouble",rt:$n[0].Double,p:[$n[0].Array.type(System.Byte),$n[0].Int32],box:function($v){return H5.box($v,System.Double,System.Double.format,System.Double.getHashCode)}},{a:2,n:"ToInt16",is:!0,t:8,pi:[{n:"value",pt:$n[0].Array.type(System.Byte),ps:0},{n:"startIndex",pt:$n[0].Int32,ps:1}],sn:"toInt16",rt:$n[0].Int16,p:[$n[0].Array.type(System.Byte),$n[0].Int32],box:function($v){return H5.box($v,System.Int16)}},{a:2,n:"ToInt32",is:!0,t:8,pi:[{n:"value",pt:$n[0].Array.type(System.Byte),ps:0},{n:"startIndex",pt:$n[0].Int32,ps:1}],sn:"toInt32",rt:$n[0].Int32,p:[$n[0].Array.type(System.Byte),$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"ToInt64",is:!0,t:8,pi:[{n:"value",pt:$n[0].Array.type(System.Byte),ps:0},{n:"startIndex",pt:$n[0].Int32,ps:1}],sn:"toInt64",rt:$n[0].Int64,p:[$n[0].Array.type(System.Byte),$n[0].Int32]},{a:2,n:"ToSingle",is:!0,t:8,pi:[{n:"value",pt:$n[0].Array.type(System.Byte),ps:0},{n:"startIndex",pt:$n[0].Int32,ps:1}],sn:"toSingle",rt:$n[0].Single,p:[$n[0].Array.type(System.Byte),$n[0].Int32],box:function($v){return H5.box($v,System.Single,System.Single.format,System.Single.getHashCode)}},{a:2,n:"ToString",is:!0,t:8,pi:[{n:"value",pt:$n[0].Array.type(System.Byte),ps:0}],sn:"toString",rt:$n[0].String,p:[$n[0].Array.type(System.Byte)]},{a:2,n:"ToString",is:!0,t:8,pi:[{n:"value",pt:$n[0].Array.type(System.Byte),ps:0},{n:"startIndex",pt:$n[0].Int32,ps:1}],sn:"toString$1",rt:$n[0].String,p:[$n[0].Array.type(System.Byte),$n[0].Int32]},{a:2,n:"ToString",is:!0,t:8,pi:[{n:"value",pt:$n[0].Array.type(System.Byte),ps:0},{n:"startIndex",pt:$n[0].Int32,ps:1},{n:"length",pt:$n[0].Int32,ps:2}],sn:"toString$2",rt:$n[0].String,p:[$n[0].Array.type(System.Byte),$n[0].Int32,$n[0].Int32]},{a:2,n:"ToUInt16",is:!0,t:8,pi:[{n:"value",pt:$n[0].Array.type(System.Byte),ps:0},{n:"startIndex",pt:$n[0].Int32,ps:1}],sn:"toUInt16",rt:$n[0].UInt16,p:[$n[0].Array.type(System.Byte),$n[0].Int32],box:function($v){return H5.box($v,System.UInt16)}},{a:2,n:"ToUInt32",is:!0,t:8,pi:[{n:"value",pt:$n[0].Array.type(System.Byte),ps:0},{n:"startIndex",pt:$n[0].Int32,ps:1}],sn:"toUInt32",rt:$n[0].UInt32,p:[$n[0].Array.type(System.Byte),$n[0].Int32],box:function($v){return H5.box($v,System.UInt32)}},{a:2,n:"ToUInt64",is:!0,t:8,pi:[{n:"value",pt:$n[0].Array.type(System.Byte),ps:0},{n:"startIndex",pt:$n[0].Int32,ps:1}],sn:"toUInt64",rt:$n[0].UInt64,p:[$n[0].Array.type(System.Byte),$n[0].Int32]},{a:1,n:"View",is:!0,t:8,pi:[{n:"length",pt:$n[0].Int32,ps:0}],sn:"view",rt:$n[0].Object,p:[$n[0].Int32]},{a:1,n:"Arg_ArrayPlusOffTooSmall",is:!0,t:4,rt:$n[0].String,sn:"arg_ArrayPlusOffTooSmall"},{a:2,n:"IsLittleEndian",is:!0,t:4,rt:$n[0].Boolean,sn:"isLittleEndian",ro:!0,box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}}]}},$n);$m("System.Boolean",function(){return{att:1048841,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:1,n:".ctor",t:1,p:[System.Object],pi:[{n:"_",pt:System.Object,ps:0}],def:function(_){return!1}},{a:2,n:"CompareTo",t:8,pi:[{n:"other",pt:$n[0].Boolean,ps:0}],tpc:0,def:function(other){return H5.compare(this,other)},rt:$n[0].Int32,p:[$n[0].Boolean],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"CompareTo",t:8,pi:[{n:"obj",pt:$n[0].Object,ps:0}],tpc:0,def:function(obj){return H5.compare(this,other)},rt:$n[0].Int32,p:[$n[0].Object],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"Equals",t:8,pi:[{n:"other",pt:$n[0].Boolean,ps:0}],tpc:0,def:function(other){return this===other},rt:$n[0].Boolean,p:[$n[0].Boolean],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Parse",is:!0,t:8,pi:[{n:"value",pt:$n[0].String,ps:0}],tpc:0,def:function(value){return System.Boolean.parse(value)},rt:$n[0].Boolean,p:[$n[0].String],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ov:!0,a:2,n:"ToString",t:8,tpc:0,def:function(){return System.Boolean.toString(this)},rt:$n[0].String},{a:2,n:"TryParse",is:!0,t:8,pi:[{n:"value",pt:$n[0].String,ps:0},{n:"result",out:!0,pt:$n[0].Boolean,ps:1}],tpc:0,def:function(value,result){return System.Boolean.tryParse(value,result)},rt:$n[0].Boolean,p:[$n[0].String,$n[0].Boolean],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:4,n:"False",is:!0,t:4,rt:$n[0].Int32,sn:"False",box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"FalseString",is:!0,t:4,rt:$n[0].String,sn:"falseString",ro:!0},{a:4,n:"True",is:!0,t:4,rt:$n[0].Int32,sn:"True",box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"TrueString",is:!0,t:4,rt:$n[0].String,sn:"trueString",ro:!0}]}},$n);$m("System.Byte",function(){return{att:1048841,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,def:function(){return Number}},{a:1,n:".ctor",t:1,p:[$n[0].Int32],pi:[{n:"i",pt:$n[0].Int32,ps:0}],def:function(i){return Number}},{a:2,n:"CompareTo",t:8,pi:[{n:"other",pt:$n[0].Byte,ps:0}],tpc:0,def:function(other){return H5.compare(this,other)},rt:$n[0].Int32,p:[$n[0].Byte],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"CompareTo",t:8,pi:[{n:"obj",pt:$n[0].Object,ps:0}],tpc:0,def:function(obj){return H5.compare(this,obj)},rt:$n[0].Int32,p:[$n[0].Object],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"Equals",t:8,pi:[{n:"other",pt:$n[0].Byte,ps:0}],tpc:0,def:function(other){return this===other},rt:$n[0].Boolean,p:[$n[0].Byte],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ov:!0,a:2,n:"Equals",t:8,pi:[{n:"other",pt:$n[0].Object,ps:0}],tpc:0,def:function(other){return System.Byte.equals(this,other)},rt:$n[0].Boolean,p:[$n[0].Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Format",t:8,pi:[{n:"format",pt:$n[0].String,ps:0}],tpc:0,def:function(format){return System.Byte.format(this,format)},rt:$n[0].String,p:[$n[0].String]},{a:2,n:"Format",t:8,pi:[{n:"format",pt:$n[0].String,ps:0},{n:"provider",pt:$n[0].IFormatProvider,ps:1}],tpc:0,def:function(format,provider){return System.Byte.format(this,format,provider)},rt:$n[0].String,p:[$n[0].String,$n[0].IFormatProvider]},{a:2,n:"Parse",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0}],tpc:0,def:function(s){return System.Byte.parse(s)},rt:$n[0].Byte,p:[$n[0].String],box:function($v){return H5.box($v,System.Byte)}},{a:2,n:"Parse",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0},{n:"radix",pt:$n[0].Int32,ps:1}],tpc:0,def:function(s,radix){return System.Byte.parse(s,radix)},rt:$n[0].Byte,p:[$n[0].String,$n[0].Int32],box:function($v){return H5.box($v,System.Byte)}},{a:2,n:"ToString",t:8,pi:[{n:"radix",pt:$n[0].Int32,ps:0}],sn:"toString",rt:$n[0].String,p:[$n[0].Int32]},{a:2,n:"ToString",t:8,pi:[{n:"format",pt:$n[0].String,ps:0}],tpc:0,def:function(format){return System.Byte.format(this,format)},rt:$n[0].String,p:[$n[0].String]},{a:2,n:"ToString",t:8,pi:[{n:"format",pt:$n[0].String,ps:0},{n:"provider",pt:$n[0].IFormatProvider,ps:1}],tpc:0,def:function(format,provider){return System.Byte.format(this,format,provider)},rt:$n[0].String,p:[$n[0].String,$n[0].IFormatProvider]},{a:2,n:"TryParse",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0},{n:"result",out:!0,pt:$n[0].Byte,ps:1}],tpc:0,def:function(s,result){return System.Byte.tryParse(s,result)},rt:$n[0].Boolean,p:[$n[0].String,$n[0].Byte],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"TryParse",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0},{n:"result",out:!0,pt:$n[0].Byte,ps:1},{n:"radix",pt:$n[0].Int32,ps:2}],tpc:0,def:function(s,result,radix){return System.Byte.tryParse(s,result,radix)},rt:$n[0].Boolean,p:[$n[0].String,$n[0].Byte,$n[0].Int32],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"MaxValue",is:!0,t:4,rt:$n[0].Byte,sn:"MaxValue",box:function($v){return H5.box($v,System.Byte)}},{a:2,n:"MinValue",is:!0,t:4,rt:$n[0].Byte,sn:"MinValue",box:function($v){return H5.box($v,System.Byte)}}]}},$n);$m("System.Char",function(){return{att:1048841,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,def:function(){return Number}},{a:1,n:".ctor",t:1,p:[$n[0].Int32],pi:[{n:"i",pt:$n[0].Int32,ps:0}],def:function(i){return Number}},{a:2,n:"CompareTo",t:8,pi:[{n:"value",pt:$n[0].Char,ps:0}],tpc:0,def:function(value){return H5.compare(this,value)},rt:$n[0].Int32,p:[$n[0].Char],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"CompareTo",t:8,pi:[{n:"value",pt:$n[0].Object,ps:0}],tpc:0,def:function(value){return H5.compare(this,value)},rt:$n[0].Int32,p:[$n[0].Object],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"Equals",t:8,pi:[{n:"obj",pt:$n[0].Char,ps:0}],tpc:0,def:function(obj){return this===obj},rt:$n[0].Boolean,p:[$n[0].Char],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ov:!0,a:2,n:"Equals",t:8,pi:[{n:"obj",pt:$n[0].Object,ps:0}],tpc:0,def:function(obj){return System.Char.equals(this,obj)},rt:$n[0].Boolean,p:[$n[0].Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Format",t:8,pi:[{n:"format",pt:$n[0].String,ps:0}],tpc:0,def:function(format){return System.Char.format(this,format)},rt:$n[0].String,p:[$n[0].String]},{a:2,n:"Format",t:8,pi:[{n:"format",pt:$n[0].String,ps:0},{n:"provider",pt:$n[0].IFormatProvider,ps:1}],tpc:0,def:function(format,provider){return System.Char.format(this,format,provider)},rt:$n[0].String,p:[$n[0].String,$n[0].IFormatProvider]},{ov:!0,a:2,n:"GetHashCode",t:8,tpc:0,def:function(){return System.Char.getHashCode(this)},rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"IsControl",is:!0,t:8,pi:[{n:"c",pt:$n[0].Char,ps:0}],sn:"isControl",rt:$n[0].Boolean,p:[$n[0].Char],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"IsControl",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0},{n:"index",pt:$n[0].Int32,ps:1}],tpc:0,def:function(s,index){return System.Char.isControl(s.charCodeAt(index))},rt:$n[0].Boolean,p:[$n[0].String,$n[0].Int32],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"IsDigit",is:!0,t:8,pi:[{n:"c",pt:$n[0].Char,ps:0}],sn:"isDigit",rt:$n[0].Boolean,p:[$n[0].Char],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"IsDigit",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0},{n:"index",pt:$n[0].Int32,ps:1}],tpc:0,def:function(s,index){return System.Char.isDigit(s.charCodeAt(index))},rt:$n[0].Boolean,p:[$n[0].String,$n[0].Int32],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"IsHighSurrogate",is:!0,t:8,pi:[{n:"c",pt:$n[0].Char,ps:0}],sn:"isHighSurrogate",rt:$n[0].Boolean,p:[$n[0].Char],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"IsHighSurrogate",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0},{n:"index",pt:$n[0].Int32,ps:1}],tpc:0,def:function(s,index){return System.Char.isHighSurrogate(s.charCodeAt(index))},rt:$n[0].Boolean,p:[$n[0].String,$n[0].Int32],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"IsLetter",is:!0,t:8,pi:[{n:"c",pt:$n[0].Char,ps:0}],sn:"isLetter",rt:$n[0].Boolean,p:[$n[0].Char],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"IsLetter",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0},{n:"index",pt:$n[0].Int32,ps:1}],tpc:0,def:function(s,index){return System.Char.isLetter(s.charCodeAt(index))},rt:$n[0].Boolean,p:[$n[0].String,$n[0].Int32],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"IsLetterOrDigit",is:!0,t:8,pi:[{n:"c",pt:$n[0].Char,ps:0}],tpc:0,def:function(c){return System.Char.isDigit(c)||System.Char.isLetter(c)},rt:$n[0].Boolean,p:[$n[0].Char],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"IsLetterOrDigit",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0},{n:"index",pt:$n[0].Int32,ps:1}],tpc:0,def:function(s,index){return System.Char.isDigit(s.charCodeAt(index))||System.Char.isLetter(s.charCodeAt(index))},rt:$n[0].Boolean,p:[$n[0].String,$n[0].Int32],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"IsLowSurrogate",is:!0,t:8,pi:[{n:"c",pt:$n[0].Char,ps:0}],sn:"isLowSurrogate",rt:$n[0].Boolean,p:[$n[0].Char],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"IsLowSurrogate",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0},{n:"index",pt:$n[0].Int32,ps:1}],tpc:0,def:function(s,index){return System.Char.isLowSurrogate(s.charCodeAt(index))},rt:$n[0].Boolean,p:[$n[0].String,$n[0].Int32],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"IsLower",is:!0,t:8,pi:[{n:"s",pt:$n[0].Char,ps:0}],tpc:0,def:function(s){return H5.isLower(s)},rt:$n[0].Boolean,p:[$n[0].Char],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"IsNumber",is:!0,t:8,pi:[{n:"c",pt:$n[0].Char,ps:0}],sn:"isNumber",rt:$n[0].Boolean,p:[$n[0].Char],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"IsNumber",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0},{n:"index",pt:$n[0].Int32,ps:1}],tpc:0,def:function(s,index){return System.Char.isNumber(s.charCodeAt(index))},rt:$n[0].Boolean,p:[$n[0].String,$n[0].Int32],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"IsPunctuation",is:!0,t:8,pi:[{n:"c",pt:$n[0].Char,ps:0}],sn:"isPunctuation",rt:$n[0].Boolean,p:[$n[0].Char],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"IsPunctuation",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0},{n:"index",pt:$n[0].Int32,ps:1}],tpc:0,def:function(s,index){return System.Char.isPunctuation(s.charCodeAt(index))},rt:$n[0].Boolean,p:[$n[0].String,$n[0].Int32],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"IsSeparator",is:!0,t:8,pi:[{n:"c",pt:$n[0].Char,ps:0}],sn:"isSeparator",rt:$n[0].Boolean,p:[$n[0].Char],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"IsSeparator",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0},{n:"index",pt:$n[0].Int32,ps:1}],tpc:0,def:function(s,index){return System.Char.isSeparator(s.charCodeAt(index))},rt:$n[0].Boolean,p:[$n[0].String,$n[0].Int32],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"IsSurrogate",is:!0,t:8,pi:[{n:"c",pt:$n[0].Char,ps:0}],sn:"isSurrogate",rt:$n[0].Boolean,p:[$n[0].Char],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"IsSurrogate",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0},{n:"index",pt:$n[0].Int32,ps:1}],tpc:0,def:function(s,index){return System.Char.isSurrogate(s.charCodeAt(index))},rt:$n[0].Boolean,p:[$n[0].String,$n[0].Int32],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"IsSurrogatePair",is:!0,t:8,pi:[{n:"highSurrogate",pt:$n[0].Char,ps:0},{n:"lowSurrogate",pt:$n[0].Char,ps:1}],tpc:0,def:function(highSurrogate,lowSurrogate){return System.Char.isHighSurrogate(highSurrogate)&&System.Char.isLowSurrogate(lowSurrogate)},rt:$n[0].Boolean,p:[$n[0].Char,$n[0].Char],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"IsSurrogatePair",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0},{n:"index",pt:$n[0].Int32,ps:1}],tpc:0,def:function(s,index){return System.Char.isHighSurrogate(s.charCodeAt(index))&&System.Char.isLowSurrogate(s.charCodeAt(index+1))},rt:$n[0].Boolean,p:[$n[0].String,$n[0].Int32],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"IsSymbol",is:!0,t:8,pi:[{n:"c",pt:$n[0].Char,ps:0}],sn:"isSymbol",rt:$n[0].Boolean,p:[$n[0].Char],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"IsSymbol",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0},{n:"index",pt:$n[0].Int32,ps:1}],tpc:0,def:function(s,index){return System.Char.isSymbol(s.charCodeAt(index))},rt:$n[0].Boolean,p:[$n[0].String,$n[0].Int32],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"IsUpper",is:!0,t:8,pi:[{n:"s",pt:$n[0].Char,ps:0}],tpc:0,def:function(s){return H5.isUpper(s)},rt:$n[0].Boolean,p:[$n[0].Char],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"IsUpper",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0},{n:"index",pt:$n[0].Int32,ps:1}],sn:"isUpper",rt:$n[0].Boolean,p:[$n[0].String,$n[0].Int32],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"IsWhiteSpace",is:!0,t:8,pi:[{n:"c",pt:$n[0].Char,ps:0}],tpc:0,def:function(c){return System.Char.isWhiteSpace(String.fromCharCode(c))},rt:$n[0].Boolean,p:[$n[0].Char],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"IsWhiteSpace",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0},{n:"index",pt:$n[0].Int32,ps:1}],tpc:0,def:function(s,index){return System.Char.isWhiteSpace(s.charAt(index))},rt:$n[0].Boolean,p:[$n[0].String,$n[0].Int32],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Parse",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0}],tpc:0,def:function(s){return System.Char.charCodeAt(s,0)},rt:$n[0].Char,p:[$n[0].String],box:function($v){return H5.box($v,System.Char,String.fromCharCode,System.Char.getHashCode)}},{a:2,n:"ToLower",is:!0,t:8,pi:[{n:"c",pt:$n[0].Char,ps:0}],tpc:0,def:function(c){return String.fromCharCode(c).toLowerCase().charCodeAt(0)},rt:$n[0].Char,p:[$n[0].Char],box:function($v){return H5.box($v,System.Char,String.fromCharCode,System.Char.getHashCode)}},{ov:!0,a:2,n:"ToString",t:8,tpc:0,def:function(){return String.fromCharCode(this)},rt:$n[0].String},{a:2,n:"ToString",is:!0,t:8,pi:[{n:"c",pt:$n[0].Char,ps:0}],tpc:0,def:function(c){return String.fromCharCode(c)},rt:$n[0].String,p:[$n[0].Char]},{a:2,n:"ToString",t:8,pi:[{n:"format",pt:$n[0].String,ps:0}],tpc:0,def:function(format){return System.Char.format(this,format)},rt:$n[0].String,p:[$n[0].String]},{a:2,n:"ToString",t:8,pi:[{n:"format",pt:$n[0].String,ps:0},{n:"provider",pt:$n[0].IFormatProvider,ps:1}],tpc:0,def:function(format,provider){return System.Char.format(this,format,provider)},rt:$n[0].String,p:[$n[0].String,$n[0].IFormatProvider]},{a:2,n:"ToUpper",is:!0,t:8,pi:[{n:"c",pt:$n[0].Char,ps:0}],tpc:0,def:function(c){return String.fromCharCode(c).toUpperCase().charCodeAt(0)},rt:$n[0].Char,p:[$n[0].Char],box:function($v){return H5.box($v,System.Char,String.fromCharCode,System.Char.getHashCode)}},{a:2,n:"MaxValue",is:!0,t:4,rt:$n[0].Char,sn:"MaxValue",box:function($v){return H5.box($v,System.Char,String.fromCharCode,System.Char.getHashCode)}},{a:2,n:"MinValue",is:!0,t:4,rt:$n[0].Char,sn:"MinValue",box:function($v){return H5.box($v,System.Char,String.fromCharCode,System.Char.getHashCode)}}]}},$n);$m("System.Console",function(){return{att:1048833,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:"Clear",is:!0,t:8,sn:"Clear",rt:$n[0].Void},{a:2,n:"Log",is:!0,t:8,pi:[{n:"value",pt:$n[0].Object,ps:0}],sn:"Log",rt:$n[0].Void,p:[$n[0].Object]},{a:2,n:"Read",is:!0,t:8,tpc:0,def:function(){return prompt()},rt:$n[0].String},{a:2,n:"ReadLine",is:!0,t:8,tpc:0,def:function(){return prompt()},rt:$n[0].String},{a:2,n:"ReadLine",is:!0,t:8,pi:[{n:"text",pt:$n[0].String,ps:0}],tpc:0,def:function(text){return prompt(text)},rt:$n[0].String,p:[$n[0].String]},{a:2,n:"ReadLine",is:!0,t:8,pi:[{n:"text",pt:$n[0].String,ps:0},{n:"value",pt:$n[0].String,ps:1}],tpc:0,def:function(text,value){return prompt(text,value)},rt:$n[0].String,p:[$n[0].String,$n[0].String]},{a:1,n:"TransformChars",is:!0,t:8,pi:[{n:"buffer",pt:$n[0].Array.type(System.Char),ps:0},{n:"all",pt:$n[0].Int32,ps:1},{n:"index",pt:$n[0].Int32,ps:2},{n:"count",pt:$n[0].Int32,ps:3}],sn:"TransformChars",rt:$n[0].String,p:[$n[0].Array.type(System.Char),$n[0].Int32,$n[0].Int32,$n[0].Int32]},{a:2,n:"Write",is:!0,t:8,pi:[{n:"value",pt:$n[0].Boolean,ps:0}],tpc:0,def:function(value){return System.Console.Write(System.Boolean.toString(value))},rt:$n[0].Void,p:[$n[0].Boolean]},{a:2,n:"Write",is:!0,t:8,pi:[{n:"value",pt:$n[0].Char,ps:0}],tpc:0,def:function(value){return System.Console.Write(String.fromCharCode(value))},rt:$n[0].Void,p:[$n[0].Char]},{a:2,n:"Write",is:!0,t:8,pi:[{n:"buffer",pt:$n[0].Array.type(System.Char),ps:0}],tpc:0,def:function(buffer){return System.Console.Write(System.Console.TransformChars(buffer,1))},rt:$n[0].Void,p:[$n[0].Array.type(System.Char)]},{a:2,n:"Write",is:!0,t:8,pi:[{n:"value",pt:$n[0].DateTime,ps:0}],sn:"write",rt:$n[0].Void,p:[$n[0].DateTime]},{a:2,n:"Write",is:!0,t:8,pi:[{n:"value",pt:$n[0].DateTimeOffset,ps:0}],sn:"write$1",rt:$n[0].Void,p:[$n[0].DateTimeOffset]},{a:2,n:"Write",is:!0,t:8,pi:[{n:"value",pt:$n[0].Decimal,ps:0}],tpc:0,def:function(value){return System.Console.Write(value.toString("G"))},rt:$n[0].Void,p:[$n[0].Decimal]},{a:2,n:"Write",is:!0,t:8,pi:[{n:"value",pt:$n[0].Double,ps:0}],tpc:0,def:function(value){return System.Console.Write(System.Double.format(value))},rt:$n[0].Void,p:[$n[0].Double]},{a:2,n:"Write",is:!0,t:8,pi:[{n:"value",pt:$n[0].Int32,ps:0}],sn:"Write",rt:$n[0].Void,p:[$n[0].Int32]},{a:2,n:"Write",is:!0,t:8,pi:[{n:"value",pt:$n[0].Int64,ps:0}],sn:"Write",rt:$n[0].Void,p:[$n[0].Int64]},{a:2,n:"Write",is:!0,t:8,pi:[{n:"value",pt:$n[0].Object,ps:0}],sn:"Write",rt:$n[0].Void,p:[$n[0].Object]},{a:2,n:"Write",is:!0,t:8,pi:[{n:"value",pt:$n[0].Single,ps:0}],sn:"Write",rt:$n[0].Void,p:[$n[0].Single]},{a:2,n:"Write",is:!0,t:8,pi:[{n:"value",pt:$n[0].String,ps:0}],sn:"Write",rt:$n[0].Void,p:[$n[0].String]},{a:2,n:"Write",is:!0,t:8,pi:[{n:"value",pt:$n[0].UInt32,ps:0}],sn:"Write",rt:$n[0].Void,p:[$n[0].UInt32]},{a:2,n:"Write",is:!0,t:8,pi:[{n:"value",pt:$n[0].UInt64,ps:0}],sn:"Write",rt:$n[0].Void,p:[$n[0].UInt64]},{a:2,n:"Write",is:!0,t:8,pi:[{n:"format",pt:$n[0].String,ps:0},{n:"arg0",pt:$n[0].Object,ps:1}],tpc:0,def:function(format,arg0){return System.Console.Write(System.String.format(format,arg0))},rt:$n[0].Void,p:[$n[0].String,$n[0].Object]},{a:2,n:"Write",is:!0,t:8,pi:[{n:"format",pt:$n[0].String,ps:0},{n:"arg",ip:!0,pt:$n[0].Array.type(System.Object),ps:1}],tpc:0,def:function(format,arg){return System.Console.Write(System.String.format(format,arg))},rt:$n[0].Void,p:[$n[0].String,$n[0].Array.type(System.Object)]},{a:2,n:"Write",is:!0,t:8,pi:[{n:"buffer",pt:$n[0].Array.type(System.Char),ps:0},{n:"index",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2}],tpc:0,def:function(buffer,index,count){return System.Console.Write(System.Console.TransformChars(buffer,0,index,count))},rt:$n[0].Void,p:[$n[0].Array.type(System.Char),$n[0].Int32,$n[0].Int32]},{a:2,n:"Write",is:!0,t:8,pi:[{n:"format",pt:$n[0].String,ps:0},{n:"arg0",pt:$n[0].Object,ps:1},{n:"arg1",pt:$n[0].Object,ps:2}],tpc:0,def:function(format,arg0,arg1){return System.Console.Write(System.String.format(format,arg0,arg1))},rt:$n[0].Void,p:[$n[0].String,$n[0].Object,$n[0].Object]},{a:2,n:"Write",is:!0,t:8,pi:[{n:"format",pt:$n[0].String,ps:0},{n:"arg0",pt:$n[0].Object,ps:1},{n:"arg1",pt:$n[0].Object,ps:2},{n:"arg2",pt:$n[0].Object,ps:3}],tpc:0,def:function(format,arg0,arg1,arg2){return System.Console.Write(System.String.format(format,arg0,arg1,arg2))},rt:$n[0].Void,p:[$n[0].String,$n[0].Object,$n[0].Object,$n[0].Object]},{a:2,n:"Write",is:!0,t:8,pi:[{n:"format",pt:$n[0].String,ps:0},{n:"arg0",pt:$n[0].Object,ps:1},{n:"arg1",pt:$n[0].Object,ps:2},{n:"arg2",pt:$n[0].Object,ps:3},{n:"arg3",pt:$n[0].Object,ps:4}],tpc:0,def:function(format,arg0,arg1,arg2,arg3){return System.Console.Write(System.String.format(format,[arg0,arg1,arg2,arg3]))},rt:$n[0].Void,p:[$n[0].String,$n[0].Object,$n[0].Object,$n[0].Object,$n[0].Object]},{a:2,n:"WriteLine",is:!0,t:8,sn:"WriteLine",rt:$n[0].Void},{a:2,n:"WriteLine",is:!0,t:8,pi:[{n:"value",pt:$n[0].Boolean,ps:0}],tpc:0,def:function(value){return System.Console.WriteLine(System.Boolean.toString(value))},rt:$n[0].Void,p:[$n[0].Boolean]},{a:2,n:"WriteLine",is:!0,t:8,pi:[{n:"value",pt:$n[0].Char,ps:0}],tpc:0,def:function(value){return System.Console.WriteLine(String.fromCharCode(value))},rt:$n[0].Void,p:[$n[0].Char]},{a:2,n:"WriteLine",is:!0,t:8,pi:[{n:"buffer",pt:$n[0].Array.type(System.Char),ps:0}],tpc:0,def:function(buffer){return System.Console.WriteLine(System.Console.TransformChars(buffer,1))},rt:$n[0].Void,p:[$n[0].Array.type(System.Char)]},{a:2,n:"WriteLine",is:!0,t:8,pi:[{n:"value",pt:$n[0].DateTime,ps:0}],sn:"writeLine",rt:$n[0].Void,p:[$n[0].DateTime]},{a:2,n:"WriteLine",is:!0,t:8,pi:[{n:"value",pt:$n[0].DateTimeOffset,ps:0}],sn:"writeLine$1",rt:$n[0].Void,p:[$n[0].DateTimeOffset]},{a:2,n:"WriteLine",is:!0,t:8,pi:[{n:"value",pt:$n[0].Decimal,ps:0}],tpc:0,def:function(value){return System.Console.WriteLine(value.toString("G"))},rt:$n[0].Void,p:[$n[0].Decimal]},{a:2,n:"WriteLine",is:!0,t:8,pi:[{n:"value",pt:$n[0].Double,ps:0}],tpc:0,def:function(value){return System.Console.WriteLine(System.Double.format(value))},rt:$n[0].Void,p:[$n[0].Double]},{a:2,n:"WriteLine",is:!0,t:8,pi:[{n:"value",pt:$n[0].Int32,ps:0}],sn:"WriteLine",rt:$n[0].Void,p:[$n[0].Int32]},{a:2,n:"WriteLine",is:!0,t:8,pi:[{n:"value",pt:$n[0].Int64,ps:0}],tpc:0,def:function(value){return System.Console.WriteLine(value.toString())},rt:$n[0].Void,p:[$n[0].Int64]},{a:2,n:"WriteLine",is:!0,t:8,pi:[{n:"value",pt:$n[0].Nullable$1(System.Decimal),ps:0}],tpc:0,def:function(value){return System.Console.WriteLine(value&&value.toString("G"))},rt:$n[0].Void,p:[$n[0].Nullable$1(System.Decimal)]},{a:2,n:"WriteLine",is:!0,t:8,pi:[{n:"value",pt:$n[0].Object,ps:0}],sn:"WriteLine",rt:$n[0].Void,p:[$n[0].Object]},{a:2,n:"WriteLine",is:!0,t:8,pi:[{n:"value",pt:$n[0].Single,ps:0}],tpc:0,def:function(value){return System.Console.WriteLine(System.Single.format(value))},rt:$n[0].Void,p:[$n[0].Single]},{a:2,n:"WriteLine",is:!0,t:8,pi:[{n:"value",pt:$n[0].String,ps:0}],sn:"WriteLine",rt:$n[0].Void,p:[$n[0].String]},{a:2,n:"WriteLine",is:!0,t:8,pi:[{n:"value",pt:$n[0].Type,ps:0}],tpc:0,def:function(value){return System.Console.WriteLine(H5.getTypeName(value))},rt:$n[0].Void,p:[$n[0].Type]},{a:2,n:"WriteLine",is:!0,t:8,pi:[{n:"value",pt:$n[0].UInt32,ps:0}],sn:"WriteLine",rt:$n[0].Void,p:[$n[0].UInt32]},{a:2,n:"WriteLine",is:!0,t:8,pi:[{n:"value",pt:$n[0].UInt64,ps:0}],tpc:0,def:function(value){return System.Console.WriteLine(value.toString())},rt:$n[0].Void,p:[$n[0].UInt64]},{a:2,n:"WriteLine",is:!0,t:8,pi:[{n:"format",pt:$n[0].String,ps:0},{n:"arg0",pt:$n[0].Object,ps:1}],tpc:0,def:function(format,arg0){return System.Console.WriteLine(System.String.format(format,arg0))},rt:$n[0].Void,p:[$n[0].String,$n[0].Object]},{a:2,n:"WriteLine",is:!0,t:8,pi:[{n:"format",pt:$n[0].String,ps:0},{n:"arg",ip:!0,pt:$n[0].Array.type(System.Object),ps:1}],tpc:0,def:function(format,arg){return System.Console.WriteLine(System.String.format(format,arg))},rt:$n[0].Void,p:[$n[0].String,$n[0].Array.type(System.Object)]},{a:2,n:"WriteLine",is:!0,t:8,pi:[{n:"buffer",pt:$n[0].Array.type(System.Char),ps:0},{n:"index",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2}],tpc:0,def:function(buffer,index,count){return System.Console.WriteLine(System.Console.TransformChars(buffer,0,index,count))},rt:$n[0].Void,p:[$n[0].Array.type(System.Char),$n[0].Int32,$n[0].Int32]},{a:2,n:"WriteLine",is:!0,t:8,pi:[{n:"format",pt:$n[0].String,ps:0},{n:"arg0",pt:$n[0].Object,ps:1},{n:"arg1",pt:$n[0].Object,ps:2}],tpc:0,def:function(format,arg0,arg1){return System.Console.WriteLine(System.String.format(format,arg0,arg1))},rt:$n[0].Void,p:[$n[0].String,$n[0].Object,$n[0].Object]},{a:2,n:"WriteLine",is:!0,t:8,pi:[{n:"format",pt:$n[0].String,ps:0},{n:"arg0",pt:$n[0].Object,ps:1},{n:"arg1",pt:$n[0].Object,ps:2},{n:"arg2",pt:$n[0].Object,ps:3}],tpc:0,def:function(format,arg0,arg1,arg2){return System.Console.WriteLine(System.String.format(format,arg0,arg1,arg2))},rt:$n[0].Void,p:[$n[0].String,$n[0].Object,$n[0].Object,$n[0].Object]},{a:2,n:"WriteLine",is:!0,t:8,pi:[{n:"format",pt:$n[0].String,ps:0},{n:"arg0",pt:$n[0].Object,ps:1},{n:"arg1",pt:$n[0].Object,ps:2},{n:"arg2",pt:$n[0].Object,ps:3},{n:"arg3",pt:$n[0].Object,ps:4}],tpc:0,def:function(format,arg0,arg1,arg2,arg3){return System.Console.WriteLine(System.String.format(format,[arg0,arg1,arg2,arg3]))},rt:$n[0].Void,p:[$n[0].String,$n[0].Object,$n[0].Object,$n[0].Object,$n[0].Object]}]}},$n);$m("System.ConsoleColor",function(){return{att:257,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:"Black",is:!0,t:4,rt:$n[0].ConsoleColor,sn:"Black",box:function($v){return H5.box($v,System.ConsoleColor,System.Enum.toStringFn(System.ConsoleColor))}},{a:2,n:"Blue",is:!0,t:4,rt:$n[0].ConsoleColor,sn:"Blue",box:function($v){return H5.box($v,System.ConsoleColor,System.Enum.toStringFn(System.ConsoleColor))}},{a:2,n:"Cyan",is:!0,t:4,rt:$n[0].ConsoleColor,sn:"Cyan",box:function($v){return H5.box($v,System.ConsoleColor,System.Enum.toStringFn(System.ConsoleColor))}},{a:2,n:"DarkBlue",is:!0,t:4,rt:$n[0].ConsoleColor,sn:"DarkBlue",box:function($v){return H5.box($v,System.ConsoleColor,System.Enum.toStringFn(System.ConsoleColor))}},{a:2,n:"DarkCyan",is:!0,t:4,rt:$n[0].ConsoleColor,sn:"DarkCyan",box:function($v){return H5.box($v,System.ConsoleColor,System.Enum.toStringFn(System.ConsoleColor))}},{a:2,n:"DarkGray",is:!0,t:4,rt:$n[0].ConsoleColor,sn:"DarkGray",box:function($v){return H5.box($v,System.ConsoleColor,System.Enum.toStringFn(System.ConsoleColor))}},{a:2,n:"DarkGreen",is:!0,t:4,rt:$n[0].ConsoleColor,sn:"DarkGreen",box:function($v){return H5.box($v,System.ConsoleColor,System.Enum.toStringFn(System.ConsoleColor))}},{a:2,n:"DarkMagenta",is:!0,t:4,rt:$n[0].ConsoleColor,sn:"DarkMagenta",box:function($v){return H5.box($v,System.ConsoleColor,System.Enum.toStringFn(System.ConsoleColor))}},{a:2,n:"DarkRed",is:!0,t:4,rt:$n[0].ConsoleColor,sn:"DarkRed",box:function($v){return H5.box($v,System.ConsoleColor,System.Enum.toStringFn(System.ConsoleColor))}},{a:2,n:"DarkYellow",is:!0,t:4,rt:$n[0].ConsoleColor,sn:"DarkYellow",box:function($v){return H5.box($v,System.ConsoleColor,System.Enum.toStringFn(System.ConsoleColor))}},{a:2,n:"Gray",is:!0,t:4,rt:$n[0].ConsoleColor,sn:"Gray",box:function($v){return H5.box($v,System.ConsoleColor,System.Enum.toStringFn(System.ConsoleColor))}},{a:2,n:"Green",is:!0,t:4,rt:$n[0].ConsoleColor,sn:"Green",box:function($v){return H5.box($v,System.ConsoleColor,System.Enum.toStringFn(System.ConsoleColor))}},{a:2,n:"Magenta",is:!0,t:4,rt:$n[0].ConsoleColor,sn:"Magenta",box:function($v){return H5.box($v,System.ConsoleColor,System.Enum.toStringFn(System.ConsoleColor))}},{a:2,n:"Red",is:!0,t:4,rt:$n[0].ConsoleColor,sn:"Red",box:function($v){return H5.box($v,System.ConsoleColor,System.Enum.toStringFn(System.ConsoleColor))}},{a:2,n:"White",is:!0,t:4,rt:$n[0].ConsoleColor,sn:"White",box:function($v){return H5.box($v,System.ConsoleColor,System.Enum.toStringFn(System.ConsoleColor))}},{a:2,n:"Yellow",is:!0,t:4,rt:$n[0].ConsoleColor,sn:"Yellow",box:function($v){return H5.box($v,System.ConsoleColor,System.Enum.toStringFn(System.ConsoleColor))}}]}},$n);$m("System.DateTime",function(){return{att:1048841,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].Int64],pi:[{n:"ticks",pt:$n[0].Int64,ps:0}],def:function(ticks){return System.DateTime.create$2(ticks)}},{a:1,n:".ctor",t:1,p:[System.Object],pi:[{n:"_",pt:System.Object,ps:0}],def:function(_){return System.DateTime.getDefaultValue()}},{a:2,n:".ctor",t:1,p:[$n[0].Int64,$n[0].DateTimeKind],pi:[{n:"ticks",pt:$n[0].Int64,ps:0},{n:"kind",pt:$n[0].DateTimeKind,ps:1}],def:function(ticks,kind){return System.DateTime.create$2(ticks,kind)}},{a:2,n:".ctor",t:1,p:[$n[0].Int32,$n[0].Int32,$n[0].Int32],pi:[{n:"year",pt:$n[0].Int32,ps:0},{n:"month",pt:$n[0].Int32,ps:1},{n:"day",pt:$n[0].Int32,ps:2}],def:function(year,month,day){return System.DateTime.create(year,month,day)}},{a:2,n:".ctor",t:1,p:[$n[0].Int32,$n[0].Int32,$n[0].Int32,$n[0].Int32,$n[0].Int32,$n[0].Int32],pi:[{n:"year",pt:$n[0].Int32,ps:0},{n:"month",pt:$n[0].Int32,ps:1},{n:"day",pt:$n[0].Int32,ps:2},{n:"hour",pt:$n[0].Int32,ps:3},{n:"minute",pt:$n[0].Int32,ps:4},{n:"second",pt:$n[0].Int32,ps:5}],def:function(year,month,day,hour,minute,second){return System.DateTime.create(year,month,day,hour,minute,second)}},{a:2,n:".ctor",t:1,p:[$n[0].Int32,$n[0].Int32,$n[0].Int32,$n[0].Int32,$n[0].Int32,$n[0].Int32,$n[0].DateTimeKind],pi:[{n:"year",pt:$n[0].Int32,ps:0},{n:"month",pt:$n[0].Int32,ps:1},{n:"day",pt:$n[0].Int32,ps:2},{n:"hour",pt:$n[0].Int32,ps:3},{n:"minute",pt:$n[0].Int32,ps:4},{n:"second",pt:$n[0].Int32,ps:5},{n:"kind",pt:$n[0].DateTimeKind,ps:6}],def:function(year,month,day,hour,minute,second,kind){return System.DateTime.create(year,month,day,hour,minute,second,0,kind)}},{a:2,n:".ctor",t:1,p:[$n[0].Int32,$n[0].Int32,$n[0].Int32,$n[0].Int32,$n[0].Int32,$n[0].Int32,$n[0].Int32],pi:[{n:"year",pt:$n[0].Int32,ps:0},{n:"month",pt:$n[0].Int32,ps:1},{n:"day",pt:$n[0].Int32,ps:2},{n:"hour",pt:$n[0].Int32,ps:3},{n:"minute",pt:$n[0].Int32,ps:4},{n:"second",pt:$n[0].Int32,ps:5},{n:"millisecond",pt:$n[0].Int32,ps:6}],def:function(year,month,day,hour,minute,second,millisecond){return System.DateTime.create(year,month,day,hour,minute,second,millisecond)}},{a:2,n:".ctor",t:1,p:[$n[0].Int32,$n[0].Int32,$n[0].Int32,$n[0].Int32,$n[0].Int32,$n[0].Int32,$n[0].Int32,$n[0].DateTimeKind],pi:[{n:"year",pt:$n[0].Int32,ps:0},{n:"month",pt:$n[0].Int32,ps:1},{n:"day",pt:$n[0].Int32,ps:2},{n:"hour",pt:$n[0].Int32,ps:3},{n:"minute",pt:$n[0].Int32,ps:4},{n:"second",pt:$n[0].Int32,ps:5},{n:"millisecond",pt:$n[0].Int32,ps:6},{n:"kind",pt:$n[0].DateTimeKind,ps:7}],def:function(year,month,day,hour,minute,second,millisecond,kind){return System.DateTime.create(year,month,day,hour,minute,second,millisecond,kind)}},{a:2,n:"Add",t:8,pi:[{n:"value",pt:$n[0].TimeSpan,ps:0}],tpc:0,def:function(value){return System.DateTime.add(this,value)},rt:$n[0].DateTime,p:[$n[0].TimeSpan],box:function($v){return H5.box($v,System.DateTime,System.DateTime.format)}},{a:2,n:"AddDays",t:8,pi:[{n:"value",pt:$n[0].Double,ps:0}],tpc:0,def:function(value){return System.DateTime.addDays(this,value)},rt:$n[0].DateTime,p:[$n[0].Double],box:function($v){return H5.box($v,System.DateTime,System.DateTime.format)}},{a:2,n:"AddHours",t:8,pi:[{n:"value",pt:$n[0].Double,ps:0}],tpc:0,def:function(value){return System.DateTime.addHours(this,value)},rt:$n[0].DateTime,p:[$n[0].Double],box:function($v){return H5.box($v,System.DateTime,System.DateTime.format)}},{a:2,n:"AddMilliseconds",t:8,pi:[{n:"value",pt:$n[0].Double,ps:0}],tpc:0,def:function(value){return System.DateTime.addMilliseconds(this,value)},rt:$n[0].DateTime,p:[$n[0].Double],box:function($v){return H5.box($v,System.DateTime,System.DateTime.format)}},{a:2,n:"AddMinutes",t:8,pi:[{n:"value",pt:$n[0].Double,ps:0}],tpc:0,def:function(value){return System.DateTime.addMinutes(this,value)},rt:$n[0].DateTime,p:[$n[0].Double],box:function($v){return H5.box($v,System.DateTime,System.DateTime.format)}},{a:2,n:"AddMonths",t:8,pi:[{n:"months",pt:$n[0].Int32,ps:0}],tpc:0,def:function(months){return System.DateTime.addMonths(this,months)},rt:$n[0].DateTime,p:[$n[0].Int32],box:function($v){return H5.box($v,System.DateTime,System.DateTime.format)}},{a:2,n:"AddSeconds",t:8,pi:[{n:"value",pt:$n[0].Double,ps:0}],tpc:0,def:function(value){return System.DateTime.addSeconds(this,value)},rt:$n[0].DateTime,p:[$n[0].Double],box:function($v){return H5.box($v,System.DateTime,System.DateTime.format)}},{a:2,n:"AddTicks",t:8,pi:[{n:"value",pt:$n[0].Int64,ps:0}],tpc:0,def:function(value){return System.DateTime.addTicks(this,value)},rt:$n[0].DateTime,p:[$n[0].Int64],box:function($v){return H5.box($v,System.DateTime,System.DateTime.format)}},{a:2,n:"AddYears",t:8,pi:[{n:"value",pt:$n[0].Int32,ps:0}],tpc:0,def:function(value){return System.DateTime.addYears(this,value)},rt:$n[0].DateTime,p:[$n[0].Int32],box:function($v){return H5.box($v,System.DateTime,System.DateTime.format)}},{a:2,n:"Compare",is:!0,t:8,pi:[{n:"t1",pt:$n[0].DateTime,ps:0},{n:"t2",pt:$n[0].DateTime,ps:1}],tpc:0,def:function(t1,t2){return H5.compare(t1,t2)},rt:$n[0].Int32,p:[$n[0].DateTime,$n[0].DateTime],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"CompareTo",t:8,pi:[{n:"other",pt:$n[0].DateTime,ps:0}],tpc:0,def:function(other){return H5.compare(this,other)},rt:$n[0].Int32,p:[$n[0].DateTime],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"CompareTo",t:8,pi:[{n:"other",pt:$n[0].Object,ps:0}],tpc:0,def:function(other){return H5.compare(this,other)},rt:$n[0].Int32,p:[$n[0].Object],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"DaysInMonth",is:!0,t:8,pi:[{n:"year",pt:$n[0].Int32,ps:0},{n:"month",pt:$n[0].Int32,ps:1}],tpc:0,def:function(year,month){return System.DateTime.getDaysInMonth(year,month)},rt:$n[0].Int32,p:[$n[0].Int32,$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"Equals",t:8,pi:[{n:"other",pt:$n[0].DateTime,ps:0}],tpc:0,def:function(other){return H5.equalsT(this,other)},rt:$n[0].Boolean,p:[$n[0].DateTime],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Equals",is:!0,t:8,pi:[{n:"t1",pt:$n[0].DateTime,ps:0},{n:"t2",pt:$n[0].DateTime,ps:1}],tpc:0,def:function(t1,t2){return H5.equalsT(t1,t2)},rt:$n[0].Boolean,p:[$n[0].DateTime,$n[0].DateTime],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"FromFileTime",is:!0,t:8,pi:[{n:"fileTime",pt:$n[0].Int64,ps:0}],tpc:0,def:function(fileTime){return System.DateTime.FromFileTime(fileTime)},rt:$n[0].DateTime,p:[$n[0].Int64],box:function($v){return H5.box($v,System.DateTime,System.DateTime.format)}},{a:2,n:"FromFileTimeUtc",is:!0,t:8,pi:[{n:"fileTime",pt:$n[0].Int64,ps:0}],tpc:0,def:function(fileTime){return System.DateTime.FromFileTimeUtc(fileTime)},rt:$n[0].DateTime,p:[$n[0].Int64],box:function($v){return H5.box($v,System.DateTime,System.DateTime.format)}},{a:2,n:"IsDaylightSavingTime",t:8,tpc:0,def:function(){return System.DateTime.isDaylightSavingTime(this)},rt:$n[0].Boolean,box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"IsLeapYear",is:!0,t:8,pi:[{n:"year",pt:$n[0].Int32,ps:0}],tpc:0,def:function(year){return System.DateTime.getIsLeapYear(year)},rt:$n[0].Boolean,p:[$n[0].Int32],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Parse",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0}],tpc:0,def:function(s){return System.DateTime.parse(s)},rt:$n[0].DateTime,p:[$n[0].String],box:function($v){return H5.box($v,System.DateTime,System.DateTime.format)}},{a:2,n:"Parse",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0},{n:"provider",pt:$n[0].IFormatProvider,ps:1}],tpc:0,def:function(s,provider){return System.DateTime.parse(s,provider)},rt:$n[0].DateTime,p:[$n[0].String,$n[0].IFormatProvider],box:function($v){return H5.box($v,System.DateTime,System.DateTime.format)}},{a:2,n:"ParseExact",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0},{n:"format",pt:$n[0].String,ps:1},{n:"provider",pt:$n[0].IFormatProvider,ps:2}],tpc:0,def:function(s,format,provider){return System.DateTime.parseExact(s,format,provider)},rt:$n[0].DateTime,p:[$n[0].String,$n[0].String,$n[0].IFormatProvider],box:function($v){return H5.box($v,System.DateTime,System.DateTime.format)}},{a:2,n:"SpecifyKind",is:!0,t:8,pi:[{n:"value",pt:$n[0].DateTime,ps:0},{n:"kind",pt:$n[0].DateTimeKind,ps:1}],tpc:0,def:function(value,kind){return System.DateTime.specifyKind(value,kind)},rt:$n[0].DateTime,p:[$n[0].DateTime,$n[0].DateTimeKind],box:function($v){return H5.box($v,System.DateTime,System.DateTime.format)}},{a:2,n:"Subtract",t:8,pi:[{n:"value",pt:$n[0].DateTime,ps:0}],tpc:0,def:function(value){return System.DateTime.subdd(this,value)},rt:$n[0].TimeSpan,p:[$n[0].DateTime]},{a:2,n:"Subtract",t:8,pi:[{n:"value",pt:$n[0].TimeSpan,ps:0}],tpc:0,def:function(value){return System.DateTime.subtract(this,value)},rt:$n[0].DateTime,p:[$n[0].TimeSpan],box:function($v){return H5.box($v,System.DateTime,System.DateTime.format)}},{a:2,n:"ToFileTime",t:8,tpc:0,def:function(){return System.DateTime.ToFileTime(this)},rt:$n[0].Int64},{a:2,n:"ToFileTimeUtc",t:8,tpc:0,def:function(){return System.DateTime.ToFileTimeUtc(this)},rt:$n[0].Int64},{a:2,n:"ToLocalTime",t:8,tpc:0,def:function(){return System.DateTime.toLocalTime(this)},rt:$n[0].DateTime,box:function($v){return H5.box($v,System.DateTime,System.DateTime.format)}},{a:2,n:"ToLocalTime",t:8,pi:[{n:"throwOnOverflow",pt:$n[0].Boolean,ps:0}],tpc:0,def:function(throwOnOverflow){return System.DateTime.toLocalTime(this,throwOnOverflow)},rt:$n[0].DateTime,p:[$n[0].Boolean],box:function($v){return H5.box($v,System.DateTime,System.DateTime.format)}},{a:2,n:"ToShortDateString",t:8,tpc:0,def:function(){return System.DateTime.format(this,"d")},rt:$n[0].String},{a:2,n:"ToShortTimeString",t:8,tpc:0,def:function(){return System.DateTime.format(this,"t")},rt:$n[0].String},{ov:!0,a:2,n:"ToString",t:8,tpc:0,def:function(){return System.DateTime.format(this)},rt:$n[0].String},{a:2,n:"ToString",t:8,pi:[{n:"format",pt:$n[0].String,ps:0}],tpc:0,def:function(format){return System.DateTime.format(this,format)},rt:$n[0].String,p:[$n[0].String]},{a:2,n:"ToString",t:8,pi:[{n:"format",pt:$n[0].String,ps:0},{n:"provider",pt:$n[0].IFormatProvider,ps:1}],tpc:0,def:function(format,provider){return System.DateTime.format(this,format,provider)},rt:$n[0].String,p:[$n[0].String,$n[0].IFormatProvider]},{a:2,n:"ToUniversalTime",t:8,tpc:0,def:function(){return System.DateTime.toUniversalTime(this)},rt:$n[0].DateTime,box:function($v){return H5.box($v,System.DateTime,System.DateTime.format)}},{a:2,n:"TryParse",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0},{n:"result",out:!0,pt:$n[0].DateTime,ps:1}],tpc:0,def:function(s,result){return System.DateTime.tryParse(s,null,result)},rt:$n[0].Boolean,p:[$n[0].String,$n[0].DateTime],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"TryParseExact",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0},{n:"format",pt:$n[0].String,ps:1},{n:"provider",pt:$n[0].IFormatProvider,ps:2},{n:"result",out:!0,pt:$n[0].DateTime,ps:3}],tpc:0,def:function(s,format,provider,result){return System.DateTime.tryParseExact(s,format,provider,result)},rt:$n[0].Boolean,p:[$n[0].String,$n[0].String,$n[0].IFormatProvider,$n[0].DateTime],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"op_Addition",is:!0,t:8,pi:[{n:"d",pt:$n[0].DateTime,ps:0},{n:"t",pt:$n[0].TimeSpan,ps:1}],tpc:0,def:function(d,t){return System.DateTime.adddt(d,t)},rt:$n[0].DateTime,p:[$n[0].DateTime,$n[0].TimeSpan],box:function($v){return H5.box($v,System.DateTime,System.DateTime.format)}},{a:2,n:"op_Equality",is:!0,t:8,pi:[{n:"a",pt:$n[0].DateTime,ps:0},{n:"b",pt:$n[0].DateTime,ps:1}],tpc:0,def:function(a,b){return H5.equals(a,b)},rt:$n[0].Boolean,p:[$n[0].DateTime,$n[0].DateTime],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"op_GreaterThan",is:!0,t:8,pi:[{n:"a",pt:$n[0].DateTime,ps:0},{n:"b",pt:$n[0].DateTime,ps:1}],tpc:0,def:function(a,b){return System.DateTime.gt(a,b)},rt:$n[0].Boolean,p:[$n[0].DateTime,$n[0].DateTime],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"op_GreaterThanOrEqual",is:!0,t:8,pi:[{n:"a",pt:$n[0].DateTime,ps:0},{n:"b",pt:$n[0].DateTime,ps:1}],tpc:0,def:function(a,b){return System.DateTime.gte(a,b)},rt:$n[0].Boolean,p:[$n[0].DateTime,$n[0].DateTime],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"op_Inequality",is:!0,t:8,pi:[{n:"a",pt:$n[0].DateTime,ps:0},{n:"b",pt:$n[0].DateTime,ps:1}],tpc:0,def:function(a,b){return!H5.equals(a,b)},rt:$n[0].Boolean,p:[$n[0].DateTime,$n[0].DateTime],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"op_LessThan",is:!0,t:8,pi:[{n:"a",pt:$n[0].DateTime,ps:0},{n:"b",pt:$n[0].DateTime,ps:1}],tpc:0,def:function(a,b){return System.DateTime.lt(a,b)},rt:$n[0].Boolean,p:[$n[0].DateTime,$n[0].DateTime],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"op_LessThanOrEqual",is:!0,t:8,pi:[{n:"a",pt:$n[0].DateTime,ps:0},{n:"b",pt:$n[0].DateTime,ps:1}],tpc:0,def:function(a,b){return System.DateTime.lte(a,b)},rt:$n[0].Boolean,p:[$n[0].DateTime,$n[0].DateTime],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"op_Subtraction",is:!0,t:8,pi:[{n:"a",pt:$n[0].DateTime,ps:0},{n:"b",pt:$n[0].DateTime,ps:1}],tpc:0,def:function(a,b){return System.DateTime.subdd(a,b)},rt:$n[0].TimeSpan,p:[$n[0].DateTime,$n[0].DateTime]},{a:2,n:"op_Subtraction",is:!0,t:8,pi:[{n:"d",pt:$n[0].DateTime,ps:0},{n:"t",pt:$n[0].TimeSpan,ps:1}],tpc:0,def:function(d,t){return System.DateTime.subdt(d,t)},rt:$n[0].DateTime,p:[$n[0].DateTime,$n[0].TimeSpan],box:function($v){return H5.box($v,System.DateTime,System.DateTime.format)}},{a:2,n:"Date",t:16,rt:$n[0].DateTime,g:{a:2,n:"get_Date",t:8,tpc:0,def:function(){return System.DateTime.getDate(this)},rt:$n[0].DateTime,box:function($v){return H5.box($v,System.DateTime,System.DateTime.format)}}},{a:2,n:"Day",t:16,rt:$n[0].Int32,g:{a:2,n:"get_Day",t:8,tpc:0,def:function(){return System.DateTime.getDay(this)},rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}}},{a:2,n:"DayOfWeek",t:16,rt:$n[0].DayOfWeek,g:{a:2,n:"get_DayOfWeek",t:8,tpc:0,def:function(){return System.DateTime.getDayOfWeek(this)},rt:$n[0].DayOfWeek,box:function($v){return H5.box($v,System.DayOfWeek,System.Enum.toStringFn(System.DayOfWeek))}}},{a:2,n:"DayOfYear",t:16,rt:$n[0].Int32,g:{a:2,n:"get_DayOfYear",t:8,tpc:0,def:function(){return System.DateTime.getDayOfYear(this)},rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}}},{a:2,n:"Hour",t:16,rt:$n[0].Int32,g:{a:2,n:"get_Hour",t:8,tpc:0,def:function(){return System.DateTime.getHour(this)},rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}}},{a:2,n:"Kind",t:16,rt:$n[0].DateTimeKind,g:{a:2,n:"get_Kind",t:8,tpc:0,def:function(){return System.DateTime.getKind(this)},rt:$n[0].DateTimeKind,box:function($v){return H5.box($v,System.DateTimeKind,System.Enum.toStringFn(System.DateTimeKind))}}},{a:2,n:"Millisecond",t:16,rt:$n[0].Int32,g:{a:2,n:"get_Millisecond",t:8,tpc:0,def:function(){return System.DateTime.getMillisecond(this)},rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}}},{a:2,n:"Minute",t:16,rt:$n[0].Int32,g:{a:2,n:"get_Minute",t:8,tpc:0,def:function(){return System.DateTime.getMinute(this)},rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}}},{a:2,n:"Month",t:16,rt:$n[0].Int32,g:{a:2,n:"get_Month",t:8,tpc:0,def:function(){return System.DateTime.getMonth(this)},rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}}},{a:2,n:"Now",is:!0,t:16,rt:$n[0].DateTime,g:{a:2,n:"get_Now",is:!0,t:8,tpc:0,def:function(){return System.DateTime.getNow()},rt:$n[0].DateTime,box:function($v){return H5.box($v,System.DateTime,System.DateTime.format)}}},{a:2,n:"Second",t:16,rt:$n[0].Int32,g:{a:2,n:"get_Second",t:8,tpc:0,def:function(){return System.DateTime.getSecond(this)},rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}}},{a:2,n:"Ticks",t:16,rt:$n[0].Int64,g:{a:2,n:"get_Ticks",t:8,tpc:0,def:function(){return System.DateTime.getTicks(this)},rt:$n[0].Int64}},{a:2,n:"TimeOfDay",t:16,rt:$n[0].TimeSpan,g:{a:2,n:"get_TimeOfDay",t:8,tpc:0,def:function(){return System.DateTime.getTimeOfDay(this)},rt:$n[0].TimeSpan}},{a:2,n:"Today",is:!0,t:16,rt:$n[0].DateTime,g:{a:2,n:"get_Today",is:!0,t:8,tpc:0,def:function(){return System.DateTime.getToday()},rt:$n[0].DateTime,box:function($v){return H5.box($v,System.DateTime,System.DateTime.format)}}},{a:2,n:"UtcNow",is:!0,t:16,rt:$n[0].DateTime,g:{a:2,n:"get_UtcNow",is:!0,t:8,tpc:0,def:function(){return System.DateTime.getUtcNow()},rt:$n[0].DateTime,box:function($v){return H5.box($v,System.DateTime,System.DateTime.format)}}},{a:2,n:"Year",t:16,rt:$n[0].Int32,g:{a:2,n:"get_Year",t:8,tpc:0,def:function(){return System.DateTime.getYear(this)},rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}}},{a:4,n:"DaysTo1970",is:!0,t:4,rt:$n[0].Int32,sn:"DaysTo1970",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"MaxTicks",is:!0,t:4,rt:$n[0].Int64,sn:"MaxTicks"},{a:2,n:"MaxValue",is:!0,t:4,rt:$n[0].DateTime,sn:"maxValue",ro:!0,box:function($v){return H5.box($v,System.DateTime,System.DateTime.format)}},{a:4,n:"MinTicks",is:!0,t:4,rt:$n[0].Int64,sn:"MinTicks"},{a:2,n:"MinValue",is:!0,t:4,rt:$n[0].DateTime,sn:"minValue",ro:!0,box:function($v){return H5.box($v,System.DateTime,System.DateTime.format)}},{a:1,n:"TicksPerDay",is:!0,t:4,rt:$n[0].Int64,sn:"TicksPerDay"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].DateTime,sn:"Date",box:function($v){return H5.box($v,System.DateTime,System.DateTime.format)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Int32,sn:"Day",box:function($v){return H5.box($v,System.Int32)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].DayOfWeek,sn:"DayOfWeek",box:function($v){return H5.box($v,System.DayOfWeek,System.Enum.toStringFn(System.DayOfWeek))}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Int32,sn:"DayOfYear",box:function($v){return H5.box($v,System.Int32)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Int32,sn:"Hour",box:function($v){return H5.box($v,System.Int32)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].DateTimeKind,sn:"Kind",box:function($v){return H5.box($v,System.DateTimeKind,System.Enum.toStringFn(System.DateTimeKind))}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Int32,sn:"Millisecond",box:function($v){return H5.box($v,System.Int32)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Int32,sn:"Minute",box:function($v){return H5.box($v,System.Int32)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Int32,sn:"Month",box:function($v){return H5.box($v,System.Int32)}},{a:1,backing:!0,n:"k__BackingField",is:!0,t:4,rt:$n[0].DateTime,sn:"Now",box:function($v){return H5.box($v,System.DateTime,System.DateTime.format)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Int32,sn:"Second",box:function($v){return H5.box($v,System.Int32)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Int64,sn:"Ticks"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].TimeSpan,sn:"TimeOfDay"},{a:1,backing:!0,n:"k__BackingField",is:!0,t:4,rt:$n[0].DateTime,sn:"Today",box:function($v){return H5.box($v,System.DateTime,System.DateTime.format)}},{a:1,backing:!0,n:"k__BackingField",is:!0,t:4,rt:$n[0].DateTime,sn:"UtcNow",box:function($v){return H5.box($v,System.DateTime,System.DateTime.format)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Int32,sn:"Year",box:function($v){return H5.box($v,System.Int32)}}]}},$n);$m("System.DayOfWeek",function(){return{att:8449,a:2,at:[new System.SerializableAttribute],m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:"Friday",is:!0,t:4,rt:$n[0].DayOfWeek,sn:"Friday",box:function($v){return H5.box($v,System.DayOfWeek,System.Enum.toStringFn(System.DayOfWeek))}},{a:2,n:"Monday",is:!0,t:4,rt:$n[0].DayOfWeek,sn:"Monday",box:function($v){return H5.box($v,System.DayOfWeek,System.Enum.toStringFn(System.DayOfWeek))}},{a:2,n:"Saturday",is:!0,t:4,rt:$n[0].DayOfWeek,sn:"Saturday",box:function($v){return H5.box($v,System.DayOfWeek,System.Enum.toStringFn(System.DayOfWeek))}},{a:2,n:"Sunday",is:!0,t:4,rt:$n[0].DayOfWeek,sn:"Sunday",box:function($v){return H5.box($v,System.DayOfWeek,System.Enum.toStringFn(System.DayOfWeek))}},{a:2,n:"Thursday",is:!0,t:4,rt:$n[0].DayOfWeek,sn:"Thursday",box:function($v){return H5.box($v,System.DayOfWeek,System.Enum.toStringFn(System.DayOfWeek))}},{a:2,n:"Tuesday",is:!0,t:4,rt:$n[0].DayOfWeek,sn:"Tuesday",box:function($v){return H5.box($v,System.DayOfWeek,System.Enum.toStringFn(System.DayOfWeek))}},{a:2,n:"Wednesday",is:!0,t:4,rt:$n[0].DayOfWeek,sn:"Wednesday",box:function($v){return H5.box($v,System.DayOfWeek,System.Enum.toStringFn(System.DayOfWeek))}}]}},$n);$m("System.Decimal",function(){return{att:1048841,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,def:function(){return System.Decimal}},{a:2,n:".ctor",t:1,p:[$n[0].Double],pi:[{n:"d",pt:$n[0].Double,ps:0}],def:function(d){return System.Decimal(d)}},{a:2,n:".ctor",t:1,p:[$n[0].Int32],pi:[{n:"i",pt:$n[0].Int32,ps:0}],def:function(i){return System.Decimal(i)}},{a:2,n:".ctor",t:1,p:[$n[0].Int64],pi:[{n:"n",pt:$n[0].Int64,ps:0}],def:function(n){return System.Decimal(n)}},{a:1,n:".ctor",t:1,p:[System.Object],pi:[{n:"_",pt:System.Object,ps:0}],def:function(_){return System.Decimal(0)}},{a:2,n:".ctor",t:1,p:[$n[0].Single],pi:[{n:"f",pt:$n[0].Single,ps:0}],def:function(f){return System.Decimal(f)}},{a:2,n:".ctor",t:1,p:[$n[0].UInt32],pi:[{n:"i",pt:$n[0].UInt32,ps:0}],def:function(i){return System.Decimal(i)}},{a:2,n:".ctor",t:1,p:[$n[0].UInt64],pi:[{n:"n",pt:$n[0].UInt64,ps:0}],def:function(n){return System.Decimal(n)}},{a:2,n:".ctor",t:1,p:[$n[0].Int32,$n[0].Int32,$n[0].Int32,$n[0].Boolean,$n[0].Byte],pi:[{n:"lo",pt:$n[0].Int32,ps:0},{n:"mid",pt:$n[0].Int32,ps:1},{n:"hi",pt:$n[0].Int32,ps:2},{n:"isNegative",pt:$n[0].Boolean,ps:3},{n:"scale",pt:$n[0].Byte,ps:4}],def:function(lo,mid,hi,isNegative,scale){return System.Decimal}},{a:2,n:"Abs",t:8,sn:"abs",rt:$n[0].Decimal},{a:2,n:"Add",is:!0,t:8,pi:[{n:"d1",pt:$n[0].Decimal,ps:0},{n:"d2",pt:$n[0].Decimal,ps:1}],tpc:0,def:function(d1,d2){return d1.add(d2)},rt:$n[0].Decimal,p:[$n[0].Decimal,$n[0].Decimal]},{a:2,n:"Ceiling",t:8,sn:"ceil",rt:$n[0].Decimal},{a:2,n:"Ceiling",is:!0,t:8,pi:[{n:"d",pt:$n[0].Decimal,ps:0}],tpc:0,def:function(d){return d.ceil()},rt:$n[0].Decimal,p:[$n[0].Decimal]},{a:2,n:"Compare",is:!0,t:8,pi:[{n:"d1",pt:$n[0].Decimal,ps:0},{n:"d2",pt:$n[0].Decimal,ps:1}],tpc:0,def:function(d1,d2){return d1.compareTo(d2)},rt:$n[0].Int32,p:[$n[0].Decimal,$n[0].Decimal],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"CompareTo",t:8,pi:[{n:"other",pt:$n[0].Decimal,ps:0}],tpc:0,def:function(other){return this.compareTo(other)},rt:$n[0].Int32,p:[$n[0].Decimal],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"CompareTo",t:8,pi:[{n:"obj",pt:$n[0].Object,ps:0}],tpc:0,def:function(obj){return this.compareTo(obj)},rt:$n[0].Int32,p:[$n[0].Object],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"ComparedTo",t:8,pi:[{n:"d",pt:$n[0].Decimal,ps:0}],sn:"comparedTo",rt:$n[0].Int32,p:[$n[0].Decimal],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"DecimalPlaces",t:8,sn:"decimalPlaces",rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"Divide",is:!0,t:8,pi:[{n:"d1",pt:$n[0].Decimal,ps:0},{n:"d2",pt:$n[0].Decimal,ps:1}],tpc:0,def:function(d1,d2){return d1.div(d2)},rt:$n[0].Decimal,p:[$n[0].Decimal,$n[0].Decimal]},{a:2,n:"DividedToIntegerBy",t:8,pi:[{n:"d",pt:$n[0].Decimal,ps:0}],sn:"dividedToIntegerBy",rt:$n[0].Decimal,p:[$n[0].Decimal]},{a:2,n:"Equals",t:8,pi:[{n:"other",pt:$n[0].Decimal,ps:0}],sn:"equalsT",rt:$n[0].Boolean,p:[$n[0].Decimal],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ov:!0,a:2,n:"Equals",t:8,pi:[{n:"o",pt:$n[0].Object,ps:0}],sn:"equals",rt:$n[0].Boolean,p:[$n[0].Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Equals",is:!0,t:8,pi:[{n:"d1",pt:$n[0].Decimal,ps:0},{n:"d2",pt:$n[0].Decimal,ps:1}],tpc:0,def:function(d1,d2){return d1.equals(d2)},rt:$n[0].Boolean,p:[$n[0].Decimal,$n[0].Decimal],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Exp",is:!0,t:8,pi:[{n:"d",pt:$n[0].Decimal,ps:0}],tpc:0,def:function(d){return System.Decimal.exp(d)},rt:$n[0].Decimal,p:[$n[0].Decimal]},{a:2,n:"Exponential",t:8,sn:"exponential",rt:$n[0].Decimal},{a:2,n:"Floor",t:8,sn:"floor",rt:$n[0].Decimal},{a:2,n:"Floor",is:!0,t:8,pi:[{n:"d",pt:$n[0].Decimal,ps:0}],tpc:0,def:function(d){return d.floor()},rt:$n[0].Decimal,p:[$n[0].Decimal]},{a:2,n:"Format",t:8,pi:[{n:"format",pt:$n[0].String,ps:0}],tpc:0,def:function(format){return H5.Int.format(this,format)},rt:$n[0].String,p:[$n[0].String]},{a:2,n:"Format",t:8,pi:[{n:"format",pt:$n[0].String,ps:0},{n:"provider",pt:$n[0].IFormatProvider,ps:1}],tpc:0,def:function(format,provider){return H5.Int.format(this,format,provider)},rt:$n[0].String,p:[$n[0].String,$n[0].IFormatProvider]},{a:4,n:"FromBytes",is:!0,t:8,pi:[{n:"bytes",pt:$n[0].Array.type(System.Byte),ps:0}],tpc:0,def:function(bytes){return System.Decimal.fromBytes(bytes)},rt:$n[0].Decimal,p:[$n[0].Array.type(System.Byte)]},{a:4,n:"GetBytes",is:!0,t:8,pi:[{n:"value",pt:$n[0].Decimal,ps:0}],tpc:0,def:function(value){return value.getBytes()},rt:$n[0].Array.type(System.Byte),p:[$n[0].Decimal]},{ov:!0,a:2,n:"GetHashCode",t:8,sn:"getHashCode",rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"IsFinite",t:8,sn:"isFinite",rt:$n[0].Boolean,box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"IsInteger",t:8,sn:"isInteger",rt:$n[0].Boolean,box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"IsNaN",t:8,sn:"isNaN",rt:$n[0].Boolean,box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"IsNegative",t:8,sn:"isNegative",rt:$n[0].Boolean,box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"IsZero",t:8,sn:"isZero",rt:$n[0].Boolean,box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Ln",t:8,sn:"ln",rt:$n[0].Decimal},{a:2,n:"Ln",is:!0,t:8,pi:[{n:"d",pt:$n[0].Decimal,ps:0}],tpc:0,def:function(d){return System.Decimal.ln(d)},rt:$n[0].Decimal,p:[$n[0].Decimal]},{a:2,n:"Log",t:8,pi:[{n:"logBase",pt:$n[0].Decimal,ps:0}],sn:"log",rt:$n[0].Decimal,p:[$n[0].Decimal]},{a:2,n:"Log",is:!0,t:8,pi:[{n:"d",pt:$n[0].Decimal,ps:0},{n:"logBase",pt:$n[0].Decimal,ps:1}],tpc:0,def:function(d,logBase){return System.Decimal.log(d,logBase)},rt:$n[0].Decimal,p:[$n[0].Decimal,$n[0].Decimal]},{a:2,n:"Max",is:!0,t:8,pi:[{n:"values",ip:!0,pt:$n[0].Array.type(System.Decimal),ps:0}],sn:"max",rt:$n[0].Decimal,p:[$n[0].Array.type(System.Decimal)]},{a:2,n:"Min",is:!0,t:8,pi:[{n:"values",ip:!0,pt:$n[0].Array.type(System.Decimal),ps:0}],sn:"min",rt:$n[0].Decimal,p:[$n[0].Array.type(System.Decimal)]},{a:2,n:"Multiply",is:!0,t:8,pi:[{n:"d1",pt:$n[0].Decimal,ps:0},{n:"d2",pt:$n[0].Decimal,ps:1}],tpc:0,def:function(d1,d2){return d1.mul(d2)},rt:$n[0].Decimal,p:[$n[0].Decimal,$n[0].Decimal]},{a:2,n:"Negate",is:!0,t:8,pi:[{n:"d",pt:$n[0].Decimal,ps:0}],tpc:0,def:function(d){return System.Decimal(0).sub(d)},rt:$n[0].Decimal,p:[$n[0].Decimal]},{a:2,n:"Parse",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0}],tpc:0,def:function(s){return System.Decimal(s)},rt:$n[0].Decimal,p:[$n[0].String]},{a:2,n:"Parse",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0},{n:"provider",pt:$n[0].IFormatProvider,ps:1}],tpc:0,def:function(s,provider){return System.Decimal(s,provider)},rt:$n[0].Decimal,p:[$n[0].String,$n[0].IFormatProvider]},{a:2,n:"Pow",t:8,pi:[{n:"n",pt:$n[0].Double,ps:0}],sn:"pow",rt:$n[0].Decimal,p:[$n[0].Double]},{a:2,n:"Pow",is:!0,t:8,pi:[{n:"d",pt:$n[0].Decimal,ps:0},{n:"exponent",pt:$n[0].Decimal,ps:1}],tpc:0,def:function(d,exponent){return System.Decimal.pow(d,exponent)},rt:$n[0].Decimal,p:[$n[0].Decimal,$n[0].Decimal]},{a:2,n:"Precision",t:8,sn:"precision",rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"Random",is:!0,t:8,pi:[{n:"dp",pt:$n[0].Int32,ps:0}],sn:"random",rt:$n[0].Decimal,p:[$n[0].Int32]},{a:2,n:"Remainder",is:!0,t:8,pi:[{n:"d1",pt:$n[0].Decimal,ps:0},{n:"d2",pt:$n[0].Decimal,ps:1}],tpc:0,def:function(d1,d2){return d1.mod(d2)},rt:$n[0].Decimal,p:[$n[0].Decimal,$n[0].Decimal]},{a:2,n:"Round",t:8,sn:"round",rt:$n[0].Decimal},{a:2,n:"Round",is:!0,t:8,pi:[{n:"d",pt:$n[0].Decimal,ps:0}],tpc:0,def:function(d){return System.Decimal.round(d,6)},rt:$n[0].Decimal,p:[$n[0].Decimal]},{a:2,n:"Round",is:!0,t:8,pi:[{n:"d",pt:$n[0].Decimal,ps:0},{n:"decimals",pt:$n[0].Int32,ps:1}],tpc:0,def:function(d,decimals){return System.Decimal.toDecimalPlaces(d,decimals,6)},rt:$n[0].Decimal,p:[$n[0].Decimal,$n[0].Int32]},{a:2,n:"Round",is:!0,t:8,pi:[{n:"d",pt:$n[0].Decimal,ps:0},{n:"mode",pt:Number,ps:1}],tpc:0,def:function(d,mode){return System.Decimal.round(d,mode)},rt:$n[0].Decimal,p:[$n[0].Decimal,Number]},{a:2,n:"Round",is:!0,t:8,pi:[{n:"d",pt:$n[0].Decimal,ps:0},{n:"decimals",pt:$n[0].Int32,ps:1},{n:"mode",pt:Number,ps:2}],tpc:0,def:function(d,decimals,mode){return System.Decimal.toDecimalPlaces(d,decimals,mode)},rt:$n[0].Decimal,p:[$n[0].Decimal,$n[0].Int32,Number]},{a:2,n:"SetConfig",is:!0,t:8,pi:[{n:"config",pt:$n[0].Object,ps:0}],sn:"setConfig",rt:$n[0].Void,p:[$n[0].Object]},{a:2,n:"Sqrt",t:8,sn:"sqrt",rt:$n[0].Decimal},{a:2,n:"Sqrt",is:!0,t:8,pi:[{n:"d",pt:$n[0].Decimal,ps:0}],tpc:0,def:function(d){return System.Decimal.sqrt(d)},rt:$n[0].Decimal,p:[$n[0].Decimal]},{a:2,n:"Subtract",is:!0,t:8,pi:[{n:"d1",pt:$n[0].Decimal,ps:0},{n:"d2",pt:$n[0].Decimal,ps:1}],tpc:0,def:function(d1,d2){return d1.sub(d2)},rt:$n[0].Decimal,p:[$n[0].Decimal,$n[0].Decimal]},{a:2,n:"ToByte",is:!0,t:8,pi:[{n:"value",pt:$n[0].Decimal,ps:0}],tpc:0,def:function(value){return System.Decimal.toInt(value)},rt:$n[0].Byte,p:[$n[0].Decimal],box:function($v){return H5.box($v,System.Byte)}},{a:2,n:"ToChar",is:!0,t:8,pi:[{n:"value",pt:$n[0].Decimal,ps:0}],tpc:0,def:function(value){return System.Decimal.toInt(value)},rt:$n[0].Char,p:[$n[0].Decimal],box:function($v){return H5.box($v,System.Char,String.fromCharCode,System.Char.getHashCode)}},{a:2,n:"ToDecimalPlaces",t:8,pi:[{n:"dp",pt:$n[0].Int32,ps:0},{n:"rm",pt:Number,ps:1}],sn:"toDecimalPlaces",rt:$n[0].Decimal,p:[$n[0].Int32,Number]},{a:2,n:"ToDouble",is:!0,t:8,pi:[{n:"value",pt:$n[0].Decimal,ps:0}],tpc:0,def:function(value){return System.Decimal.toFloat(value)},rt:$n[0].Double,p:[$n[0].Decimal],box:function($v){return H5.box($v,System.Double,System.Double.format,System.Double.getHashCode)}},{a:2,n:"ToExponential",t:8,pi:[{n:"dp",pt:$n[0].Int32,ps:0},{n:"rm",pt:Number,ps:1}],sn:"toExponential",rt:$n[0].String,p:[$n[0].Int32,Number]},{a:2,n:"ToFixed",t:8,pi:[{n:"dp",pt:$n[0].Int32,ps:0},{n:"rm",pt:Number,ps:1}],sn:"toFixed",rt:$n[0].String,p:[$n[0].Int32,Number]},{a:2,n:"ToFormat",t:8,sn:"toFormat",rt:$n[0].String},{a:2,n:"ToFormat",t:8,pi:[{n:"config",pt:$n[0].Object,ps:0}],tpc:0,def:function(config){return this.toFormat(null,null,config)},rt:$n[0].String,p:[$n[0].Object]},{a:2,n:"ToFormat",t:8,pi:[{n:"dp",pt:$n[0].Int32,ps:0}],sn:"toFormat",rt:$n[0].String,p:[$n[0].Int32]},{a:2,n:"ToFormat",t:8,pi:[{n:"dp",pt:$n[0].Int32,ps:0},{n:"rm",pt:Number,ps:1}],sn:"toFormat",rt:$n[0].String,p:[$n[0].Int32,Number]},{a:2,n:"ToFormat",t:8,pi:[{n:"dp",pt:$n[0].Int32,ps:0},{n:"rm",pt:Number,ps:1},{n:"config",pt:$n[0].Object,ps:2}],sn:"toFormat",rt:$n[0].String,p:[$n[0].Int32,Number,$n[0].Object]},{a:2,n:"ToFormat",t:8,pi:[{n:"dp",pt:$n[0].Int32,ps:0},{n:"rm",pt:Number,ps:1},{n:"provider",pt:$n[0].IFormatProvider,ps:2}],sn:"toFormat",rt:$n[0].String,p:[$n[0].Int32,Number,$n[0].IFormatProvider]},{a:2,n:"ToInt16",is:!0,t:8,pi:[{n:"value",pt:$n[0].Decimal,ps:0}],tpc:0,def:function(value){return System.Decimal.toInt(value)},rt:$n[0].Int16,p:[$n[0].Decimal],box:function($v){return H5.box($v,System.Int16)}},{a:2,n:"ToInt32",is:!0,t:8,pi:[{n:"value",pt:$n[0].Decimal,ps:0}],tpc:0,def:function(value){return System.Decimal.toInt(value)},rt:$n[0].Int32,p:[$n[0].Decimal],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"ToInt64",is:!0,t:8,pi:[{n:"value",pt:$n[0].Decimal,ps:0}],tpc:0,def:function(value){return System.Decimal.toInt(value,System.Int64)},rt:$n[0].Int64,p:[$n[0].Decimal]},{a:2,n:"ToPrecision",t:8,pi:[{n:"sd",pt:$n[0].Int32,ps:0},{n:"rm",pt:Number,ps:1}],sn:"toPrecision",rt:$n[0].String,p:[$n[0].Int32,Number]},{a:2,n:"ToSByte",is:!0,t:8,pi:[{n:"value",pt:$n[0].Decimal,ps:0}],tpc:0,def:function(value){return System.Decimal.toInt(value)},rt:$n[0].SByte,p:[$n[0].Decimal],box:function($v){return H5.box($v,System.SByte)}},{a:2,n:"ToSignificantDigits",t:8,pi:[{n:"sd",pt:$n[0].Int32,ps:0},{n:"rm",pt:Number,ps:1}],sn:"toSignificantDigits",rt:$n[0].Decimal,p:[$n[0].Int32,Number]},{a:2,n:"ToSingle",is:!0,t:8,pi:[{n:"value",pt:$n[0].Decimal,ps:0}],tpc:0,def:function(value){return System.Decimal.toFloat(value)},rt:$n[0].Single,p:[$n[0].Decimal],box:function($v){return H5.box($v,System.Single,System.Single.format,System.Single.getHashCode)}},{ov:!0,a:2,n:"ToString",t:8,sn:"toString",rt:$n[0].String},{a:2,n:"ToString",t:8,pi:[{n:"provider",pt:$n[0].IFormatProvider,ps:0}],tpc:0,def:function(provider){return H5.Int.format(this,"G",provider)},rt:$n[0].String,p:[$n[0].IFormatProvider]},{a:2,n:"ToString",t:8,pi:[{n:"format",pt:$n[0].String,ps:0}],tpc:0,def:function(format){return H5.Int.format(this,format)},rt:$n[0].String,p:[$n[0].String]},{a:2,n:"ToString",t:8,pi:[{n:"format",pt:$n[0].String,ps:0},{n:"provider",pt:$n[0].IFormatProvider,ps:1}],tpc:0,def:function(format,provider){return H5.Int.format(this,format,provider)},rt:$n[0].String,p:[$n[0].String,$n[0].IFormatProvider]},{a:2,n:"ToUInt16",is:!0,t:8,pi:[{n:"value",pt:$n[0].Decimal,ps:0}],tpc:0,def:function(value){return System.Decimal.toInt(value)},rt:$n[0].UInt16,p:[$n[0].Decimal],box:function($v){return H5.box($v,System.UInt16)}},{a:2,n:"ToUInt32",is:!0,t:8,pi:[{n:"value",pt:$n[0].Decimal,ps:0}],tpc:0,def:function(value){return System.Decimal.toInt(value)},rt:$n[0].UInt32,p:[$n[0].Decimal],box:function($v){return H5.box($v,System.UInt32)}},{a:2,n:"ToUInt64",is:!0,t:8,pi:[{n:"value",pt:$n[0].Decimal,ps:0}],tpc:0,def:function(value){return System.Decimal.toInt(value,System.UInt64)},rt:$n[0].UInt64,p:[$n[0].Decimal]},{a:2,n:"Truncate",is:!0,t:8,pi:[{n:"d",pt:$n[0].Decimal,ps:0}],tpc:0,def:function(d){return d.trunc()},rt:$n[0].Decimal,p:[$n[0].Decimal]},{a:2,n:"TryParse",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0},{n:"result",out:!0,pt:$n[0].Decimal,ps:1}],tpc:0,def:function(s,result){return System.Decimal.tryParse(s,null,result)},rt:$n[0].Boolean,p:[$n[0].String,$n[0].Decimal],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"TryParse",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0},{n:"provider",pt:$n[0].IFormatProvider,ps:1},{n:"result",out:!0,pt:$n[0].Decimal,ps:2}],tpc:0,def:function(s,provider,result){return System.Decimal.tryParse(s,provider,result)},rt:$n[0].Boolean,p:[$n[0].String,$n[0].IFormatProvider,$n[0].Decimal],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"op_Addition",is:!0,t:8,pi:[{n:"d1",pt:$n[0].Decimal,ps:0},{n:"d2",pt:$n[0].Decimal,ps:1}],tpc:0,def:function(d1,d2){return d1.add(d2)},rt:$n[0].Decimal,p:[$n[0].Decimal,$n[0].Decimal]},{a:2,n:"op_Decrement",is:!0,t:8,pi:[{n:"d",pt:$n[0].Decimal,ps:0}],tpc:0,def:function(d){return d.dec()},rt:$n[0].Decimal,p:[$n[0].Decimal]},{a:2,n:"op_Division",is:!0,t:8,pi:[{n:"d1",pt:$n[0].Decimal,ps:0},{n:"d2",pt:$n[0].Decimal,ps:1}],tpc:0,def:function(d1,d2){return d1.div(d2)},rt:$n[0].Decimal,p:[$n[0].Decimal,$n[0].Decimal]},{a:2,n:"op_Equality",is:!0,t:8,pi:[{n:"d1",pt:$n[0].Decimal,ps:0},{n:"d2",pt:$n[0].Decimal,ps:1}],tpc:0,def:function(d1,d2){return d1.equalsT(d2)},rt:$n[0].Boolean,p:[$n[0].Decimal,$n[0].Decimal],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"op_Explicit",is:!0,t:8,pi:[{n:"value",pt:$n[0].Decimal,ps:0}],sn:"op_Explicit",rt:$n[0].Byte,p:[$n[0].Decimal],box:function($v){return H5.box($v,System.Byte)}},{a:2,n:"op_Explicit",is:!0,t:8,pi:[{n:"value",pt:$n[0].Decimal,ps:0}],sn:"op_Explicit",rt:$n[0].Char,p:[$n[0].Decimal],box:function($v){return H5.box($v,System.Char,String.fromCharCode,System.Char.getHashCode)}},{a:2,n:"op_Explicit",is:!0,t:8,pi:[{n:"value",pt:$n[0].Decimal,ps:0}],sn:"op_Explicit",rt:$n[0].Double,p:[$n[0].Decimal],box:function($v){return H5.box($v,System.Double,System.Double.format,System.Double.getHashCode)}},{a:2,n:"op_Explicit",is:!0,t:8,pi:[{n:"value",pt:$n[0].Decimal,ps:0}],sn:"op_Explicit",rt:$n[0].Int16,p:[$n[0].Decimal],box:function($v){return H5.box($v,System.Int16)}},{a:2,n:"op_Explicit",is:!0,t:8,pi:[{n:"value",pt:$n[0].Decimal,ps:0}],sn:"op_Explicit",rt:$n[0].Int32,p:[$n[0].Decimal],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"op_Explicit",is:!0,t:8,pi:[{n:"value",pt:$n[0].Decimal,ps:0}],sn:"op_Explicit",rt:$n[0].Int64,p:[$n[0].Decimal]},{a:2,n:"op_Explicit",is:!0,t:8,pi:[{n:"value",pt:$n[0].Decimal,ps:0}],sn:"op_Explicit",rt:$n[0].SByte,p:[$n[0].Decimal],box:function($v){return H5.box($v,System.SByte)}},{a:2,n:"op_Explicit",is:!0,t:8,pi:[{n:"value",pt:$n[0].Decimal,ps:0}],sn:"op_Explicit",rt:$n[0].Single,p:[$n[0].Decimal],box:function($v){return H5.box($v,System.Single,System.Single.format,System.Single.getHashCode)}},{a:2,n:"op_Explicit",is:!0,t:8,pi:[{n:"value",pt:$n[0].Decimal,ps:0}],sn:"op_Explicit",rt:$n[0].UInt16,p:[$n[0].Decimal],box:function($v){return H5.box($v,System.UInt16)}},{a:2,n:"op_Explicit",is:!0,t:8,pi:[{n:"value",pt:$n[0].Decimal,ps:0}],sn:"op_Explicit",rt:$n[0].UInt32,p:[$n[0].Decimal],box:function($v){return H5.box($v,System.UInt32)}},{a:2,n:"op_Explicit",is:!0,t:8,pi:[{n:"value",pt:$n[0].Decimal,ps:0}],sn:"op_Explicit",rt:$n[0].UInt64,p:[$n[0].Decimal]},{a:2,n:"op_Explicit",is:!0,t:8,pi:[{n:"value",pt:$n[0].Double,ps:0}],sn:"op_Explicit",rt:$n[0].Decimal,p:[$n[0].Double]},{a:2,n:"op_Explicit",is:!0,t:8,pi:[{n:"value",pt:$n[0].Single,ps:0}],sn:"op_Explicit",rt:$n[0].Decimal,p:[$n[0].Single]},{a:2,n:"op_GreaterThan",is:!0,t:8,pi:[{n:"d1",pt:$n[0].Decimal,ps:0},{n:"d2",pt:$n[0].Decimal,ps:1}],tpc:0,def:function(d1,d2){return d1.gt(d2)},rt:$n[0].Boolean,p:[$n[0].Decimal,$n[0].Decimal],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"op_GreaterThanOrEqual",is:!0,t:8,pi:[{n:"d1",pt:$n[0].Decimal,ps:0},{n:"d2",pt:$n[0].Decimal,ps:1}],tpc:0,def:function(d1,d2){return d1.gte(d2)},rt:$n[0].Boolean,p:[$n[0].Decimal,$n[0].Decimal],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"op_Implicit",is:!0,t:8,pi:[{n:"value",pt:$n[0].Byte,ps:0}],sn:"op_Implicit",rt:$n[0].Decimal,p:[$n[0].Byte]},{a:2,n:"op_Implicit",is:!0,t:8,pi:[{n:"value",pt:$n[0].Char,ps:0}],sn:"op_Implicit",rt:$n[0].Decimal,p:[$n[0].Char]},{a:2,n:"op_Implicit",is:!0,t:8,pi:[{n:"value",pt:$n[0].Int16,ps:0}],sn:"op_Implicit",rt:$n[0].Decimal,p:[$n[0].Int16]},{a:2,n:"op_Implicit",is:!0,t:8,pi:[{n:"value",pt:$n[0].Int32,ps:0}],sn:"op_Implicit",rt:$n[0].Decimal,p:[$n[0].Int32]},{a:2,n:"op_Implicit",is:!0,t:8,pi:[{n:"value",pt:$n[0].Int64,ps:0}],sn:"op_Implicit",rt:$n[0].Decimal,p:[$n[0].Int64]},{a:2,n:"op_Implicit",is:!0,t:8,pi:[{n:"value",pt:$n[0].SByte,ps:0}],sn:"op_Implicit",rt:$n[0].Decimal,p:[$n[0].SByte]},{a:2,n:"op_Implicit",is:!0,t:8,pi:[{n:"value",pt:$n[0].UInt16,ps:0}],sn:"op_Implicit",rt:$n[0].Decimal,p:[$n[0].UInt16]},{a:2,n:"op_Implicit",is:!0,t:8,pi:[{n:"value",pt:$n[0].UInt32,ps:0}],sn:"op_Implicit",rt:$n[0].Decimal,p:[$n[0].UInt32]},{a:2,n:"op_Implicit",is:!0,t:8,pi:[{n:"value",pt:$n[0].UInt64,ps:0}],sn:"op_Implicit",rt:$n[0].Decimal,p:[$n[0].UInt64]},{a:2,n:"op_Increment",is:!0,t:8,pi:[{n:"d",pt:$n[0].Decimal,ps:0}],tpc:0,def:function(d){return d.inc()},rt:$n[0].Decimal,p:[$n[0].Decimal]},{a:2,n:"op_Inequality",is:!0,t:8,pi:[{n:"d1",pt:$n[0].Decimal,ps:0},{n:"d2",pt:$n[0].Decimal,ps:1}],tpc:0,def:function(d1,d2){return d1.ne(d2)},rt:$n[0].Boolean,p:[$n[0].Decimal,$n[0].Decimal],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"op_LessThan",is:!0,t:8,pi:[{n:"d1",pt:$n[0].Decimal,ps:0},{n:"d2",pt:$n[0].Decimal,ps:1}],tpc:0,def:function(d1,d2){return d1.lt(d2)},rt:$n[0].Boolean,p:[$n[0].Decimal,$n[0].Decimal],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"op_LessThanOrEqual",is:!0,t:8,pi:[{n:"d1",pt:$n[0].Decimal,ps:0},{n:"d2",pt:$n[0].Decimal,ps:1}],tpc:0,def:function(d1,d2){return d1.lte(d2)},rt:$n[0].Boolean,p:[$n[0].Decimal,$n[0].Decimal],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"op_Modulus",is:!0,t:8,pi:[{n:"d1",pt:$n[0].Decimal,ps:0},{n:"d2",pt:$n[0].Decimal,ps:1}],tpc:0,def:function(d1,d2){return d1.mod(d2)},rt:$n[0].Decimal,p:[$n[0].Decimal,$n[0].Decimal]},{a:2,n:"op_Multiply",is:!0,t:8,pi:[{n:"d1",pt:$n[0].Decimal,ps:0},{n:"d2",pt:$n[0].Decimal,ps:1}],tpc:0,def:function(d1,d2){return d1.mul(d2)},rt:$n[0].Decimal,p:[$n[0].Decimal,$n[0].Decimal]},{a:2,n:"op_Subtraction",is:!0,t:8,pi:[{n:"d1",pt:$n[0].Decimal,ps:0},{n:"d2",pt:$n[0].Decimal,ps:1}],tpc:0,def:function(d1,d2){return d1.sub(d2)},rt:$n[0].Decimal,p:[$n[0].Decimal,$n[0].Decimal]},{a:2,n:"op_UnaryNegation",is:!0,t:8,pi:[{n:"d",pt:$n[0].Decimal,ps:0}],tpc:0,def:function(d){return d.neg()},rt:$n[0].Decimal,p:[$n[0].Decimal]},{a:2,n:"op_UnaryPlus",is:!0,t:8,pi:[{n:"d",pt:$n[0].Decimal,ps:0}],tpc:0,def:function(d){return d.clone()},rt:$n[0].Decimal,p:[$n[0].Decimal]},{a:2,n:"MaxValue",is:!0,t:4,rt:$n[0].Decimal,sn:"MaxValue"},{a:2,n:"MinValue",is:!0,t:4,rt:$n[0].Decimal,sn:"MinValue"},{a:2,n:"MinusOne",is:!0,t:4,rt:$n[0].Decimal,sn:"MinusOne"},{a:2,n:"One",is:!0,t:4,rt:$n[0].Decimal,sn:"One"},{a:2,n:"Zero",is:!0,t:4,rt:$n[0].Decimal,sn:"Zero"}]}},$n);$m("System.Double",function(){return{att:1048841,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,def:function(){return Number}},{a:1,n:".ctor",t:1,p:[$n[0].Int32],pi:[{n:"i",pt:$n[0].Int32,ps:0}],def:function(i){return Number}},{a:2,n:"CompareTo",t:8,pi:[{n:"other",pt:$n[0].Double,ps:0}],tpc:0,def:function(other){return H5.compare(this,other)},rt:$n[0].Int32,p:[$n[0].Double],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"CompareTo",t:8,pi:[{n:"obj",pt:$n[0].Object,ps:0}],tpc:0,def:function(obj){return H5.compare(this,obj)},rt:$n[0].Int32,p:[$n[0].Object],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"Equals",t:8,pi:[{n:"other",pt:$n[0].Double,ps:0}],tpc:0,def:function(other){return this===other},rt:$n[0].Boolean,p:[$n[0].Double],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ov:!0,a:2,n:"Equals",t:8,pi:[{n:"other",pt:$n[0].Object,ps:0}],tpc:0,def:function(other){return System.Double.equals(this,other)},rt:$n[0].Boolean,p:[$n[0].Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Format",t:8,pi:[{n:"format",pt:$n[0].String,ps:0}],tpc:0,def:function(format){return System.Double.format(this,format)},rt:$n[0].String,p:[$n[0].String]},{a:2,n:"Format",t:8,pi:[{n:"format",pt:$n[0].String,ps:0},{n:"provider",pt:$n[0].IFormatProvider,ps:1}],tpc:0,def:function(format,provider){return System.Double.format(this,format,provider)},rt:$n[0].String,p:[$n[0].String,$n[0].IFormatProvider]},{ov:!0,a:2,n:"GetHashCode",t:8,tpc:0,def:function(){return System.Double.getHashCode(this)},rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"IsFinite",is:!0,t:8,pi:[{n:"d",pt:$n[0].Double,ps:0}],tpc:0,def:function(d){return isFinite(d)},rt:$n[0].Boolean,p:[$n[0].Double],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"IsInfinity",is:!0,t:8,pi:[{n:"d",pt:$n[0].Double,ps:0}],tpc:0,def:function(d){return Math.abs(d)===Number.POSITIVE_INFINITY},rt:$n[0].Boolean,p:[$n[0].Double],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"IsNaN",is:!0,t:8,pi:[{n:"d",pt:$n[0].Double,ps:0}],tpc:0,def:function(d){return isNaN(d)},rt:$n[0].Boolean,p:[$n[0].Double],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"IsNegativeInfinity",is:!0,t:8,pi:[{n:"d",pt:$n[0].Double,ps:0}],tpc:0,def:function(d){return d===Number.NEGATIVE_INFINITY},rt:$n[0].Boolean,p:[$n[0].Double],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"IsPositiveInfinity",is:!0,t:8,pi:[{n:"d",pt:$n[0].Double,ps:0}],tpc:0,def:function(d){return d===Number.POSITIVE_INFINITY},rt:$n[0].Boolean,p:[$n[0].Double],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Parse",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0}],tpc:0,def:function(s){return System.Double.parse(s)},rt:$n[0].Double,p:[$n[0].String],box:function($v){return H5.box($v,System.Double,System.Double.format,System.Double.getHashCode)}},{a:2,n:"Parse",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0},{n:"provider",pt:$n[0].IFormatProvider,ps:1}],tpc:0,def:function(s,provider){return H5.Int.parseFloat(s,provider)},rt:$n[0].Double,p:[$n[0].String,$n[0].IFormatProvider],box:function($v){return H5.box($v,System.Double,System.Double.format,System.Double.getHashCode)}},{a:2,n:"ToExponential",t:8,sn:"toExponential",rt:$n[0].String},{a:2,n:"ToExponential",t:8,pi:[{n:"fractionDigits",pt:$n[0].Int32,ps:0}],sn:"toExponential",rt:$n[0].String,p:[$n[0].Int32]},{a:2,n:"ToFixed",t:8,sn:"toFixed",rt:$n[0].String},{a:2,n:"ToFixed",t:8,pi:[{n:"fractionDigits",pt:$n[0].Int32,ps:0}],sn:"toFixed",rt:$n[0].String,p:[$n[0].Int32]},{a:2,n:"ToPrecision",t:8,sn:"toPrecision",rt:$n[0].String},{a:2,n:"ToPrecision",t:8,pi:[{n:"precision",pt:$n[0].Int32,ps:0}],sn:"toPrecision",rt:$n[0].String,p:[$n[0].Int32]},{ov:!0,a:2,n:"ToString",t:8,tpc:0,def:function(){return System.Double.format(this)},rt:$n[0].String},{a:2,n:"ToString",t:8,pi:[{n:"provider",pt:$n[0].IFormatProvider,ps:0}],tpc:0,def:function(provider){return System.Double.format(this,"G",provider)},rt:$n[0].String,p:[$n[0].IFormatProvider]},{a:2,n:"ToString",t:8,pi:[{n:"radix",pt:$n[0].Int32,ps:0}],sn:"toString",rt:$n[0].String,p:[$n[0].Int32]},{a:2,n:"ToString",t:8,pi:[{n:"format",pt:$n[0].String,ps:0}],tpc:0,def:function(format){return System.Double.format(this,format)},rt:$n[0].String,p:[$n[0].String]},{a:2,n:"ToString",t:8,pi:[{n:"format",pt:$n[0].String,ps:0},{n:"provider",pt:$n[0].IFormatProvider,ps:1}],tpc:0,def:function(format,provider){return System.Double.format(this,format,provider)},rt:$n[0].String,p:[$n[0].String,$n[0].IFormatProvider]},{a:2,n:"TryParse",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0},{n:"result",out:!0,pt:$n[0].Double,ps:1}],tpc:0,def:function(s,result){return System.Double.tryParse(s,null,result)},rt:$n[0].Boolean,p:[$n[0].String,$n[0].Double],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"TryParse",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0},{n:"provider",pt:$n[0].IFormatProvider,ps:1},{n:"result",out:!0,pt:$n[0].Double,ps:2}],tpc:0,def:function(s,provider,result){return System.Double.tryParse(s,provider,result)},rt:$n[0].Boolean,p:[$n[0].String,$n[0].IFormatProvider,$n[0].Double],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Epsilon",is:!0,t:4,rt:$n[0].Double,sn:"Epsilon",box:function($v){return H5.box($v,System.Double,System.Double.format,System.Double.getHashCode)}},{a:2,n:"MaxValue",is:!0,t:4,rt:$n[0].Double,sn:"MaxValue",box:function($v){return H5.box($v,System.Double,System.Double.format,System.Double.getHashCode)}},{a:2,n:"MinValue",is:!0,t:4,rt:$n[0].Double,sn:"MinValue",box:function($v){return H5.box($v,System.Double,System.Double.format,System.Double.getHashCode)}},{a:2,n:"NaN",is:!0,t:4,rt:$n[0].Double,sn:"NaN",box:function($v){return H5.box($v,System.Double,System.Double.format,System.Double.getHashCode)}},{a:2,n:"NegativeInfinity",is:!0,t:4,rt:$n[0].Double,sn:"NegativeInfinity",box:function($v){return H5.box($v,System.Double,System.Double.format,System.Double.getHashCode)}},{a:2,n:"PositiveInfinity",is:!0,t:4,rt:$n[0].Double,sn:"PositiveInfinity",box:function($v){return H5.box($v,System.Double,System.Double.format,System.Double.getHashCode)}}]}},$n);$m("System.Enum",function(){return{att:1048705,a:2,m:[{a:3,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:"CompareTo",t:8,pi:[{n:"target",pt:$n[0].Object,ps:0}],tpc:0,def:function(target){return H5.compare(this,target)},rt:$n[0].Int32,p:[$n[0].Object],box:function($v){return H5.box($v,System.Int32)}},{ov:!0,a:2,n:"Equals",t:8,pi:[{n:"other",pt:$n[0].Object,ps:0}],tpc:0,def:function(other){return System.Enum.equals(this,other,H5.getType(this))},rt:$n[0].Boolean,p:[$n[0].Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Format",is:!0,t:8,pi:[{n:"enumType",pt:$n[0].Type,ps:0},{n:"value",pt:$n[0].Object,ps:1},{n:"format",pt:$n[0].String,ps:2}],sn:"format",rt:$n[0].String,p:[$n[0].Type,$n[0].Object,$n[0].String]},{a:2,n:"GetName",is:!0,t:8,pi:[{n:"enumType",pt:$n[0].Type,ps:0},{n:"value",pt:$n[0].Object,ps:1}],sn:"getName",rt:$n[0].String,p:[$n[0].Type,$n[0].Object]},{a:2,n:"GetNames",is:!0,t:8,tpc:1,def:function(TEnum){return System.Enum.getNames(TEnum)},rt:$n[0].Array.type(System.String)},{a:2,n:"GetNames",is:!0,t:8,pi:[{n:"enumType",pt:$n[0].Type,ps:0}],sn:"getNames",rt:$n[0].Array.type(System.String),p:[$n[0].Type]},{a:2,n:"GetValues",is:!0,t:8,tpc:1,def:function(TEnum){return System.Enum.getValues(TEnum)},rt:System.Array.type(System.Object)},{a:2,n:"GetValues",is:!0,t:8,pi:[{n:"enumType",pt:$n[0].Type,ps:0}],sn:"getValues",rt:Array,p:[$n[0].Type]},{a:2,n:"HasFlag",t:8,pi:[{n:"flag",pt:$n[0].Enum,ps:0}],tpc:0,def:function(flag){return System.Enum.hasFlag(this,flag)},rt:$n[0].Boolean,p:[$n[0].Enum],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"IsDefined",is:!0,t:8,pi:[{n:"value",pt:System.Object,ps:0}],tpc:1,def:function(TEnum,value){return System.Enum.isDefined(TEnum,value)},rt:$n[0].Boolean,p:[System.Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"IsDefined",is:!0,t:8,pi:[{n:"enumType",pt:$n[0].Type,ps:0},{n:"value",pt:$n[0].Object,ps:1}],sn:"isDefined",rt:$n[0].Boolean,p:[$n[0].Type,$n[0].Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Parse",is:!0,t:8,pi:[{n:"value",pt:$n[0].String,ps:0}],tpc:1,def:function(TEnum,value){return System.Enum.parse(TEnum,value,result)},rt:System.Object,p:[$n[0].String]},{a:2,n:"Parse",is:!0,t:8,pi:[{n:"value",pt:$n[0].String,ps:0},{n:"ignoreCase",pt:$n[0].Boolean,ps:1}],tpc:1,def:function(TEnum,value,ignoreCase){return System.Enum.parse(TEnum,value,result)},rt:System.Object,p:[$n[0].String,$n[0].Boolean]},{a:2,n:"Parse",is:!0,t:8,pi:[{n:"enumType",pt:$n[0].Type,ps:0},{n:"value",pt:$n[0].String,ps:1}],sn:"parse",rt:$n[0].Object,p:[$n[0].Type,$n[0].String]},{a:2,n:"Parse",is:!0,t:8,pi:[{n:"enumType",pt:$n[0].Type,ps:0},{n:"value",pt:$n[0].String,ps:1},{n:"ignoreCase",pt:$n[0].Boolean,ps:2}],sn:"parse",rt:$n[0].Object,p:[$n[0].Type,$n[0].String,$n[0].Boolean]},{a:2,n:"ToObject",is:!0,t:8,pi:[{n:"enumType",pt:$n[0].Type,ps:0},{n:"value",pt:$n[0].Object,ps:1}],tpc:0,def:function(enumType,value){return System.Enum.toObject(enumType,value)},rt:$n[0].Object,p:[$n[0].Type,$n[0].Object]},{ov:!0,a:2,n:"ToString",t:8,tpc:0,def:function(){return System.Enum.toString(H5.getType(this),this)},rt:$n[0].String},{a:2,n:"ToString",t:8,pi:[{n:"format",pt:$n[0].String,ps:0}],tpc:0,def:function(format){return System.Enum.format(H5.getType(this),this,format)},rt:$n[0].String,p:[$n[0].String]},{a:2,n:"ToString",t:8,pi:[{n:"format",pt:$n[0].String,ps:0},{n:"formatProvider",pt:$n[0].IFormatProvider,ps:1}],tpc:0,def:function(format,formatProvider){return System.Enum.format(H5.getType(this),this,format)},rt:$n[0].String,p:[$n[0].String,$n[0].IFormatProvider]},{a:2,n:"ToString",is:!0,t:8,pi:[{n:"enumType",pt:$n[0].Type,ps:0},{n:"value",pt:$n[0].Enum,ps:1}],sn:"toString",rt:$n[0].String,p:[$n[0].Type,$n[0].Enum]},{a:2,n:"TryParse",is:!0,t:8,pi:[{n:"value",pt:$n[0].String,ps:0},{n:"result",out:!0,pt:System.Object,ps:1}],tpc:1,def:function(TEnum,value,result){return System.Enum.tryParse(TEnum,value,result)},rt:$n[0].Boolean,p:[$n[0].String,System.Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"TryParse",is:!0,t:8,pi:[{n:"value",pt:$n[0].String,ps:0},{n:"ignoreCase",pt:$n[0].Boolean,ps:1},{n:"result",out:!0,pt:System.Object,ps:2}],tpc:1,def:function(TEnum,value,ignoreCase,result){return System.Enum.tryParse(TEnum,value,result,ignoreCase)},rt:$n[0].Boolean,p:[$n[0].String,$n[0].Boolean,System.Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}}]}},$n);$m("System.Environment",function(){return{nested:[System.Object,System.Object],att:385,a:2,s:!0,m:[{n:".cctor",t:1,sn:"ctor",sm:!0},{a:2,n:"Exit",is:!0,t:8,pi:[{n:"exitCode",pt:$n[0].Int32,ps:0}],sn:"Exit",rt:$n[0].Void,p:[$n[0].Int32]},{a:2,n:"ExpandEnvironmentVariables",is:!0,t:8,pi:[{n:"name",pt:$n[0].String,ps:0}],sn:"ExpandEnvironmentVariables",rt:$n[0].String,p:[$n[0].String]},{a:2,n:"FailFast",is:!0,t:8,pi:[{n:"message",pt:$n[0].String,ps:0}],sn:"FailFast",rt:$n[0].Void,p:[$n[0].String]},{a:2,n:"FailFast",is:!0,t:8,pi:[{n:"message",pt:$n[0].String,ps:0},{n:"exception",pt:$n[0].Exception,ps:1}],sn:"FailFast$1",rt:$n[0].Void,p:[$n[0].String,$n[0].Exception]},{a:2,n:"GetCommandLineArgs",is:!0,t:8,sn:"GetCommandLineArgs",rt:$n[0].Array.type(System.String)},{a:2,n:"GetEnvironmentVariable",is:!0,t:8,pi:[{n:"variable",pt:$n[0].String,ps:0}],sn:"GetEnvironmentVariable",rt:$n[0].String,p:[$n[0].String]},{a:2,n:"GetEnvironmentVariable",is:!0,t:8,pi:[{n:"variable",pt:$n[0].String,ps:0},{n:"target",pt:$n[0].EnvironmentVariableTarget,ps:1}],sn:"GetEnvironmentVariable$1",rt:$n[0].String,p:[$n[0].String,$n[0].EnvironmentVariableTarget]},{a:2,n:"GetEnvironmentVariables",is:!0,t:8,sn:"GetEnvironmentVariables",rt:$n[6].IDictionary},{a:2,n:"GetEnvironmentVariables",is:!0,t:8,pi:[{n:"target",pt:$n[0].EnvironmentVariableTarget,ps:0}],sn:"GetEnvironmentVariables$1",rt:$n[6].IDictionary,p:[$n[0].EnvironmentVariableTarget]},{a:2,n:"GetFolderPath",is:!0,t:8,pi:[{n:"folder",pt:System.Object,ps:0}],tpc:0,def:function(folder){return""},rt:$n[0].String,p:[System.Object]},{a:2,n:"GetFolderPath",is:!0,t:8,pi:[{n:"folder",pt:System.Object,ps:0},{n:"option",pt:System.Object,ps:1}],tpc:0,def:function(folder,option){return""},rt:$n[0].String,p:[System.Object,System.Object]},{a:2,n:"GetLogicalDrives",is:!0,t:8,sn:"GetLogicalDrives",rt:$n[0].Array.type(System.String)},{a:4,n:"GetResourceString",is:!0,t:8,pi:[{n:"key",pt:$n[0].String,ps:0}],sn:"GetResourceString",rt:$n[0].String,p:[$n[0].String]},{a:4,n:"GetResourceString",is:!0,t:8,pi:[{n:"key",pt:$n[0].String,ps:0},{n:"values",ip:!0,pt:$n[0].Array.type(System.Object),ps:1}],sn:"GetResourceString$1",rt:$n[0].String,p:[$n[0].String,$n[0].Array.type(System.Object)]},{a:1,n:"PatchDictionary",is:!0,t:8,pi:[{n:"d",pt:$n[3].Dictionary$2(System.String,System.String),ps:0}],sn:"PatchDictionary",rt:$n[3].Dictionary$2(System.String,System.String),p:[$n[3].Dictionary$2(System.String,System.String)]},{a:2,n:"SetEnvironmentVariable",is:!0,t:8,pi:[{n:"variable",pt:$n[0].String,ps:0},{n:"value",pt:$n[0].String,ps:1}],sn:"SetEnvironmentVariable",rt:$n[0].Void,p:[$n[0].String,$n[0].String]},{a:2,n:"SetEnvironmentVariable",is:!0,t:8,pi:[{n:"variable",pt:$n[0].String,ps:0},{n:"value",pt:$n[0].String,ps:1},{n:"target",pt:$n[0].EnvironmentVariableTarget,ps:2}],sn:"SetEnvironmentVariable$1",rt:$n[0].Void,p:[$n[0].String,$n[0].String,$n[0].EnvironmentVariableTarget]},{a:2,n:"CommandLine",is:!0,t:16,rt:$n[0].String,g:{a:2,n:"get_CommandLine",t:8,rt:$n[0].String,fg:"CommandLine",is:!0},fn:"CommandLine"},{a:2,n:"CurrentDirectory",is:!0,t:16,rt:$n[0].String,g:{a:2,n:"get_CurrentDirectory",t:8,rt:$n[0].String,fg:"CurrentDirectory",is:!0},s:{a:2,n:"set_CurrentDirectory",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"CurrentDirectory",is:!0},fn:"CurrentDirectory"},{a:2,n:"CurrentManagedThreadId",is:!0,t:16,rt:$n[0].Int32,g:{a:2,n:"get_CurrentManagedThreadId",is:!0,t:8,tpc:0,def:function(){return 0},rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}}},{a:2,n:"ExitCode",is:!0,t:16,rt:$n[0].Int32,g:{a:2,n:"get_ExitCode",t:8,rt:$n[0].Int32,fg:"ExitCode",is:!0,box:function($v){return H5.box($v,System.Int32)}},s:{a:2,n:"set_ExitCode",t:8,p:[$n[0].Int32],rt:$n[0].Void,fs:"ExitCode",is:!0},fn:"ExitCode"},{a:1,n:"Global",is:!0,t:16,rt:System.Object,g:{a:1,n:"get_Global",is:!0,t:8,tpc:0,def:function(){return H5.global},rt:System.Object}},{a:2,n:"HasShutdownStarted",is:!0,t:16,rt:$n[0].Boolean,g:{a:2,n:"get_HasShutdownStarted",is:!0,t:8,tpc:0,def:function(){return!1},rt:$n[0].Boolean,box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}}},{a:2,n:"Is64BitOperatingSystem",is:!0,t:16,rt:$n[0].Boolean,g:{a:2,n:"get_Is64BitOperatingSystem",t:8,rt:$n[0].Boolean,fg:"Is64BitOperatingSystem",is:!0,box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},fn:"Is64BitOperatingSystem"},{a:2,n:"Is64BitProcess",is:!0,t:16,rt:$n[0].Boolean,g:{a:2,n:"get_Is64BitProcess",is:!0,t:8,tpc:0,def:function(){return!1},rt:$n[0].Boolean,box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}}},{a:1,n:"Location",is:!0,t:16,rt:System.Object,g:{a:1,n:"get_Location",t:8,rt:System.Object,fg:"Location",is:!0},fn:"Location"},{a:2,n:"MachineName",is:!0,t:16,rt:$n[0].String,g:{a:2,n:"get_MachineName",is:!0,t:8,tpc:0,def:function(){return""},rt:$n[0].String}},{a:2,n:"NewLine",is:!0,t:16,rt:$n[0].String,g:{a:2,n:"get_NewLine",is:!0,t:8,tpc:0,def:function(){return"\n"},rt:$n[0].String}},{a:2,n:"OSVersion",is:!0,t:16,rt:$n[0].Object,g:{a:2,n:"get_OSVersion",is:!0,t:8,tpc:0,def:function(){return null},rt:$n[0].Object}},{a:2,n:"ProcessorCount",is:!0,t:16,rt:$n[0].Int32,g:{a:2,n:"get_ProcessorCount",t:8,rt:$n[0].Int32,fg:"ProcessorCount",is:!0,box:function($v){return H5.box($v,System.Int32)}},fn:"ProcessorCount"},{a:2,n:"StackTrace",is:!0,t:16,rt:$n[0].String,g:{a:2,n:"get_StackTrace",t:8,rt:$n[0].String,fg:"StackTrace",is:!0},fn:"StackTrace"},{a:2,n:"SystemDirectory",is:!0,t:16,rt:$n[0].String,g:{a:2,n:"get_SystemDirectory",is:!0,t:8,tpc:0,def:function(){return""},rt:$n[0].String}},{a:2,n:"SystemPageSize",is:!0,t:16,rt:$n[0].Int32,g:{a:2,n:"get_SystemPageSize",is:!0,t:8,tpc:0,def:function(){return 1},rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}}},{a:2,n:"TickCount",is:!0,t:16,rt:$n[0].Int32,g:{a:2,n:"get_TickCount",is:!0,t:8,tpc:0,def:function(){return Date.now()},rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}}},{a:2,n:"UserDomainName",is:!0,t:16,rt:$n[0].String,g:{a:2,n:"get_UserDomainName",is:!0,t:8,tpc:0,def:function(){return""},rt:$n[0].String}},{a:2,n:"UserInteractive",is:!0,t:16,rt:$n[0].Boolean,g:{a:2,n:"get_UserInteractive",is:!0,t:8,tpc:0,def:function(){return!0},rt:$n[0].Boolean,box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}}},{a:2,n:"UserName",is:!0,t:16,rt:$n[0].String,g:{a:2,n:"get_UserName",is:!0,t:8,tpc:0,def:function(){return""},rt:$n[0].String}},{a:2,n:"Version",is:!0,t:16,rt:$n[0].Version,g:{a:2,n:"get_Version",t:8,rt:$n[0].Version,fg:"Version",is:!0},fn:"Version"},{a:2,n:"WorkingSet",is:!0,t:16,rt:$n[0].Int64,g:{a:2,n:"get_WorkingSet",is:!0,t:8,tpc:0,def:function(){return System.Int64(0)},rt:$n[0].Int64}},{a:1,n:"Variables",is:!0,t:4,rt:$n[3].Dictionary$2(System.String,System.String),sn:"Variables"},{a:1,n:"__Property__Initializer__ExitCode",is:!0,t:4,rt:$n[0].Int32,sn:"__Property__Initializer__ExitCode",box:function($v){return H5.box($v,System.Int32)}},{a:1,backing:!0,n:"k__BackingField",is:!0,t:4,rt:$n[0].Int32,sn:"CurrentManagedThreadId",box:function($v){return H5.box($v,System.Int32)}},{a:1,backing:!0,n:"k__BackingField",is:!0,t:4,rt:$n[0].Int32,sn:"ExitCode",box:function($v){return H5.box($v,System.Int32)}},{a:1,backing:!0,n:"k__BackingField",is:!0,t:4,rt:System.Object,sn:"Global"},{a:1,backing:!0,n:"k__BackingField",is:!0,t:4,rt:$n[0].Boolean,sn:"HasShutdownStarted",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,backing:!0,n:"k__BackingField",is:!0,t:4,rt:$n[0].Boolean,sn:"Is64BitProcess",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,backing:!0,n:"k__BackingField",is:!0,t:4,rt:$n[0].String,sn:"MachineName"},{a:1,backing:!0,n:"k__BackingField",is:!0,t:4,rt:$n[0].String,sn:"NewLine"},{a:1,backing:!0,n:"k__BackingField",is:!0,t:4,rt:$n[0].Object,sn:"OSVersion"},{a:1,backing:!0,n:"k__BackingField",is:!0,t:4,rt:$n[0].String,sn:"SystemDirectory"},{a:1,backing:!0,n:"k__BackingField",is:!0,t:4,rt:$n[0].Int32,sn:"SystemPageSize",box:function($v){return H5.box($v,System.Int32)}},{a:1,backing:!0,n:"k__BackingField",is:!0,t:4,rt:$n[0].Int32,sn:"TickCount",box:function($v){return H5.box($v,System.Int32)}},{a:1,backing:!0,n:"k__BackingField",is:!0,t:4,rt:$n[0].String,sn:"UserDomainName"},{a:1,backing:!0,n:"k__BackingField",is:!0,t:4,rt:$n[0].Boolean,sn:"UserInteractive",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,backing:!0,n:"k__BackingField",is:!0,t:4,rt:$n[0].String,sn:"UserName"},{a:1,backing:!0,n:"k__BackingField",is:!0,t:4,rt:$n[0].Int64,sn:"WorkingSet"}]}},$n);$m("System.Exception",function(){return{att:1048577,a:2,m:[{a:2,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].String],pi:[{n:"message",pt:$n[0].String,ps:0}],sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[0].Exception],pi:[{n:"message",pt:$n[0].String,ps:0},{n:"innerException",pt:$n[0].Exception,ps:1}],sn:"ctor"},{v:!0,a:2,n:"GetBaseException",t:8,sn:"getBaseException",rt:$n[0].Exception},{v:!0,a:2,n:"Data",t:16,rt:$n[3].IDictionary$2(System.Object,System.Object),g:{v:!0,a:2,n:"get_Data",t:8,rt:$n[3].IDictionary$2(System.Object,System.Object),fg:"Data"},fn:"Data"},{a:2,n:"HResult",t:16,rt:$n[0].Int32,g:{a:2,n:"get_HResult",t:8,rt:$n[0].Int32,fg:"HResult",box:function($v){return H5.box($v,System.Int32)}},s:{a:3,n:"set_HResult",t:8,p:[$n[0].Int32],rt:$n[0].Void,fs:"HResult"},fn:"HResult"},{v:!0,a:2,n:"InnerException",t:16,rt:$n[0].Exception,g:{v:!0,a:2,n:"get_InnerException",t:8,rt:$n[0].Exception,fg:"InnerException"},fn:"InnerException"},{v:!0,a:2,n:"Message",t:16,rt:$n[0].String,g:{v:!0,a:2,n:"get_Message",t:8,rt:$n[0].String,fg:"Message"},fn:"Message"},{v:!0,a:2,n:"StackTrace",t:16,rt:$n[0].String,g:{v:!0,a:2,n:"get_StackTrace",t:8,rt:$n[0].String,fg:"StackTrace"},fn:"StackTrace"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[3].IDictionary$2(System.Object,System.Object),sn:"Data"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Int32,sn:"HResult",box:function($v){return H5.box($v,System.Int32)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Exception,sn:"InnerException"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"Message"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"StackTrace"}]}},$n);$m("System.Guid",function(){return{att:1048841,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].Array.type(System.Byte)],pi:[{n:"b",pt:$n[0].Array.type(System.Byte),ps:0}],sn:"$ctor1"},{a:2,n:".ctor",t:1,p:[$n[0].String],pi:[{n:"uuid",pt:$n[0].String,ps:0}],sn:"$ctor4"},{a:2,n:".ctor",t:1,p:[$n[0].Int32,$n[0].Int16,$n[0].Int16,$n[0].Array.type(System.Byte)],pi:[{n:"a",pt:$n[0].Int32,ps:0},{n:"b",pt:$n[0].Int16,ps:1},{n:"c",pt:$n[0].Int16,ps:2},{n:"d",pt:$n[0].Array.type(System.Byte),ps:3}],sn:"$ctor3"},{a:2,n:".ctor",t:1,p:[$n[0].Int32,$n[0].Int16,$n[0].Int16,$n[0].Byte,$n[0].Byte,$n[0].Byte,$n[0].Byte,$n[0].Byte,$n[0].Byte,$n[0].Byte,$n[0].Byte],pi:[{n:"a",pt:$n[0].Int32,ps:0},{n:"b",pt:$n[0].Int16,ps:1},{n:"c",pt:$n[0].Int16,ps:2},{n:"d",pt:$n[0].Byte,ps:3},{n:"e",pt:$n[0].Byte,ps:4},{n:"f",pt:$n[0].Byte,ps:5},{n:"g",pt:$n[0].Byte,ps:6},{n:"h",pt:$n[0].Byte,ps:7},{n:"i",pt:$n[0].Byte,ps:8},{n:"j",pt:$n[0].Byte,ps:9},{n:"k",pt:$n[0].Byte,ps:10}],sn:"$ctor2"},{a:2,n:".ctor",t:1,p:[$n[0].UInt32,$n[0].UInt16,$n[0].UInt16,$n[0].Byte,$n[0].Byte,$n[0].Byte,$n[0].Byte,$n[0].Byte,$n[0].Byte,$n[0].Byte,$n[0].Byte],pi:[{n:"a",pt:$n[0].UInt32,ps:0},{n:"b",pt:$n[0].UInt16,ps:1},{n:"c",pt:$n[0].UInt16,ps:2},{n:"d",pt:$n[0].Byte,ps:3},{n:"e",pt:$n[0].Byte,ps:4},{n:"f",pt:$n[0].Byte,ps:5},{n:"g",pt:$n[0].Byte,ps:6},{n:"h",pt:$n[0].Byte,ps:7},{n:"i",pt:$n[0].Byte,ps:8},{n:"j",pt:$n[0].Byte,ps:9},{n:"k",pt:$n[0].Byte,ps:10}],sn:"$ctor5"},{a:2,n:"CompareTo",t:8,pi:[{n:"value",pt:$n[0].Guid,ps:0}],sn:"compareTo",rt:$n[0].Int32,p:[$n[0].Guid],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"Equals",t:8,pi:[{n:"o",pt:$n[0].Guid,ps:0}],sn:"equalsT",rt:$n[0].Boolean,p:[$n[0].Guid],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ov:!0,a:2,n:"Equals",t:8,pi:[{n:"o",pt:$n[0].Object,ps:0}],sn:"equals",rt:$n[0].Boolean,p:[$n[0].Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"Format",t:8,pi:[{n:"format",pt:$n[0].String,ps:0}],sn:"Format",rt:$n[0].String,p:[$n[0].String]},{a:1,n:"FromString",t:8,pi:[{n:"s",pt:$n[0].String,ps:0}],sn:"FromString",rt:$n[0].Void,p:[$n[0].String]},{ov:!0,a:2,n:"GetHashCode",t:8,sn:"getHashCode",rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"NewGuid",is:!0,t:8,sn:"NewGuid",rt:$n[0].Guid},{a:2,n:"Parse",is:!0,t:8,pi:[{n:"input",pt:$n[0].String,ps:0}],sn:"Parse",rt:$n[0].Guid,p:[$n[0].String]},{a:2,n:"ParseExact",is:!0,t:8,pi:[{n:"input",pt:$n[0].String,ps:0},{n:"format",pt:$n[0].String,ps:1}],sn:"ParseExact",rt:$n[0].Guid,p:[$n[0].String,$n[0].String]},{a:1,n:"ParseInternal",t:8,pi:[{n:"input",pt:$n[0].String,ps:0},{n:"format",pt:$n[0].String,ps:1},{n:"check",pt:$n[0].Boolean,ps:2}],sn:"ParseInternal",rt:$n[0].Boolean,p:[$n[0].String,$n[0].String,$n[0].Boolean],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"ToByteArray",t:8,sn:"ToByteArray",rt:$n[0].Array.type(System.Byte)},{a:1,n:"ToHex",is:!0,t:8,pi:[{n:"x",pt:$n[0].Byte,ps:0}],sn:"ToHex",rt:$n[0].String,p:[$n[0].Byte]},{a:1,n:"ToHex",is:!0,t:8,pi:[{n:"x",pt:$n[0].UInt32,ps:0},{n:"precision",pt:$n[0].Int32,ps:1}],sn:"ToHex$1",rt:$n[0].String,p:[$n[0].UInt32,$n[0].Int32]},{ov:!0,a:2,n:"ToString",t:8,sn:"toString",rt:$n[0].String},{a:2,n:"ToString",t:8,pi:[{n:"format",pt:$n[0].String,ps:0}],sn:"ToString",rt:$n[0].String,p:[$n[0].String]},{a:2,n:"ToString",t:8,pi:[{n:"format",pt:$n[0].String,ps:0},{n:"formatProvider",pt:$n[0].IFormatProvider,ps:1}],sn:"format",rt:$n[0].String,p:[$n[0].String,$n[0].IFormatProvider]},{a:2,n:"TryParse",is:!0,t:8,pi:[{n:"input",pt:$n[0].String,ps:0},{n:"result",out:!0,pt:$n[0].Guid,ps:1}],sn:"TryParse",rt:$n[0].Boolean,p:[$n[0].String,$n[0].Guid],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"TryParseExact",is:!0,t:8,pi:[{n:"input",pt:$n[0].String,ps:0},{n:"format",pt:$n[0].String,ps:1},{n:"result",out:!0,pt:$n[0].Guid,ps:2}],sn:"TryParseExact",rt:$n[0].Boolean,p:[$n[0].String,$n[0].String,$n[0].Guid],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"op_Equality",is:!0,t:8,pi:[{n:"a",pt:$n[0].Guid,ps:0},{n:"b",pt:$n[0].Guid,ps:1}],sn:"op_Equality",rt:$n[0].Boolean,p:[$n[0].Guid,$n[0].Guid],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"op_Inequality",is:!0,t:8,pi:[{n:"a",pt:$n[0].Guid,ps:0},{n:"b",pt:$n[0].Guid,ps:1}],sn:"op_Inequality",rt:$n[0].Boolean,p:[$n[0].Guid,$n[0].Guid],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"toJSON",t:8,sn:"toJSON",rt:$n[0].String},{a:2,n:"Empty",is:!0,t:4,rt:$n[0].Guid,sn:"Empty",ro:!0},{a:1,n:"NonFormat",is:!0,t:4,rt:RegExp,sn:"NonFormat",ro:!0},{a:1,n:"Replace",is:!0,t:4,rt:RegExp,sn:"Replace",ro:!0},{a:1,n:"Rnd",is:!0,t:4,rt:$n[0].Random,sn:"Rnd",ro:!0},{a:1,n:"Split",is:!0,t:4,rt:RegExp,sn:"Split",ro:!0},{a:1,n:"Valid",is:!0,t:4,rt:RegExp,sn:"Valid",ro:!0},{a:1,n:"_a",t:4,rt:$n[0].Int32,sn:"_a",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"_b",t:4,rt:$n[0].Int16,sn:"_b",box:function($v){return H5.box($v,System.Int16)}},{a:1,n:"_c",t:4,rt:$n[0].Int16,sn:"_c",box:function($v){return H5.box($v,System.Int16)}},{a:1,n:"_d",t:4,rt:$n[0].Byte,sn:"_d",box:function($v){return H5.box($v,System.Byte)}},{a:1,n:"_e",t:4,rt:$n[0].Byte,sn:"_e",box:function($v){return H5.box($v,System.Byte)}},{a:1,n:"_f",t:4,rt:$n[0].Byte,sn:"_f",box:function($v){return H5.box($v,System.Byte)}},{a:1,n:"_g",t:4,rt:$n[0].Byte,sn:"_g",box:function($v){return H5.box($v,System.Byte)}},{a:1,n:"_h",t:4,rt:$n[0].Byte,sn:"_h",box:function($v){return H5.box($v,System.Byte)}},{a:1,n:"_i",t:4,rt:$n[0].Byte,sn:"_i",box:function($v){return H5.box($v,System.Byte)}},{a:1,n:"_j",t:4,rt:$n[0].Byte,sn:"_j",box:function($v){return H5.box($v,System.Byte)}},{a:1,n:"_k",t:4,rt:$n[0].Byte,sn:"_k",box:function($v){return H5.box($v,System.Byte)}},{a:1,n:"error1",is:!0,t:4,rt:$n[0].String,sn:"error1"}]}},$n);$m("System.IAsyncResult",function(){return{att:1048737,a:2,m:[{ab:!0,a:2,n:"AsyncState",t:16,rt:$n[0].Object,g:{ab:!0,a:2,n:"get_AsyncState",t:8,rt:$n[0].Object,fg:"System$IAsyncResult$AsyncState"},fn:"System$IAsyncResult$AsyncState"},{ab:!0,a:2,n:"CompletedSynchronously",t:16,rt:$n[0].Boolean,g:{ab:!0,a:2,n:"get_CompletedSynchronously",t:8,rt:$n[0].Boolean,fg:"System$IAsyncResult$CompletedSynchronously",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},fn:"System$IAsyncResult$CompletedSynchronously"},{ab:!0,a:2,n:"IsCompleted",t:16,rt:$n[0].Boolean,g:{ab:!0,a:2,n:"get_IsCompleted",t:8,rt:$n[0].Boolean,fg:"System$IAsyncResult$IsCompleted",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},fn:"System$IAsyncResult$IsCompleted"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Object,sn:"System$IAsyncResult$AsyncState"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Boolean,sn:"System$IAsyncResult$CompletedSynchronously",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Boolean,sn:"System$IAsyncResult$IsCompleted",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}}]}},$n);$m("System.ICloneable",function(){return{att:1048737,a:2,m:[{ab:!0,a:2,n:"Clone",t:8,tpc:0,def:function(){return H5.clone(this)},rt:$n[0].Object}]}},$n);$m("System.IComparable",function(){return{att:1048737,a:2,m:[{ab:!0,a:2,n:"CompareTo",t:8,pi:[{n:"obj",pt:$n[0].Object,ps:0}],tpc:0,def:function(obj){return H5.compare(this,obj)},rt:$n[0].Int32,p:[$n[0].Object],box:function($v){return H5.box($v,System.Int32)}}]}},$n);$m("System.IComparable$1",function(T){return{att:1048737,a:2,m:[{ab:!0,a:2,n:"CompareTo",t:8,pi:[{n:"other",pt:T,ps:0}],tpc:0,def:function(other){return H5.compare(this,other,!1,T)},rt:$n[0].Int32,p:[T],box:function($v){return H5.box($v,System.Int32)}}]}},$n);$m("System.IDisposable",function(){return{att:1048737,a:2,m:[{ab:!0,a:2,n:"Dispose",t:8,sn:"System$IDisposable$Dispose",rt:$n[0].Void}]}},$n);$m("System.IEquatable$1",function(T){return{att:1048737,a:2,m:[{ab:!0,a:2,n:"Equals",t:8,pi:[{n:"other",pt:T,ps:0}],tpc:0,def:function(other){return H5.equalsT(this,other,T)},rt:$n[0].Boolean,p:[T],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}}]}},$n);$m("System.IFormatProvider",function(){return{att:1048737,a:2,m:[{ab:!0,a:2,n:"GetFormat",t:8,pi:[{n:"formatType",pt:$n[0].Type,ps:0}],sn:"System$IFormatProvider$getFormat",rt:$n[0].Object,p:[$n[0].Type]}]}},$n);$m("System.IFormattable",function(){return{att:1048737,a:2,m:[{ab:!0,a:2,n:"ToString",t:8,pi:[{n:"format",pt:$n[0].String,ps:0},{n:"formatProvider",pt:$n[0].IFormatProvider,ps:1}],tpc:0,def:function(format,formatProvider){return H5.format(this,format,formatProvider)},rt:$n[0].String,p:[$n[0].String,$n[0].IFormatProvider]}]}},$n);$m("System.Index",function(){return{att:1048841,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].Int32,$n[0].Boolean],pi:[{n:"value",pt:$n[0].Int32,ps:0},{n:"fromEnd",dv:!1,o:!0,pt:$n[0].Boolean,ps:1}],sn:"$ctor1"},{a:2,n:"Equals",t:8,pi:[{n:"other",pt:$n[0].Index,ps:0}],sn:"equalsT",rt:$n[0].Boolean,p:[$n[0].Index],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ov:!0,a:2,n:"Equals",t:8,pi:[{n:"value",pt:$n[0].Object,ps:0}],sn:"equals",rt:$n[0].Boolean,p:[$n[0].Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"FromEnd",is:!0,t:8,pi:[{n:"value",pt:$n[0].Int32,ps:0}],sn:"FromEnd",rt:$n[0].Index,p:[$n[0].Int32]},{a:2,n:"FromStart",is:!0,t:8,pi:[{n:"value",pt:$n[0].Int32,ps:0}],sn:"FromStart",rt:$n[0].Index,p:[$n[0].Int32]},{ov:!0,a:2,n:"GetHashCode",t:8,sn:"getHashCode",rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"GetOffset",t:8,pi:[{n:"length",pt:$n[0].Int32,ps:0}],sn:"GetOffset",rt:$n[0].Int32,p:[$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{ov:!0,a:2,n:"ToString",t:8,sn:"toString",rt:$n[0].String},{a:2,n:"op_Implicit",is:!0,t:8,pi:[{n:"value",pt:$n[0].Int32,ps:0}],sn:"op_Implicit",rt:$n[0].Index,p:[$n[0].Int32]},{a:2,n:"End",is:!0,t:16,rt:$n[0].Index,g:{a:2,n:"get_End",t:8,rt:$n[0].Index,fg:"End",is:!0},fn:"End"},{a:2,n:"IsFromEnd",t:16,rt:$n[0].Boolean,g:{a:2,n:"get_IsFromEnd",t:8,rt:$n[0].Boolean,fg:"IsFromEnd",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},fn:"IsFromEnd"},{a:2,n:"Start",is:!0,t:16,rt:$n[0].Index,g:{a:2,n:"get_Start",t:8,rt:$n[0].Index,fg:"Start",is:!0},fn:"Start"},{a:2,n:"Value",t:16,rt:$n[0].Int32,g:{a:2,n:"get_Value",t:8,rt:$n[0].Int32,fg:"Value",box:function($v){return H5.box($v,System.Int32)}},fn:"Value"},{a:1,n:"_value",t:4,rt:$n[0].Int32,sn:"_value",ro:!0,box:function($v){return H5.box($v,System.Int32)}}]}},$n);$m("System.Int16",function(){return{att:1048841,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,def:function(){return Number}},{a:1,n:".ctor",t:1,p:[$n[0].Int32],pi:[{n:"i",pt:$n[0].Int32,ps:0}],def:function(i){return Number}},{a:2,n:"CompareTo",t:8,pi:[{n:"other",pt:$n[0].Int16,ps:0}],tpc:0,def:function(other){return H5.compare(this,other)},rt:$n[0].Int32,p:[$n[0].Int16],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"CompareTo",t:8,pi:[{n:"obj",pt:$n[0].Object,ps:0}],tpc:0,def:function(obj){return H5.compare(this,obj)},rt:$n[0].Int32,p:[$n[0].Object],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"Equals",t:8,pi:[{n:"other",pt:$n[0].Int16,ps:0}],tpc:0,def:function(other){return this===other},rt:$n[0].Boolean,p:[$n[0].Int16],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ov:!0,a:2,n:"Equals",t:8,pi:[{n:"other",pt:$n[0].Object,ps:0}],tpc:0,def:function(other){return System.Int16.equals(this,other)},rt:$n[0].Boolean,p:[$n[0].Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Format",t:8,pi:[{n:"format",pt:$n[0].String,ps:0}],tpc:0,def:function(format){return System.Int16.format(this,format)},rt:$n[0].String,p:[$n[0].String]},{a:2,n:"Format",t:8,pi:[{n:"format",pt:$n[0].String,ps:0},{n:"provider",pt:$n[0].IFormatProvider,ps:1}],tpc:0,def:function(format,provider){return System.Int16.format(this,format,provider)},rt:$n[0].String,p:[$n[0].String,$n[0].IFormatProvider]},{a:2,n:"Parse",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0}],tpc:0,def:function(s){return System.Int16.parse(s)},rt:$n[0].Int16,p:[$n[0].String],box:function($v){return H5.box($v,System.Int16)}},{a:2,n:"Parse",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0},{n:"radix",pt:$n[0].Int32,ps:1}],tpc:0,def:function(s,radix){return System.Int16.parse(s,radix)},rt:$n[0].Int16,p:[$n[0].String,$n[0].Int32],box:function($v){return H5.box($v,System.Int16)}},{a:2,n:"ToString",t:8,pi:[{n:"radix",pt:$n[0].Int32,ps:0}],sn:"toString",rt:$n[0].String,p:[$n[0].Int32]},{a:2,n:"ToString",t:8,pi:[{n:"format",pt:$n[0].String,ps:0}],tpc:0,def:function(format){return System.Int16.format(this,format)},rt:$n[0].String,p:[$n[0].String]},{a:2,n:"ToString",t:8,pi:[{n:"format",pt:$n[0].String,ps:0},{n:"provider",pt:$n[0].IFormatProvider,ps:1}],tpc:0,def:function(format,provider){return System.Int16.format(this,format,provider)},rt:$n[0].String,p:[$n[0].String,$n[0].IFormatProvider]},{a:2,n:"TryParse",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0},{n:"result",out:!0,pt:$n[0].Int16,ps:1}],tpc:0,def:function(s,result){return System.Int16.tryParse(s,result)},rt:$n[0].Boolean,p:[$n[0].String,$n[0].Int16],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"TryParse",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0},{n:"result",out:!0,pt:$n[0].Int16,ps:1},{n:"radix",pt:$n[0].Int32,ps:2}],tpc:0,def:function(s,result,radix){return System.Int16.tryParse(s,result,radix)},rt:$n[0].Boolean,p:[$n[0].String,$n[0].Int16,$n[0].Int32],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"MaxValue",is:!0,t:4,rt:$n[0].Int16,sn:"MaxValue",box:function($v){return H5.box($v,System.Int16)}},{a:2,n:"MinValue",is:!0,t:4,rt:$n[0].Int16,sn:"MinValue",box:function($v){return H5.box($v,System.Int16)}}]}},$n);$m("System.Int32",function(){return{att:1048841,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,def:function(){return Number}},{a:1,n:".ctor",t:1,p:[$n[0].Int32],pi:[{n:"i",pt:$n[0].Int32,ps:0}],def:function(i){return Number}},{a:2,n:"CompareTo",t:8,pi:[{n:"other",pt:$n[0].Int32,ps:0}],tpc:0,def:function(other){return H5.compare(this,other)},rt:$n[0].Int32,p:[$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"CompareTo",t:8,pi:[{n:"obj",pt:$n[0].Object,ps:0}],tpc:0,def:function(obj){return H5.compare(this,obj)},rt:$n[0].Int32,p:[$n[0].Object],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"Equals",t:8,pi:[{n:"other",pt:$n[0].Int32,ps:0}],tpc:0,def:function(other){return this===other},rt:$n[0].Boolean,p:[$n[0].Int32],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ov:!0,a:2,n:"Equals",t:8,pi:[{n:"other",pt:$n[0].Object,ps:0}],tpc:0,def:function(other){return System.Int32.equals(this,other)},rt:$n[0].Boolean,p:[$n[0].Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Format",t:8,pi:[{n:"format",pt:$n[0].String,ps:0}],tpc:0,def:function(format){return System.Int32.format(this,format)},rt:$n[0].String,p:[$n[0].String]},{a:2,n:"Format",t:8,pi:[{n:"format",pt:$n[0].String,ps:0},{n:"provider",pt:$n[0].IFormatProvider,ps:1}],tpc:0,def:function(format,provider){return System.Int32.format(this,format,provider)},rt:$n[0].String,p:[$n[0].String,$n[0].IFormatProvider]},{a:2,n:"Parse",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0}],tpc:0,def:function(s){return System.Int32.parse(s)},rt:$n[0].Int32,p:[$n[0].String],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"Parse",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0},{n:"radix",pt:$n[0].Int32,ps:1}],tpc:0,def:function(s,radix){return System.Int32.parse(s,radix)},rt:$n[0].Int32,p:[$n[0].String,$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"ToString",t:8,pi:[{n:"radix",pt:$n[0].Int32,ps:0}],sn:"toString",rt:$n[0].String,p:[$n[0].Int32]},{a:2,n:"ToString",t:8,pi:[{n:"format",pt:$n[0].String,ps:0}],tpc:0,def:function(format){return System.Int32.format(this,format)},rt:$n[0].String,p:[$n[0].String]},{a:2,n:"ToString",t:8,pi:[{n:"format",pt:$n[0].String,ps:0},{n:"provider",pt:$n[0].IFormatProvider,ps:1}],tpc:0,def:function(format,provider){return System.Int32.format(this,format,provider)},rt:$n[0].String,p:[$n[0].String,$n[0].IFormatProvider]},{a:2,n:"TryParse",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0},{n:"result",out:!0,pt:$n[0].Int32,ps:1}],tpc:0,def:function(s,result){return System.Int32.tryParse(s,result)},rt:$n[0].Boolean,p:[$n[0].String,$n[0].Int32],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"TryParse",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0},{n:"result",out:!0,pt:$n[0].Int32,ps:1},{n:"radix",pt:$n[0].Int32,ps:2}],tpc:0,def:function(s,result,radix){return System.Int32.tryParse(s,result,radix)},rt:$n[0].Boolean,p:[$n[0].String,$n[0].Int32,$n[0].Int32],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"MaxValue",is:!0,t:4,rt:$n[0].Int32,sn:"MaxValue",box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"MinValue",is:!0,t:4,rt:$n[0].Int32,sn:"MinValue",box:function($v){return H5.box($v,System.Int32)}}]}},$n);$m("System.Int64",function(){return{att:1048841,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:1,n:".ctor",t:1,p:[$n[0].Int32],pi:[{n:"i",pt:$n[0].Int32,ps:0}],sn:"ctor"},{a:2,n:"CompareTo",t:8,pi:[{n:"other",pt:$n[0].Int64,ps:0}],sn:"compareTo",rt:$n[0].Int32,p:[$n[0].Int64],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"CompareTo",t:8,pi:[{n:"obj",pt:$n[0].Object,ps:0}],sn:"compareTo",rt:$n[0].Int32,p:[$n[0].Object],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"Equals",t:8,pi:[{n:"other",pt:$n[0].Int64,ps:0}],sn:"equalsT",rt:$n[0].Boolean,p:[$n[0].Int64],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Format",t:8,pi:[{n:"format",pt:$n[0].String,ps:0}],sn:"format",rt:$n[0].String,p:[$n[0].String]},{a:2,n:"Format",t:8,pi:[{n:"format",pt:$n[0].String,ps:0},{n:"provider",pt:$n[0].IFormatProvider,ps:1}],sn:"format",rt:$n[0].String,p:[$n[0].String,$n[0].IFormatProvider]},{a:2,n:"Parse",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0}],tpc:0,def:function(s){return System.Int64.parse(s)},rt:$n[0].Int64,p:[$n[0].String]},{a:2,n:"ToString",t:8,pi:[{n:"radix",pt:$n[0].Int32,ps:0}],sn:"toString",rt:$n[0].String,p:[$n[0].Int32]},{a:2,n:"ToString",t:8,pi:[{n:"format",pt:$n[0].String,ps:0}],sn:"toString",rt:$n[0].String,p:[$n[0].String]},{a:2,n:"ToString",t:8,pi:[{n:"format",pt:$n[0].String,ps:0},{n:"provider",pt:$n[0].IFormatProvider,ps:1}],sn:"format",rt:$n[0].String,p:[$n[0].String,$n[0].IFormatProvider]},{a:2,n:"TryParse",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0},{n:"result",out:!0,pt:$n[0].Int64,ps:1}],tpc:0,def:function(s,result){return System.Int64.tryParse(s,result)},rt:$n[0].Boolean,p:[$n[0].String,$n[0].Int64],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"op_Explicit",is:!0,t:8,pi:[{n:"value",pt:$n[0].Double,ps:0}],sn:"op_Explicit",rt:$n[0].Int64,p:[$n[0].Double]},{a:2,n:"op_Explicit",is:!0,t:8,pi:[{n:"value",pt:$n[0].Int64,ps:0}],sn:"op_Explicit",rt:$n[0].Byte,p:[$n[0].Int64],box:function($v){return H5.box($v,System.Byte)}},{a:2,n:"op_Explicit",is:!0,t:8,pi:[{n:"value",pt:$n[0].Int64,ps:0}],sn:"op_Explicit",rt:$n[0].Char,p:[$n[0].Int64],box:function($v){return H5.box($v,System.Char,String.fromCharCode,System.Char.getHashCode)}},{a:2,n:"op_Explicit",is:!0,t:8,pi:[{n:"value",pt:$n[0].Int64,ps:0}],sn:"op_Explicit",rt:$n[0].Double,p:[$n[0].Int64],box:function($v){return H5.box($v,System.Double,System.Double.format,System.Double.getHashCode)}},{a:2,n:"op_Explicit",is:!0,t:8,pi:[{n:"value",pt:$n[0].Int64,ps:0}],sn:"op_Explicit",rt:$n[0].Int16,p:[$n[0].Int64],box:function($v){return H5.box($v,System.Int16)}},{a:2,n:"op_Explicit",is:!0,t:8,pi:[{n:"value",pt:$n[0].Int64,ps:0}],sn:"op_Explicit",rt:$n[0].Int32,p:[$n[0].Int64],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"op_Explicit",is:!0,t:8,pi:[{n:"value",pt:$n[0].Int64,ps:0}],sn:"op_Explicit",rt:$n[0].SByte,p:[$n[0].Int64],box:function($v){return H5.box($v,System.SByte)}},{a:2,n:"op_Explicit",is:!0,t:8,pi:[{n:"value",pt:$n[0].Int64,ps:0}],sn:"op_Explicit",rt:$n[0].Single,p:[$n[0].Int64],box:function($v){return H5.box($v,System.Single,System.Single.format,System.Single.getHashCode)}},{a:2,n:"op_Explicit",is:!0,t:8,pi:[{n:"value",pt:$n[0].Int64,ps:0}],sn:"op_Explicit",rt:$n[0].UInt16,p:[$n[0].Int64],box:function($v){return H5.box($v,System.UInt16)}},{a:2,n:"op_Explicit",is:!0,t:8,pi:[{n:"value",pt:$n[0].Int64,ps:0}],sn:"op_Explicit",rt:$n[0].UInt32,p:[$n[0].Int64],box:function($v){return H5.box($v,System.UInt32)}},{a:2,n:"op_Explicit",is:!0,t:8,pi:[{n:"value",pt:$n[0].Int64,ps:0}],sn:"op_Explicit",rt:$n[0].UInt64,p:[$n[0].Int64]},{a:2,n:"op_Explicit",is:!0,t:8,pi:[{n:"value",pt:$n[0].Single,ps:0}],sn:"op_Explicit",rt:$n[0].Int64,p:[$n[0].Single]},{a:2,n:"op_Explicit",is:!0,t:8,pi:[{n:"value",pt:$n[0].UInt64,ps:0}],sn:"op_Explicit",rt:$n[0].Int64,p:[$n[0].UInt64]},{a:2,n:"op_Implicit",is:!0,t:8,pi:[{n:"value",pt:$n[0].Byte,ps:0}],sn:"op_Implicit",rt:$n[0].Int64,p:[$n[0].Byte]},{a:2,n:"op_Implicit",is:!0,t:8,pi:[{n:"value",pt:$n[0].Char,ps:0}],sn:"op_Implicit",rt:$n[0].Int64,p:[$n[0].Char]},{a:2,n:"op_Implicit",is:!0,t:8,pi:[{n:"value",pt:$n[0].Int16,ps:0}],sn:"op_Implicit",rt:$n[0].Int64,p:[$n[0].Int16]},{a:2,n:"op_Implicit",is:!0,t:8,pi:[{n:"value",pt:$n[0].Int32,ps:0}],sn:"op_Implicit",rt:$n[0].Int64,p:[$n[0].Int32]},{a:2,n:"op_Implicit",is:!0,t:8,pi:[{n:"value",pt:$n[0].SByte,ps:0}],sn:"op_Implicit",rt:$n[0].Int64,p:[$n[0].SByte]},{a:2,n:"op_Implicit",is:!0,t:8,pi:[{n:"value",pt:$n[0].UInt16,ps:0}],sn:"op_Implicit",rt:$n[0].Int64,p:[$n[0].UInt16]},{a:2,n:"op_Implicit",is:!0,t:8,pi:[{n:"value",pt:$n[0].UInt32,ps:0}],sn:"op_Implicit",rt:$n[0].Int64,p:[$n[0].UInt32]},{a:2,n:"MaxValue",is:!0,t:4,rt:$n[0].Int64,sn:"MaxValue"},{a:2,n:"MinValue",is:!0,t:4,rt:$n[0].Int64,sn:"MinValue"}]}},$n);$m("System.MathF",function(){return{att:1048961,a:2,s:!0,m:[{a:2,n:"Abs",is:!0,t:8,pi:[{n:"x",pt:$n[0].Single,ps:0}],tpc:0,def:function(x){return Math.abs(x)},rt:$n[0].Single,p:[$n[0].Single],box:function($v){return H5.box($v,System.Single,System.Single.format,System.Single.getHashCode)}},{a:2,n:"Acos",is:!0,t:8,pi:[{n:"x",pt:$n[0].Single,ps:0}],tpc:0,def:function(x){return Math.acos(x)},rt:$n[0].Single,p:[$n[0].Single],box:function($v){return H5.box($v,System.Single,System.Single.format,System.Single.getHashCode)}},{a:2,n:"Asin",is:!0,t:8,pi:[{n:"x",pt:$n[0].Single,ps:0}],tpc:0,def:function(x){return Math.asin(x)},rt:$n[0].Single,p:[$n[0].Single],box:function($v){return H5.box($v,System.Single,System.Single.format,System.Single.getHashCode)}},{a:2,n:"Atan",is:!0,t:8,pi:[{n:"x",pt:$n[0].Single,ps:0}],tpc:0,def:function(x){return Math.atan(x)},rt:$n[0].Single,p:[$n[0].Single],box:function($v){return H5.box($v,System.Single,System.Single.format,System.Single.getHashCode)}},{a:2,n:"Atan2",is:!0,t:8,pi:[{n:"y",pt:$n[0].Single,ps:0},{n:"x",pt:$n[0].Single,ps:1}],tpc:0,def:function(y,x){return Math.atan2(y,x)},rt:$n[0].Single,p:[$n[0].Single,$n[0].Single],box:function($v){return H5.box($v,System.Single,System.Single.format,System.Single.getHashCode)}},{a:2,n:"BitDecrement",is:!0,t:8,pi:[{n:"x",pt:$n[0].Single,ps:0}],tpc:0,def:function(x){return H5.Int.bitDecrement(x)},rt:$n[0].Single,p:[$n[0].Single],box:function($v){return H5.box($v,System.Single,System.Single.format,System.Single.getHashCode)}},{a:2,n:"BitIncrement",is:!0,t:8,pi:[{n:"x",pt:$n[0].Single,ps:0}],tpc:0,def:function(x){return H5.Int.bitIncrement(x)},rt:$n[0].Single,p:[$n[0].Single],box:function($v){return H5.box($v,System.Single,System.Single.format,System.Single.getHashCode)}},{a:2,n:"Ceiling",is:!0,t:8,pi:[{n:"x",pt:$n[0].Single,ps:0}],tpc:0,def:function(x){return Math.ceil(x)},rt:$n[0].Single,p:[$n[0].Single],box:function($v){return H5.box($v,System.Single,System.Single.format,System.Single.getHashCode)}},{a:2,n:"CopySign",is:!0,t:8,pi:[{n:"x",pt:$n[0].Single,ps:0},{n:"y",pt:$n[0].Single,ps:1}],tpc:0,def:function(x,y){return(1/y<0?-1:1)*Math.abs(x)},rt:$n[0].Single,p:[$n[0].Single,$n[0].Single],box:function($v){return H5.box($v,System.Single,System.Single.format,System.Single.getHashCode)}},{a:2,n:"Cos",is:!0,t:8,pi:[{n:"x",pt:$n[0].Single,ps:0}],tpc:0,def:function(x){return Math.cos(x)},rt:$n[0].Single,p:[$n[0].Single],box:function($v){return H5.box($v,System.Single,System.Single.format,System.Single.getHashCode)}},{a:2,n:"Cosh",is:!0,t:8,pi:[{n:"value",pt:$n[0].Single,ps:0}],tpc:0,def:function(value){return H5.Math.cosh(value)},rt:$n[0].Single,p:[$n[0].Single],box:function($v){return H5.box($v,System.Single,System.Single.format,System.Single.getHashCode)}},{a:2,n:"Exp",is:!0,t:8,pi:[{n:"x",pt:$n[0].Single,ps:0}],tpc:0,def:function(x){return Math.exp(x)},rt:$n[0].Single,p:[$n[0].Single],box:function($v){return H5.box($v,System.Single,System.Single.format,System.Single.getHashCode)}},{a:2,n:"Floor",is:!0,t:8,pi:[{n:"x",pt:$n[0].Single,ps:0}],tpc:0,def:function(x){return Math.floor(x)},rt:$n[0].Single,p:[$n[0].Single],box:function($v){return H5.box($v,System.Single,System.Single.format,System.Single.getHashCode)}},{a:2,n:"FusedMultiplyAdd",is:!0,t:8,pi:[{n:"x",pt:$n[0].Single,ps:0},{n:"y",pt:$n[0].Single,ps:1},{n:"z",pt:$n[0].Single,ps:2}],tpc:0,def:function(x,y,z){return x*y+z},rt:$n[0].Single,p:[$n[0].Single,$n[0].Single,$n[0].Single],box:function($v){return H5.box($v,System.Single,System.Single.format,System.Single.getHashCode)}},{a:2,n:"IEEERemainder",is:!0,t:8,pi:[{n:"x",pt:$n[0].Single,ps:0},{n:"y",pt:$n[0].Single,ps:1}],tpc:0,def:function(x,y){return H5.Math.IEEERemainder(x,y)},rt:$n[0].Single,p:[$n[0].Single,$n[0].Single],box:function($v){return H5.box($v,System.Single,System.Single.format,System.Single.getHashCode)}},{a:2,n:"Log",is:!0,t:8,pi:[{n:"x",pt:$n[0].Single,ps:0}],tpc:0,def:function(x){return H5.Math.log(x)},rt:$n[0].Single,p:[$n[0].Single],box:function($v){return H5.box($v,System.Single,System.Single.format,System.Single.getHashCode)}},{a:2,n:"Log",is:!0,t:8,pi:[{n:"x",pt:$n[0].Single,ps:0},{n:"y",pt:$n[0].Single,ps:1}],tpc:0,def:function(x,y){return H5.Math.logWithBase(x,y)},rt:$n[0].Single,p:[$n[0].Single,$n[0].Single],box:function($v){return H5.box($v,System.Single,System.Single.format,System.Single.getHashCode)}},{a:2,n:"Log10",is:!0,t:8,pi:[{n:"x",pt:$n[0].Single,ps:0}],tpc:0,def:function(x){return H5.Math.logWithBase(x,10)},rt:$n[0].Single,p:[$n[0].Single],box:function($v){return H5.box($v,System.Single,System.Single.format,System.Single.getHashCode)}},{a:2,n:"Log2",is:!0,t:8,pi:[{n:"x",pt:$n[0].Single,ps:0}],tpc:0,def:function(x){return H5.Math.logWithBase(x,2)},rt:$n[0].Single,p:[$n[0].Single],box:function($v){return H5.box($v,System.Single,System.Single.format,System.Single.getHashCode)}},{a:2,n:"Max",is:!0,t:8,pi:[{n:"x",pt:$n[0].Single,ps:0},{n:"y",pt:$n[0].Single,ps:1}],tpc:0,def:function(x,y){return Math.max(x,y)},rt:$n[0].Single,p:[$n[0].Single,$n[0].Single],box:function($v){return H5.box($v,System.Single,System.Single.format,System.Single.getHashCode)}},{a:2,n:"MaxMagnitude",is:!0,t:8,pi:[{n:"x",pt:$n[0].Single,ps:0},{n:"y",pt:$n[0].Single,ps:1}],tpc:0,def:function(x,y){return function(x,y){var ax=Math.abs(x),ay=Math.abs(y);return ax>ay?x:ax===ay?x>y?x:y:y}(x,y)},rt:$n[0].Single,p:[$n[0].Single,$n[0].Single],box:function($v){return H5.box($v,System.Single,System.Single.format,System.Single.getHashCode)}},{a:2,n:"Min",is:!0,t:8,pi:[{n:"x",pt:$n[0].Single,ps:0},{n:"y",pt:$n[0].Single,ps:1}],tpc:0,def:function(x,y){return Math.min(x,y)},rt:$n[0].Single,p:[$n[0].Single,$n[0].Single],box:function($v){return H5.box($v,System.Single,System.Single.format,System.Single.getHashCode)}},{a:2,n:"MinMagnitude",is:!0,t:8,pi:[{n:"x",pt:$n[0].Single,ps:0},{n:"y",pt:$n[0].Single,ps:1}],tpc:0,def:function(x,y){return function(x,y){var ax=Math.abs(x),ay=Math.abs(y);return axk__BackingField",t:4,rt:$n[0].Boolean,sn:"HasValue",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:T,sn:"Value"}]}},$n);$m("System.Range",function(){return{att:1048841,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].Index,$n[0].Index],pi:[{n:"start",pt:$n[0].Index,ps:0},{n:"end",pt:$n[0].Index,ps:1}],sn:"$ctor1"},{a:2,n:"EndAt",is:!0,t:8,pi:[{n:"end",pt:$n[0].Index,ps:0}],sn:"EndAt",rt:$n[0].Range,p:[$n[0].Index]},{ov:!0,a:2,n:"Equals",t:8,pi:[{n:"value",pt:$n[0].Object,ps:0}],sn:"equals",rt:$n[0].Boolean,p:[$n[0].Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Equals",t:8,pi:[{n:"other",pt:$n[0].Range,ps:0}],sn:"equalsT",rt:$n[0].Boolean,p:[$n[0].Range],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ov:!0,a:2,n:"GetHashCode",t:8,sn:"getHashCode",rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"GetOffsetAndLength",t:8,pi:[{n:"length",pt:$n[0].Int32,ps:0}],sn:"GetOffsetAndLength",rt:$n[0].ValueTuple$2(System.Int32,System.Int32),p:[$n[0].Int32]},{a:2,n:"StartAt",is:!0,t:8,pi:[{n:"start",pt:$n[0].Index,ps:0}],sn:"StartAt",rt:$n[0].Range,p:[$n[0].Index]},{ov:!0,a:2,n:"ToString",t:8,sn:"toString",rt:$n[0].String},{a:2,n:"All",is:!0,t:16,rt:$n[0].Range,g:{a:2,n:"get_All",t:8,rt:$n[0].Range,fg:"All",is:!0},fn:"All"},{a:2,n:"End",t:16,rt:$n[0].Index,g:{a:2,n:"get_End",t:8,rt:$n[0].Index,fg:"End"},fn:"End"},{a:2,n:"Start",t:16,rt:$n[0].Index,g:{a:2,n:"get_Start",t:8,rt:$n[0].Index,fg:"Start"},fn:"Start"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Index,sn:"End"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Index,sn:"Start"}]}},$n);$m("System.ReadOnlySpan$1",function(T){return{att:1048841,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].Span$1(T)],pi:[{n:"span",pt:$n[0].Span$1(T),ps:0}],sn:"$ctor3"},{a:2,n:".ctor",t:1,p:[System.Array.type(T)],pi:[{n:"array",pt:System.Array.type(T),ps:0}],sn:"$ctor1"},{a:2,n:".ctor",t:1,p:[System.Array.type(T),$n[0].Int32,$n[0].Int32],pi:[{n:"array",pt:System.Array.type(T),ps:0},{n:"start",pt:$n[0].Int32,ps:1},{n:"length",pt:$n[0].Int32,ps:2}],sn:"$ctor2"},{a:2,n:"ToArray",t:8,sn:"ToArray",rt:System.Array.type(T)},{a:2,n:"op_Implicit",is:!0,t:8,pi:[{n:"span",pt:$n[0].Span$1(T),ps:0}],sn:"op_Implicit$1",rt:$n[0].ReadOnlySpan$1(T),p:[$n[0].Span$1(T)]},{a:2,n:"op_Implicit",is:!0,t:8,pi:[{n:"array",pt:System.Array.type(T),ps:0}],sn:"op_Implicit",rt:$n[0].ReadOnlySpan$1(T),p:[System.Array.type(T)]},{a:2,n:"Item",t:16,rt:$n[7].Ref$1(T),p:[$n[0].Int32],i:!0,ipi:[{n:"index",pt:$n[0].Int32,ps:0}],g:{a:2,n:"get_Item",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0}],sn:"getItem",rt:$n[7].Ref$1(T),p:[$n[0].Int32]}},{a:2,n:"Length",t:16,rt:$n[0].Int32,g:{a:2,n:"get_Length",t:8,rt:$n[0].Int32,fg:"Length",box:function($v){return H5.box($v,System.Int32)}},fn:"Length"},{a:4,n:"_array",t:4,rt:System.Array.type(T),sn:"_array",ro:!0},{a:4,n:"_length",t:4,rt:$n[0].Int32,sn:"_length",ro:!0,box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"_offset",t:4,rt:$n[0].Int32,sn:"_offset",ro:!0,box:function($v){return H5.box($v,System.Int32)}}]}},$n);$m("System.SByte",function(){return{att:1048841,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,def:function(){return Number}},{a:1,n:".ctor",t:1,p:[$n[0].Int32],pi:[{n:"i",pt:$n[0].Int32,ps:0}],def:function(i){return Number}},{a:2,n:"CompareTo",t:8,pi:[{n:"obj",pt:$n[0].Object,ps:0}],tpc:0,def:function(obj){return H5.compare(this,obj)},rt:$n[0].Int32,p:[$n[0].Object],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"CompareTo",t:8,pi:[{n:"other",pt:$n[0].SByte,ps:0}],tpc:0,def:function(other){return H5.compare(this,other)},rt:$n[0].Int32,p:[$n[0].SByte],box:function($v){return H5.box($v,System.Int32)}},{ov:!0,a:2,n:"Equals",t:8,pi:[{n:"other",pt:$n[0].Object,ps:0}],tpc:0,def:function(other){return System.SByte.equals(this,other)},rt:$n[0].Boolean,p:[$n[0].Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Equals",t:8,pi:[{n:"other",pt:$n[0].SByte,ps:0}],tpc:0,def:function(other){return this===other},rt:$n[0].Boolean,p:[$n[0].SByte],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Format",t:8,pi:[{n:"format",pt:$n[0].String,ps:0}],tpc:0,def:function(format){return System.SByte.format(this,format)},rt:$n[0].String,p:[$n[0].String]},{a:2,n:"Format",t:8,pi:[{n:"format",pt:$n[0].String,ps:0},{n:"provider",pt:$n[0].IFormatProvider,ps:1}],tpc:0,def:function(format,provider){return System.SByte.format(this,format,provider)},rt:$n[0].String,p:[$n[0].String,$n[0].IFormatProvider]},{a:2,n:"Parse",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0}],tpc:0,def:function(s){return System.SByte.parse(s)},rt:$n[0].SByte,p:[$n[0].String],box:function($v){return H5.box($v,System.SByte)}},{a:2,n:"Parse",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0},{n:"radix",pt:$n[0].Int32,ps:1}],tpc:0,def:function(s,radix){return System.SByte.parse(s,radix)},rt:$n[0].SByte,p:[$n[0].String,$n[0].Int32],box:function($v){return H5.box($v,System.SByte)}},{a:2,n:"ToString",t:8,pi:[{n:"radix",pt:$n[0].Int32,ps:0}],sn:"toString",rt:$n[0].String,p:[$n[0].Int32]},{a:2,n:"ToString",t:8,pi:[{n:"format",pt:$n[0].String,ps:0}],tpc:0,def:function(format){return System.SByte.format(this,format)},rt:$n[0].String,p:[$n[0].String]},{a:2,n:"ToString",t:8,pi:[{n:"format",pt:$n[0].String,ps:0},{n:"provider",pt:$n[0].IFormatProvider,ps:1}],tpc:0,def:function(format,provider){return System.SByte.format(this,format,provider)},rt:$n[0].String,p:[$n[0].String,$n[0].IFormatProvider]},{a:2,n:"TryParse",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0},{n:"result",out:!0,pt:$n[0].SByte,ps:1}],tpc:0,def:function(s,result){return System.SByte.tryParse(s,result)},rt:$n[0].Boolean,p:[$n[0].String,$n[0].SByte],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"TryParse",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0},{n:"result",out:!0,pt:$n[0].SByte,ps:1},{n:"radix",pt:$n[0].Int32,ps:2}],tpc:0,def:function(s,result,radix){return System.SByte.tryParse(s,result,radix)},rt:$n[0].Boolean,p:[$n[0].String,$n[0].SByte,$n[0].Int32],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"MaxValue",is:!0,t:4,rt:$n[0].SByte,sn:"MaxValue",box:function($v){return H5.box($v,System.SByte)}},{a:2,n:"MinValue",is:!0,t:4,rt:$n[0].SByte,sn:"MinValue",box:function($v){return H5.box($v,System.SByte)}}]}},$n);$m("System.Single",function(){return{att:1048841,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,def:function(){return Number}},{a:1,n:".ctor",t:1,p:[$n[0].Int32],pi:[{n:"i",pt:$n[0].Int32,ps:0}],def:function(i){return Number}},{a:2,n:"CompareTo",t:8,pi:[{n:"obj",pt:$n[0].Object,ps:0}],tpc:0,def:function(obj){return H5.compare(this,obj)},rt:$n[0].Int32,p:[$n[0].Object],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"CompareTo",t:8,pi:[{n:"other",pt:$n[0].Single,ps:0}],tpc:0,def:function(other){return H5.compare(this,other)},rt:$n[0].Int32,p:[$n[0].Single],box:function($v){return H5.box($v,System.Int32)}},{ov:!0,a:2,n:"Equals",t:8,pi:[{n:"other",pt:$n[0].Object,ps:0}],tpc:0,def:function(other){return System.Single.equals(this,other)},rt:$n[0].Boolean,p:[$n[0].Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Equals",t:8,pi:[{n:"other",pt:$n[0].Single,ps:0}],tpc:0,def:function(other){return this===other},rt:$n[0].Boolean,p:[$n[0].Single],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Format",t:8,pi:[{n:"format",pt:$n[0].String,ps:0}],tpc:0,def:function(format){return System.Single.format(this,format)},rt:$n[0].String,p:[$n[0].String]},{a:2,n:"Format",t:8,pi:[{n:"format",pt:$n[0].String,ps:0},{n:"provider",pt:$n[0].IFormatProvider,ps:1}],tpc:0,def:function(format,provider){return System.Single.format(this,format,provider)},rt:$n[0].String,p:[$n[0].String,$n[0].IFormatProvider]},{ov:!0,a:2,n:"GetHashCode",t:8,tpc:0,def:function(){return System.Single.getHashCode(this)},rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"IsFinite",is:!0,t:8,pi:[{n:"d",pt:$n[0].Single,ps:0}],tpc:0,def:function(d){return isFinite(d)},rt:$n[0].Boolean,p:[$n[0].Single],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"IsInfinity",is:!0,t:8,pi:[{n:"d",pt:$n[0].Single,ps:0}],tpc:0,def:function(d){return Math.abs(d)===Number.POSITIVE_INFINITY},rt:$n[0].Boolean,p:[$n[0].Single],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"IsNaN",is:!0,t:8,pi:[{n:"d",pt:$n[0].Single,ps:0}],tpc:0,def:function(d){return isNaN(d)},rt:$n[0].Boolean,p:[$n[0].Single],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"IsNegativeInfinity",is:!0,t:8,pi:[{n:"d",pt:$n[0].Single,ps:0}],tpc:0,def:function(d){return d===Number.NEGATIVE_INFINITY},rt:$n[0].Boolean,p:[$n[0].Single],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"IsPositiveInfinity",is:!0,t:8,pi:[{n:"d",pt:$n[0].Single,ps:0}],tpc:0,def:function(d){return d===Number.POSITIVE_INFINITY},rt:$n[0].Boolean,p:[$n[0].Single],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Parse",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0}],tpc:0,def:function(s){return System.Single.parse(s)},rt:$n[0].Single,p:[$n[0].String],box:function($v){return H5.box($v,System.Single,System.Single.format,System.Single.getHashCode)}},{a:2,n:"Parse",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0},{n:"provider",pt:$n[0].IFormatProvider,ps:1}],tpc:0,def:function(s,provider){return System.Single.parse(s,provider)},rt:$n[0].Single,p:[$n[0].String,$n[0].IFormatProvider],box:function($v){return H5.box($v,System.Single,System.Single.format,System.Single.getHashCode)}},{a:2,n:"ToExponential",t:8,sn:"toExponential",rt:$n[0].String},{a:2,n:"ToExponential",t:8,pi:[{n:"fractionDigits",pt:$n[0].Int32,ps:0}],sn:"toExponential",rt:$n[0].String,p:[$n[0].Int32]},{a:2,n:"ToFixed",t:8,sn:"toFixed",rt:$n[0].String},{a:2,n:"ToFixed",t:8,pi:[{n:"fractionDigits",pt:$n[0].Int32,ps:0}],sn:"toFixed",rt:$n[0].String,p:[$n[0].Int32]},{a:2,n:"ToPrecision",t:8,sn:"toPrecision",rt:$n[0].String},{a:2,n:"ToPrecision",t:8,pi:[{n:"precision",pt:$n[0].Int32,ps:0}],sn:"toPrecision",rt:$n[0].String,p:[$n[0].Int32]},{ov:!0,a:2,n:"ToString",t:8,tpc:0,def:function(){return System.Single.format(this)},rt:$n[0].String},{a:2,n:"ToString",t:8,pi:[{n:"provider",pt:$n[0].IFormatProvider,ps:0}],tpc:0,def:function(provider){return System.Single.format(this,"G",provider)},rt:$n[0].String,p:[$n[0].IFormatProvider]},{a:2,n:"ToString",t:8,pi:[{n:"radix",pt:$n[0].Int32,ps:0}],sn:"toString",rt:$n[0].String,p:[$n[0].Int32]},{a:2,n:"ToString",t:8,pi:[{n:"format",pt:$n[0].String,ps:0}],tpc:0,def:function(format){return System.Single.format(this,format)},rt:$n[0].String,p:[$n[0].String]},{a:2,n:"ToString",t:8,pi:[{n:"format",pt:$n[0].String,ps:0},{n:"provider",pt:$n[0].IFormatProvider,ps:1}],tpc:0,def:function(format,provider){return System.Single.format(this,format,provider)},rt:$n[0].String,p:[$n[0].String,$n[0].IFormatProvider]},{a:2,n:"TryParse",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0},{n:"result",out:!0,pt:$n[0].Single,ps:1}],tpc:0,def:function(s,result){return System.Single.tryParse(s,null,result)},rt:$n[0].Boolean,p:[$n[0].String,$n[0].Single],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"TryParse",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0},{n:"provider",pt:$n[0].IFormatProvider,ps:1},{n:"result",out:!0,pt:$n[0].Single,ps:2}],tpc:0,def:function(s,provider,result){return System.Single.tryParse(s,provider,result)},rt:$n[0].Boolean,p:[$n[0].String,$n[0].IFormatProvider,$n[0].Single],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Epsilon",is:!0,t:4,rt:$n[0].Single,sn:"Epsilon",box:function($v){return H5.box($v,System.Single,System.Single.format,System.Single.getHashCode)}},{a:2,n:"MaxValue",is:!0,t:4,rt:$n[0].Single,sn:"MaxValue",box:function($v){return H5.box($v,System.Single,System.Single.format,System.Single.getHashCode)}},{a:2,n:"MinValue",is:!0,t:4,rt:$n[0].Single,sn:"MinValue",box:function($v){return H5.box($v,System.Single,System.Single.format,System.Single.getHashCode)}},{a:2,n:"NaN",is:!0,t:4,rt:$n[0].Single,sn:"NaN",box:function($v){return H5.box($v,System.Single,System.Single.format,System.Single.getHashCode)}},{a:2,n:"NegativeInfinity",is:!0,t:4,rt:$n[0].Single,sn:"NegativeInfinity",box:function($v){return H5.box($v,System.Single,System.Single.format,System.Single.getHashCode)}},{a:2,n:"PositiveInfinity",is:!0,t:4,rt:$n[0].Single,sn:"PositiveInfinity",box:function($v){return H5.box($v,System.Single,System.Single.format,System.Single.getHashCode)}}]}},$n);$m("System.Span$1",function(T){return{att:1048841,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[System.Array.type(T)],pi:[{n:"array",pt:System.Array.type(T),ps:0}],sn:"$ctor1"},{a:2,n:".ctor",t:1,p:[System.Array.type(T),$n[0].Int32,$n[0].Int32],pi:[{n:"array",pt:System.Array.type(T),ps:0},{n:"start",pt:$n[0].Int32,ps:1},{n:"length",pt:$n[0].Int32,ps:2}],sn:"$ctor2"},{a:2,n:"ToArray",t:8,sn:"ToArray",rt:System.Array.type(T)},{a:2,n:"op_Implicit",is:!0,t:8,pi:[{n:"array",pt:System.Array.type(T),ps:0}],sn:"op_Implicit",rt:$n[0].Span$1(T),p:[System.Array.type(T)]},{a:2,n:"Item",t:16,rt:$n[7].Ref$1(T),p:[$n[0].Int32],i:!0,ipi:[{n:"index",pt:$n[0].Int32,ps:0}],g:{a:2,n:"get_Item",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0}],sn:"getItem",rt:$n[7].Ref$1(T),p:[$n[0].Int32]}},{a:2,n:"Length",t:16,rt:$n[0].Int32,g:{a:2,n:"get_Length",t:8,rt:$n[0].Int32,fg:"Length",box:function($v){return H5.box($v,System.Int32)}},fn:"Length"},{a:4,n:"_array",t:4,rt:System.Array.type(T),sn:"_array",ro:!0},{a:4,n:"_length",t:4,rt:$n[0].Int32,sn:"_length",ro:!0,box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"_offset",t:4,rt:$n[0].Int32,sn:"_offset",ro:!0,box:function($v){return H5.box($v,System.Int32)}}]}},$n);$m("System.String",function(){return{att:1048833,a:2,m:[{a:2,n:".ctor",t:1,def:function(){return""}},{a:2,n:".ctor",t:1,p:[$n[0].Array.type(System.Char)],pi:[{n:"value",pt:$n[0].Array.type(System.Char),ps:0}],def:function(value){return System.String.fromCharArray(value)}},{a:2,n:".ctor",t:1,p:[$n[0].Char,$n[0].Int32],pi:[{n:"c",pt:$n[0].Char,ps:0},{n:"count",pt:$n[0].Int32,ps:1}],def:function(c,count){return System.String.fromCharCount(c,count)}},{a:2,n:".ctor",t:1,p:[$n[0].Array.type(System.Char),$n[0].Int32,$n[0].Int32],pi:[{n:"value",pt:$n[0].Array.type(System.Char),ps:0},{n:"startIndex",pt:$n[0].Int32,ps:1},{n:"length",pt:$n[0].Int32,ps:2}],def:function(value,startIndex,length){return System.String.fromCharArray(value,startIndex,length)}},{a:2,n:"Clone",t:8,tpc:0,def:function(){return this},rt:$n[0].Object},{a:2,n:"Compare",is:!0,t:8,pi:[{n:"strA",pt:$n[0].String,ps:0},{n:"strB",pt:$n[0].String,ps:1}],tpc:0,def:function(strA,strB){return System.String.compare(strA,strB)},rt:$n[0].Int32,p:[$n[0].String,$n[0].String],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"Compare",is:!0,t:8,pi:[{n:"strA",pt:$n[0].String,ps:0},{n:"strB",pt:$n[0].String,ps:1},{n:"ignoreCase",pt:$n[0].Boolean,ps:2}],tpc:0,def:function(strA,strB,ignoreCase){return System.String.compare(strA,strB,ignoreCase)},rt:$n[0].Int32,p:[$n[0].String,$n[0].String,$n[0].Boolean],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"Compare",is:!0,t:8,pi:[{n:"strA",pt:$n[0].String,ps:0},{n:"strB",pt:$n[0].String,ps:1},{n:"comparisonType",pt:$n[0].StringComparison,ps:2}],tpc:0,def:function(strA,strB,comparisonType){return System.String.compare(strA,strB,comparisonType)},rt:$n[0].Int32,p:[$n[0].String,$n[0].String,$n[0].StringComparison],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"Compare",is:!0,t:8,pi:[{n:"strA",pt:$n[0].String,ps:0},{n:"strB",pt:$n[0].String,ps:1},{n:"ignoreCase",pt:$n[0].Boolean,ps:2},{n:"culture",pt:$n[1].CultureInfo,ps:3}],tpc:0,def:function(strA,strB,ignoreCase,culture){return System.String.compare(strA,strB,ignoreCase,culture)},rt:$n[0].Int32,p:[$n[0].String,$n[0].String,$n[0].Boolean,$n[1].CultureInfo],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"Compare",is:!0,t:8,pi:[{n:"strA",pt:$n[0].String,ps:0},{n:"indexA",pt:$n[0].Int32,ps:1},{n:"strB",pt:$n[0].String,ps:2},{n:"indexB",pt:$n[0].Int32,ps:3},{n:"length",pt:$n[0].Int32,ps:4}],tpc:0,def:function(strA,indexA,strB,indexB,length){return System.String.compare(strA.substr(indexA,length),strB.substr(indexB,length))},rt:$n[0].Int32,p:[$n[0].String,$n[0].Int32,$n[0].String,$n[0].Int32,$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"Compare",is:!0,t:8,pi:[{n:"strA",pt:$n[0].String,ps:0},{n:"indexA",pt:$n[0].Int32,ps:1},{n:"strB",pt:$n[0].String,ps:2},{n:"indexB",pt:$n[0].Int32,ps:3},{n:"length",pt:$n[0].Int32,ps:4},{n:"ignoreCase",pt:$n[0].Boolean,ps:5}],tpc:0,def:function(strA,indexA,strB,indexB,length,ignoreCase){return System.String.compare(strA.substr(indexA,length),strB.substr(indexB,length),ignoreCase)},rt:$n[0].Int32,p:[$n[0].String,$n[0].Int32,$n[0].String,$n[0].Int32,$n[0].Int32,$n[0].Boolean],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"Compare",is:!0,t:8,pi:[{n:"strA",pt:$n[0].String,ps:0},{n:"indexA",pt:$n[0].Int32,ps:1},{n:"strB",pt:$n[0].String,ps:2},{n:"indexB",pt:$n[0].Int32,ps:3},{n:"length",pt:$n[0].Int32,ps:4},{n:"comparisonType",pt:$n[0].StringComparison,ps:5}],tpc:0,def:function(strA,indexA,strB,indexB,length,comparisonType){return System.String.compare(strA.substr(indexA,length),strB.substr(indexB,length),comparisonType)},rt:$n[0].Int32,p:[$n[0].String,$n[0].Int32,$n[0].String,$n[0].Int32,$n[0].Int32,$n[0].StringComparison],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"Compare",is:!0,t:8,pi:[{n:"strA",pt:$n[0].String,ps:0},{n:"indexA",pt:$n[0].Int32,ps:1},{n:"strB",pt:$n[0].String,ps:2},{n:"indexB",pt:$n[0].Int32,ps:3},{n:"length",pt:$n[0].Int32,ps:4},{n:"ignoreCase",pt:$n[0].Boolean,ps:5},{n:"culture",pt:$n[1].CultureInfo,ps:6}],tpc:0,def:function(strA,indexA,strB,indexB,length,ignoreCase,culture){return System.String.compare(strA.substr(indexA,length),strB.substr(indexB,length),ignoreCase,culture)},rt:$n[0].Int32,p:[$n[0].String,$n[0].Int32,$n[0].String,$n[0].Int32,$n[0].Int32,$n[0].Boolean,$n[1].CultureInfo],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"CompareTo",t:8,pi:[{n:"value",pt:$n[0].Object,ps:0}],tpc:0,def:function(value){return System.String.compare(this,value.toString())},rt:$n[0].Int32,p:[$n[0].Object],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"CompareTo",t:8,pi:[{n:"strB",pt:$n[0].String,ps:0}],tpc:0,def:function(strB){return System.String.compare(this,strB)},rt:$n[0].Int32,p:[$n[0].String],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"Concat",is:!0,t:8,pi:[{n:"values",pt:$n[3].IEnumerable$1(System.String),ps:0}],tpc:0,def:function(values){return System.String.concat(H5.toArray(values))},rt:$n[0].String,p:[$n[3].IEnumerable$1(System.String)]},{a:2,n:"Concat",is:!0,t:8,pi:[{n:"values",pt:$n[3].IEnumerable$1(System.Object),ps:0}],tpc:1,def:function(T,values){return System.String.concat(H5.toArray(values))},rt:$n[0].String,p:[$n[3].IEnumerable$1(System.Object)]},{a:2,n:"Concat",is:!0,t:8,pi:[{n:"arg0",pt:$n[0].Object,ps:0}],tpc:0,def:function(arg0){return System.String.concat(arg0)},rt:$n[0].String,p:[$n[0].Object]},{a:2,n:"Concat",is:!0,t:8,pi:[{n:"args",ip:!0,pt:$n[0].Array.type(System.Object),ps:0}],tpc:0,def:function(args){return System.String.concat(Array.prototype.slice.call((arguments,0)))},rt:$n[0].String,p:[$n[0].Array.type(System.Object)]},{a:2,n:"Concat",is:!0,t:8,pi:[{n:"values",ip:!0,pt:$n[0].Array.type(System.String),ps:0}],tpc:0,def:function(values){return System.String.concat(Array.prototype.slice.call((arguments,0)))},rt:$n[0].String,p:[$n[0].Array.type(System.String)]},{a:2,n:"Concat",is:!0,t:8,pi:[{n:"arg0",pt:$n[0].Object,ps:0},{n:"arg1",pt:$n[0].Object,ps:1}],tpc:0,def:function(arg0,arg1){return System.String.concat(arg0,arg1)},rt:$n[0].String,p:[$n[0].Object,$n[0].Object]},{a:2,n:"Concat",is:!0,t:8,pi:[{n:"str0",pt:$n[0].String,ps:0},{n:"str1",pt:$n[0].String,ps:1}],tpc:0,def:function(str0,str1){return System.String.concat(str0,str1)},rt:$n[0].String,p:[$n[0].String,$n[0].String]},{a:2,n:"Concat",is:!0,t:8,pi:[{n:"arg0",pt:$n[0].Object,ps:0},{n:"arg1",pt:$n[0].Object,ps:1},{n:"arg2",pt:$n[0].Object,ps:2}],tpc:0,def:function(arg0,arg1,arg2){return System.String.concat(arg0,arg1,arg2)},rt:$n[0].String,p:[$n[0].Object,$n[0].Object,$n[0].Object]},{a:2,n:"Concat",is:!0,t:8,pi:[{n:"str0",pt:$n[0].String,ps:0},{n:"str1",pt:$n[0].String,ps:1},{n:"str2",pt:$n[0].String,ps:2}],tpc:0,def:function(str0,str1,str2){return System.String.concat(str0,str1,str2)},rt:$n[0].String,p:[$n[0].String,$n[0].String,$n[0].String]},{a:2,n:"Concat",is:!0,t:8,pi:[{n:"arg0",pt:$n[0].Object,ps:0},{n:"arg1",pt:$n[0].Object,ps:1},{n:"arg2",pt:$n[0].Object,ps:2},{n:"arg3",pt:$n[0].Object,ps:3}],tpc:0,def:function(arg0,arg1,arg2,arg3){return System.String.concat(arg0,arg1,arg2,arg3)},rt:$n[0].String,p:[$n[0].Object,$n[0].Object,$n[0].Object,$n[0].Object]},{a:2,n:"Concat",is:!0,t:8,pi:[{n:"str0",pt:$n[0].String,ps:0},{n:"str1",pt:$n[0].String,ps:1},{n:"str2",pt:$n[0].String,ps:2},{n:"str3",pt:$n[0].String,ps:3}],tpc:0,def:function(str0,str1,str2,str3){return System.String.concat(str0,str1,str2,str3)},rt:$n[0].String,p:[$n[0].String,$n[0].String,$n[0].String,$n[0].String]},{a:2,n:"Concat",is:!0,t:8,pi:[{n:"arg0",pt:$n[0].Object,ps:0},{n:"arg1",pt:$n[0].Object,ps:1},{n:"arg2",pt:$n[0].Object,ps:2},{n:"arg3",pt:$n[0].Object,ps:3},{n:"args",ip:!0,pt:$n[0].Array.type(System.Object),ps:4}],tpc:0,def:function(arg0,arg1,arg2,arg3,args){return System.String.concat(arg0,arg1,arg2,arg3,args)},rt:$n[0].String,p:[$n[0].Object,$n[0].Object,$n[0].Object,$n[0].Object,$n[0].Array.type(System.Object)]},{a:2,n:"Contains",t:8,pi:[{n:"value",pt:$n[0].String,ps:0}],tpc:0,def:function(value){return System.String.contains(this,value)},rt:$n[0].Boolean,p:[$n[0].String],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"CopyTo",t:8,pi:[{n:"sourceIndex",pt:$n[0].Int32,ps:0},{n:"destination",pt:$n[0].Array.type(System.Char),ps:1},{n:"destinationIndex",pt:$n[0].Int32,ps:2},{n:"count",pt:$n[0].Int32,ps:3}],tpc:0,def:function(sourceIndex,destination,destinationIndex,count){return System.String.copyTo(this,sourceIndex,destination,destinationIndex,count)},rt:$n[0].Void,p:[$n[0].Int32,$n[0].Array.type(System.Char),$n[0].Int32,$n[0].Int32]},{a:2,n:"EndsWith",t:8,pi:[{n:"value",pt:$n[0].String,ps:0}],tpc:0,def:function(value){return System.String.endsWith(this,value)},rt:$n[0].Boolean,p:[$n[0].String],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"EndsWith",t:8,pi:[{n:"value",pt:$n[0].String,ps:0},{n:"comparisonType",pt:$n[0].StringComparison,ps:1}],tpc:0,def:function(value,comparisonType){return System.String.endsWith(this,value,comparisonType)},rt:$n[0].Boolean,p:[$n[0].String,$n[0].StringComparison],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Equals",t:8,pi:[{n:"value",pt:$n[0].String,ps:0}],tpc:0,def:function(value){return System.String.equals(this,value)},rt:$n[0].Boolean,p:[$n[0].String],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Equals",is:!0,t:8,pi:[{n:"a",pt:$n[0].String,ps:0},{n:"b",pt:$n[0].String,ps:1}],tpc:0,def:function(a,b){return System.String.equals(a,b)},rt:$n[0].Boolean,p:[$n[0].String,$n[0].String],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Equals",t:8,pi:[{n:"value",pt:$n[0].String,ps:0},{n:"comparisonType",pt:$n[0].StringComparison,ps:1}],tpc:0,def:function(value,comparisonType){return System.String.equals(this,value,comparisonType)},rt:$n[0].Boolean,p:[$n[0].String,$n[0].StringComparison],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Equals",is:!0,t:8,pi:[{n:"a",pt:$n[0].String,ps:0},{n:"b",pt:$n[0].String,ps:1},{n:"comparisonType",pt:$n[0].StringComparison,ps:2}],tpc:0,def:function(a,b,comparisonType){return System.String.equals(a,b,comparisonType)},rt:$n[0].Boolean,p:[$n[0].String,$n[0].String,$n[0].StringComparison],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Format",is:!0,t:8,pi:[{n:"format",pt:$n[0].String,ps:0},{n:"arg0",pt:$n[0].Object,ps:1}],tpc:0,def:function(format,arg0){return System.String.format(format,[arg0])},rt:$n[0].String,p:[$n[0].String,$n[0].Object]},{a:2,n:"Format",is:!0,t:8,pi:[{n:"format",pt:$n[0].String,ps:0},{n:"args",ip:!0,pt:$n[0].Array.type(System.Object),ps:1}],tpc:0,def:function(format,args){return System.String.format(format,args)},rt:$n[0].String,p:[$n[0].String,$n[0].Array.type(System.Object)]},{a:2,n:"Format",is:!0,t:8,pi:[{n:"provider",pt:$n[0].IFormatProvider,ps:0},{n:"format",pt:$n[0].String,ps:1},{n:"arg0",pt:$n[0].Object,ps:2}],tpc:0,def:function(provider,format,arg0){return System.String.formatProvider(provider,format,[arg0])},rt:$n[0].String,p:[$n[0].IFormatProvider,$n[0].String,$n[0].Object]},{a:2,n:"Format",is:!0,t:8,pi:[{n:"provider",pt:$n[0].IFormatProvider,ps:0},{n:"format",pt:$n[0].String,ps:1},{n:"args",ip:!0,pt:$n[0].Array.type(System.Object),ps:2}],tpc:0,def:function(provider,format,args){return System.String.formatProvider(provider,format,args)},rt:$n[0].String,p:[$n[0].IFormatProvider,$n[0].String,$n[0].Array.type(System.Object)]},{a:2,n:"Format",is:!0,t:8,pi:[{n:"format",pt:$n[0].String,ps:0},{n:"arg0",pt:$n[0].Object,ps:1},{n:"arg1",pt:$n[0].Object,ps:2}],tpc:0,def:function(format,arg0,arg1){return System.String.format(format,arg0,arg1)},rt:$n[0].String,p:[$n[0].String,$n[0].Object,$n[0].Object]},{a:2,n:"Format",is:!0,t:8,pi:[{n:"provider",pt:$n[0].IFormatProvider,ps:0},{n:"format",pt:$n[0].String,ps:1},{n:"arg0",pt:$n[0].Object,ps:2},{n:"arg1",pt:$n[0].Object,ps:3}],tpc:0,def:function(provider,format,arg0,arg1){return System.String.formatProvider(provider,format,arg0,arg1)},rt:$n[0].String,p:[$n[0].IFormatProvider,$n[0].String,$n[0].Object,$n[0].Object]},{a:2,n:"Format",is:!0,t:8,pi:[{n:"format",pt:$n[0].String,ps:0},{n:"arg0",pt:$n[0].Object,ps:1},{n:"arg1",pt:$n[0].Object,ps:2},{n:"arg2",pt:$n[0].Object,ps:3}],tpc:0,def:function(format,arg0,arg1,arg2){return System.String.format(format,arg0,arg1,arg2)},rt:$n[0].String,p:[$n[0].String,$n[0].Object,$n[0].Object,$n[0].Object]},{a:2,n:"Format",is:!0,t:8,pi:[{n:"provider",pt:$n[0].IFormatProvider,ps:0},{n:"format",pt:$n[0].String,ps:1},{n:"arg0",pt:$n[0].Object,ps:2},{n:"arg1",pt:$n[0].Object,ps:3},{n:"arg2",pt:$n[0].Object,ps:4}],tpc:0,def:function(provider,format,arg0,arg1,arg2){return System.String.formatProvider(provider,format,arg0,arg1,arg2)},rt:$n[0].String,p:[$n[0].IFormatProvider,$n[0].String,$n[0].Object,$n[0].Object,$n[0].Object]},{a:2,n:"GetEnumerator",t:8,tpc:0,def:function(){return H5.getEnumerator(this)},rt:$n[0].CharEnumerator},{a:2,n:"IndexOf",t:8,pi:[{n:"value",pt:$n[0].Char,ps:0}],tpc:0,def:function(value){return System.String.indexOf(this,String.fromCharCode(value))},rt:$n[0].Int32,p:[$n[0].Char],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"IndexOf",t:8,pi:[{n:"value",pt:$n[0].String,ps:0}],tpc:0,def:function(value){return System.String.indexOf(this,value)},rt:$n[0].Int32,p:[$n[0].String],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"IndexOf",t:8,pi:[{n:"value",pt:$n[0].Char,ps:0},{n:"startIndex",pt:$n[0].Int32,ps:1}],tpc:0,def:function(value,startIndex){return System.String.indexOf(this,String.fromCharCode(value),startIndex)},rt:$n[0].Int32,p:[$n[0].Char,$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"IndexOf",t:8,pi:[{n:"value",pt:$n[0].String,ps:0},{n:"startIndex",pt:$n[0].Int32,ps:1}],tpc:0,def:function(value,startIndex){return System.String.indexOf(this,value,startIndex)},rt:$n[0].Int32,p:[$n[0].String,$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"IndexOf",t:8,pi:[{n:"value",pt:$n[0].String,ps:0},{n:"comparisonType",pt:$n[0].StringComparison,ps:1}],tpc:0,def:function(value,comparisonType){return System.String.indexOf(this,value,0,null,comparisonType)},rt:$n[0].Int32,p:[$n[0].String,$n[0].StringComparison],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"IndexOf",t:8,pi:[{n:"value",pt:$n[0].Char,ps:0},{n:"startIndex",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2}],tpc:0,def:function(value,startIndex,count){return System.String.indexOf(this,String.fromCharCode(value),startIndex,count)},rt:$n[0].Int32,p:[$n[0].Char,$n[0].Int32,$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"IndexOf",t:8,pi:[{n:"searchValue",pt:$n[0].String,ps:0},{n:"fromIndex",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2}],tpc:0,def:function(searchValue,fromIndex,count){return System.String.indexOf(this,searchValue,fromIndex,count)},rt:$n[0].Int32,p:[$n[0].String,$n[0].Int32,$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"IndexOf",t:8,pi:[{n:"value",pt:$n[0].String,ps:0},{n:"startIndex",pt:$n[0].Int32,ps:1},{n:"comparisonType",pt:$n[0].StringComparison,ps:2}],tpc:0,def:function(value,startIndex,comparisonType){return System.String.indexOf(this,value,startIndex,null,comparisonType)},rt:$n[0].Int32,p:[$n[0].String,$n[0].Int32,$n[0].StringComparison],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"IndexOf",t:8,pi:[{n:"value",pt:$n[0].String,ps:0},{n:"startIndex",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2},{n:"comparisonType",pt:$n[0].StringComparison,ps:3}],tpc:0,def:function(value,startIndex,count,comparisonType){return System.String.indexOf(this,value,startIndex,count,comparisonType)},rt:$n[0].Int32,p:[$n[0].String,$n[0].Int32,$n[0].Int32,$n[0].StringComparison],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"IndexOfAny",t:8,pi:[{n:"anyOf",pt:$n[0].Array.type(System.Char),ps:0}],tpc:0,def:function(anyOf){return System.String.indexOfAny(this,anyOf)},rt:$n[0].Int32,p:[$n[0].Array.type(System.Char)],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"IndexOfAny",t:8,pi:[{n:"anyOf",pt:$n[0].Array.type(System.Char),ps:0},{n:"startIndex",pt:$n[0].Int32,ps:1}],tpc:0,def:function(anyOf,startIndex){return System.String.indexOfAny(this,anyOf,startIndex)},rt:$n[0].Int32,p:[$n[0].Array.type(System.Char),$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"IndexOfAny",t:8,pi:[{n:"anyOf",pt:$n[0].Array.type(System.Char),ps:0},{n:"startIndex",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2}],tpc:0,def:function(anyOf,startIndex,count){return System.String.indexOfAny(this,anyOf,startIndex,count)},rt:$n[0].Int32,p:[$n[0].Array.type(System.Char),$n[0].Int32,$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"Insert",t:8,pi:[{n:"startIndex",pt:$n[0].Int32,ps:0},{n:"value",pt:$n[0].String,ps:1}],tpc:0,def:function(startIndex,value){return System.String.insert(startIndex,this,value)},rt:$n[0].String,p:[$n[0].Int32,$n[0].String]},{a:2,n:"IsNullOrEmpty",is:!0,t:8,pi:[{n:"value",pt:$n[0].String,ps:0}],tpc:0,def:function(value){return System.String.isNullOrEmpty(value)},rt:$n[0].Boolean,p:[$n[0].String],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"IsNullOrWhiteSpace",is:!0,t:8,pi:[{n:"value",pt:$n[0].String,ps:0}],tpc:0,def:function(value){return System.String.isNullOrWhiteSpace(value)},rt:$n[0].Boolean,p:[$n[0].String],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Join",is:!0,t:8,pi:[{n:"separator",pt:$n[0].String,ps:0},{n:"values",pt:$n[3].IEnumerable$1(System.String),ps:1}],tpc:0,def:function(separator,values){return H5.toArray(values).join(separator)},rt:$n[0].String,p:[$n[0].String,$n[3].IEnumerable$1(System.String)]},{a:2,n:"Join",is:!0,t:8,pi:[{n:"separator",pt:$n[0].String,ps:0},{n:"values",pt:$n[3].IEnumerable$1(System.Object),ps:1}],tpc:1,def:function(T,separator,values){return H5.toArray(values).join(separator)},rt:$n[0].String,p:[$n[0].String,$n[3].IEnumerable$1(System.Object)]},{a:2,n:"Join",is:!0,t:8,pi:[{n:"separator",pt:$n[0].String,ps:0},{n:"values",ip:!0,pt:$n[0].Array.type(System.Object),ps:1}],tpc:0,def:function(separator,values){return Array.prototype.slice.call((arguments,1)).join(separator)},rt:$n[0].String,p:[$n[0].String,$n[0].Array.type(System.Object)]},{a:2,n:"Join",is:!0,t:8,pi:[{n:"separator",pt:$n[0].String,ps:0},{n:"value",ip:!0,pt:$n[0].Array.type(System.String),ps:1}],tpc:0,def:function(separator,value){return Array.prototype.slice.call((arguments,1)).join(separator)},rt:$n[0].String,p:[$n[0].String,$n[0].Array.type(System.String)]},{a:2,n:"Join",is:!0,t:8,pi:[{n:"separator",pt:$n[0].String,ps:0},{n:"value",pt:$n[0].Array.type(System.String),ps:1},{n:"startIndex",pt:$n[0].Int32,ps:2},{n:"count",pt:$n[0].Int32,ps:3}],tpc:0,def:function(separator,value,startIndex,count){return value.slice(startIndex,startIndex+count).join(separator)},rt:$n[0].String,p:[$n[0].String,$n[0].Array.type(System.String),$n[0].Int32,$n[0].Int32]},{a:2,n:"LastIndexOf",t:8,pi:[{n:"value",pt:$n[0].Char,ps:0}],tpc:0,def:function(value){return this.lastIndexOf(String.fromCharCode(value))},rt:$n[0].Int32,p:[$n[0].Char],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"LastIndexOf",t:8,pi:[{n:"value",pt:$n[0].String,ps:0}],sn:"lastIndexOf",rt:$n[0].Int32,p:[$n[0].String],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"LastIndexOf",t:8,pi:[{n:"value",pt:$n[0].Char,ps:0},{n:"startIndex",pt:$n[0].Int32,ps:1}],tpc:0,def:function(value,startIndex){return this.lastIndexOf(String.fromCharCode(value),startIndex)},rt:$n[0].Int32,p:[$n[0].Char,$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"LastIndexOf",t:8,pi:[{n:"value",pt:$n[0].String,ps:0},{n:"startIndex",pt:$n[0].Int32,ps:1}],sn:"lastIndexOf",rt:$n[0].Int32,p:[$n[0].String,$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"LastIndexOf",t:8,pi:[{n:"value",pt:$n[0].Char,ps:0},{n:"startIndex",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2}],tpc:0,def:function(value,startIndex,count){return System.String.lastIndexOf(this,String.fromCharCode(value),startIndex,count)},rt:$n[0].Int32,p:[$n[0].Char,$n[0].Int32,$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"LastIndexOf",t:8,pi:[{n:"value",pt:$n[0].String,ps:0},{n:"startIndex",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2}],tpc:0,def:function(value,startIndex,count){return System.String.lastIndexOf(this,value,startIndex,count)},rt:$n[0].Int32,p:[$n[0].String,$n[0].Int32,$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"LastIndexOfAny",t:8,pi:[{n:"anyOf",ip:!0,pt:$n[0].Array.type(System.Char),ps:0}],tpc:0,def:function(anyOf){return System.String.lastIndexOfAny(this,Array.prototype.slice.call((arguments,0)))},rt:$n[0].Int32,p:[$n[0].Array.type(System.Char)],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"LastIndexOfAny",t:8,pi:[{n:"anyOf",pt:$n[0].Array.type(System.Char),ps:0},{n:"startIndex",pt:$n[0].Int32,ps:1}],tpc:0,def:function(anyOf,startIndex){return System.String.lastIndexOfAny(this,anyOf,startIndex)},rt:$n[0].Int32,p:[$n[0].Array.type(System.Char),$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"LastIndexOfAny",t:8,pi:[{n:"anyOf",pt:$n[0].Array.type(System.Char),ps:0},{n:"startIndex",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2}],tpc:0,def:function(anyOf,startIndex,count){return System.String.lastIndexOfAny(this,anyOf,startIndex,count)},rt:$n[0].Int32,p:[$n[0].Array.type(System.Char),$n[0].Int32,$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"PadLeft",t:8,pi:[{n:"totalWidth",pt:$n[0].Int32,ps:0}],tpc:0,def:function(totalWidth){return System.String.alignString(this,totalWidth)},rt:$n[0].String,p:[$n[0].Int32]},{a:2,n:"PadLeft",t:8,pi:[{n:"totalWidth",pt:$n[0].Int32,ps:0},{n:"paddingChar",pt:$n[0].Char,ps:1}],tpc:0,def:function(totalWidth,paddingChar){return System.String.alignString(this,totalWidth,paddingChar)},rt:$n[0].String,p:[$n[0].Int32,$n[0].Char]},{a:2,n:"PadRight",t:8,pi:[{n:"totalWidth",pt:$n[0].Int32,ps:0}],tpc:0,def:function(totalWidth){return System.String.alignString(this,-totalWidth)},rt:$n[0].String,p:[$n[0].Int32]},{a:2,n:"PadRight",t:8,pi:[{n:"totalWidth",pt:$n[0].Int32,ps:0},{n:"paddingChar",pt:$n[0].Char,ps:1}],tpc:0,def:function(totalWidth,paddingChar){return System.String.alignString(this,-totalWidth,paddingChar)},rt:$n[0].String,p:[$n[0].Int32,$n[0].Char]},{a:2,n:"Remove",t:8,pi:[{n:"startIndex",pt:$n[0].Int32,ps:0}],tpc:0,def:function(startIndex){return System.String.remove(this,startIndex)},rt:$n[0].String,p:[$n[0].Int32]},{a:2,n:"Remove",t:8,pi:[{n:"startIndex",pt:$n[0].Int32,ps:0},{n:"count",pt:$n[0].Int32,ps:1}],tpc:0,def:function(startIndex,count){return System.String.remove(this,startIndex,count)},rt:$n[0].String,p:[$n[0].Int32,$n[0].Int32]},{a:2,n:"Replace",t:8,pi:[{n:"oldChar",pt:$n[0].Char,ps:0},{n:"newChar",pt:$n[0].Char,ps:1}],tpc:0,def:function(oldChar,newChar){return System.String.replaceAll(this,String.fromCharCode(oldChar),String.fromCharCode(newChar))},rt:$n[0].String,p:[$n[0].Char,$n[0].Char]},{a:2,n:"Replace",t:8,pi:[{n:"oldValue",pt:$n[0].String,ps:0},{n:"newValue",pt:$n[0].String,ps:1}],tpc:0,def:function(oldValue,newValue){return System.String.replaceAll(this,oldValue,newValue)},rt:$n[0].String,p:[$n[0].String,$n[0].String]},{a:2,n:"Split",t:8,pi:[{n:"separator",ip:!0,pt:$n[0].Array.type(System.Char),ps:0}],tpc:0,def:function(separator){return System.String.split(this,Array.prototype.slice.call((arguments,0)).map(function(i){return String.fromCharCode(i)}))},rt:$n[0].Array.type(System.String),p:[$n[0].Array.type(System.Char)]},{a:2,n:"Split",t:8,pi:[{n:"separator",pt:$n[0].Array.type(System.Char),ps:0},{n:"count",pt:$n[0].Int32,ps:1}],tpc:0,def:function(separator,count){return System.String.split(this,separator.map(function(i){return String.fromCharCode(i)}),count)},rt:$n[0].Array.type(System.String),p:[$n[0].Array.type(System.Char),$n[0].Int32]},{a:2,n:"Split",t:8,pi:[{n:"separator",pt:$n[0].Array.type(System.Char),ps:0},{n:"options",pt:$n[0].StringSplitOptions,ps:1}],tpc:0,def:function(separator,options){return System.String.split(this,separator.map(function(i){return String.fromCharCode(i)}),null,options)},rt:$n[0].Array.type(System.String),p:[$n[0].Array.type(System.Char),$n[0].StringSplitOptions]},{a:2,n:"Split",t:8,pi:[{n:"separator",pt:$n[0].Array.type(System.String),ps:0},{n:"options",pt:$n[0].StringSplitOptions,ps:1}],tpc:0,def:function(separator,options){return System.String.split(this,separator,null,options)},rt:$n[0].Array.type(System.String),p:[$n[0].Array.type(System.String),$n[0].StringSplitOptions]},{a:2,n:"Split",t:8,pi:[{n:"separator",pt:$n[0].Array.type(System.Char),ps:0},{n:"count",pt:$n[0].Int32,ps:1},{n:"options",pt:$n[0].StringSplitOptions,ps:2}],tpc:0,def:function(separator,count,options){return System.String.split(this,separator.map(function(i){return String.fromCharCode(i)}),count,options)},rt:$n[0].Array.type(System.String),p:[$n[0].Array.type(System.Char),$n[0].Int32,$n[0].StringSplitOptions]},{a:2,n:"Split",t:8,pi:[{n:"separator",pt:$n[0].Array.type(System.String),ps:0},{n:"count",pt:$n[0].Int32,ps:1},{n:"options",pt:$n[0].StringSplitOptions,ps:2}],tpc:0,def:function(separator,count,options){return System.String.split(this,separator,count,options)},rt:$n[0].Array.type(System.String),p:[$n[0].Array.type(System.String),$n[0].Int32,$n[0].StringSplitOptions]},{a:2,n:"StartsWith",t:8,pi:[{n:"value",pt:$n[0].String,ps:0}],tpc:0,def:function(value){return System.String.startsWith(this,value)},rt:$n[0].Boolean,p:[$n[0].String],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"StartsWith",t:8,pi:[{n:"value",pt:$n[0].String,ps:0},{n:"comparisonType",pt:$n[0].StringComparison,ps:1}],tpc:0,def:function(value,comparisonType){return System.String.startsWith(this,value,comparisonType)},rt:$n[0].Boolean,p:[$n[0].String,$n[0].StringComparison],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Substring",t:8,pi:[{n:"startIndex",pt:$n[0].Int32,ps:0}],sn:"substr",rt:$n[0].String,p:[$n[0].Int32]},{a:2,n:"Substring",t:8,pi:[{n:"startIndex",pt:$n[0].Int32,ps:0},{n:"length",pt:$n[0].Int32,ps:1}],sn:"substr",rt:$n[0].String,p:[$n[0].Int32,$n[0].Int32]},{a:2,n:"ToCharArray",t:8,tpc:0,def:function(){return $t=this,System.String.toCharArray($t,0,$t.length)},rt:$n[0].Array.type(System.Char)},{a:2,n:"ToCharArray",t:8,pi:[{n:"startIndex",pt:$n[0].Int32,ps:0},{n:"length",pt:$n[0].Int32,ps:1}],tpc:0,def:function(startIndex,length){return System.String.toCharArray(this,startIndex,length)},rt:$n[0].Array.type(System.Char),p:[$n[0].Int32,$n[0].Int32]},{a:2,n:"ToLower",t:8,tpc:0,def:function(){return this.toLowerCase()},rt:$n[0].String},{a:2,n:"ToUpper",t:8,tpc:0,def:function(){return this.toUpperCase()},rt:$n[0].String},{a:2,n:"Trim",t:8,sn:"trim",rt:$n[0].String},{a:2,n:"Trim",t:8,pi:[{n:"trimChars",ip:!0,pt:$n[0].Array.type(System.Char),ps:0}],tpc:0,def:function(trimChars){return System.String.trim(this,Array.prototype.slice.call((arguments,0)))},rt:$n[0].String,p:[$n[0].Array.type(System.Char)]},{a:2,n:"TrimEnd",t:8,tpc:0,def:function(){return System.String.trimEnd(this)},rt:$n[0].String},{a:2,n:"TrimEnd",t:8,pi:[{n:"trimChars",ip:!0,pt:$n[0].Array.type(System.Char),ps:0}],tpc:0,def:function(trimChars){return System.String.trimEnd(this,Array.prototype.slice.call((arguments,0)))},rt:$n[0].String,p:[$n[0].Array.type(System.Char)]},{a:2,n:"TrimStart",t:8,tpc:0,def:function(){return System.String.trimStart(this)},rt:$n[0].String},{a:2,n:"TrimStart",t:8,pi:[{n:"trimChars",ip:!0,pt:$n[0].Array.type(System.Char),ps:0}],tpc:0,def:function(trimChars){return System.String.trimStart(this,Array.prototype.slice.call((arguments,0)))},rt:$n[0].String,p:[$n[0].Array.type(System.Char)]},{a:2,n:"op_Equality",is:!0,t:8,pi:[{n:"s1",pt:$n[0].String,ps:0},{n:"s2",pt:$n[0].String,ps:1}],sn:"op_Equality",rt:$n[0].Boolean,p:[$n[0].String,$n[0].String],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"op_Inequality",is:!0,t:8,pi:[{n:"s1",pt:$n[0].String,ps:0},{n:"s2",pt:$n[0].String,ps:1}],sn:"op_Inequality",rt:$n[0].Boolean,p:[$n[0].String,$n[0].String],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Item",t:16,rt:$n[0].Char,p:[$n[0].Int32],i:!0,ipi:[{n:"index",pt:$n[0].Int32,ps:0}],g:{a:2,n:"get_Item",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0}],tpc:0,def:function(index){return this.charCodeAt(index)},rt:$n[0].Char,p:[$n[0].Int32],box:function($v){return H5.box($v,System.Char,String.fromCharCode,System.Char.getHashCode)}}},{a:2,n:"Length",t:16,rt:$n[0].Int32,g:{a:2,n:"get_Length",t:8,rt:$n[0].Int32,fg:"length",box:function($v){return H5.box($v,System.Int32)}},fn:"length"},{a:2,n:"Empty",is:!0,t:4,rt:$n[0].String,sn:"Empty"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Char,sn:"Item",box:function($v){return H5.box($v,System.Char,String.fromCharCode,System.Char.getHashCode)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Int32,sn:"length",box:function($v){return H5.box($v,System.Int32)}}]}},$n);$m("System.StringComparer",function(){return{att:1048705,a:2,m:[{a:3,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:"Compare",t:8,pi:[{n:"x",pt:$n[0].Object,ps:0},{n:"y",pt:$n[0].Object,ps:1}],sn:"Compare",rt:$n[0].Int32,p:[$n[0].Object,$n[0].Object],box:function($v){return H5.box($v,System.Int32)}},{ab:!0,a:2,n:"Compare",t:8,pi:[{n:"x",pt:$n[0].String,ps:0},{n:"y",pt:$n[0].String,ps:1}],sn:"compare",rt:$n[0].Int32,p:[$n[0].String,$n[0].String],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"Equals",t:8,pi:[{n:"x",pt:$n[0].Object,ps:0},{n:"y",pt:$n[0].Object,ps:1}],sn:"Equals",rt:$n[0].Boolean,p:[$n[0].Object,$n[0].Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ab:!0,a:2,n:"Equals",t:8,pi:[{n:"x",pt:$n[0].String,ps:0},{n:"y",pt:$n[0].String,ps:1}],sn:"equals2",rt:$n[0].Boolean,p:[$n[0].String,$n[0].String],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"GetHashCode",t:8,pi:[{n:"obj",pt:$n[0].Object,ps:0}],sn:"GetHashCode",rt:$n[0].Int32,p:[$n[0].Object],box:function($v){return H5.box($v,System.Int32)}},{ab:!0,a:2,n:"GetHashCode",t:8,pi:[{n:"obj",pt:$n[0].String,ps:0}],sn:"getHashCode2",rt:$n[0].Int32,p:[$n[0].String],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"Ordinal",is:!0,t:16,rt:$n[0].StringComparer,g:{a:2,n:"get_Ordinal",t:8,rt:$n[0].StringComparer,fg:"Ordinal",is:!0},fn:"Ordinal"},{a:2,n:"OrdinalIgnoreCase",is:!0,t:16,rt:$n[0].StringComparer,g:{a:2,n:"get_OrdinalIgnoreCase",t:8,rt:$n[0].StringComparer,fg:"OrdinalIgnoreCase",is:!0},fn:"OrdinalIgnoreCase"},{a:1,n:"_ordinal",is:!0,t:4,rt:$n[0].StringComparer,sn:"_ordinal",ro:!0},{a:1,n:"_ordinalIgnoreCase",is:!0,t:4,rt:$n[0].StringComparer,sn:"_ordinalIgnoreCase",ro:!0}]}},$n);$m("System.OrdinalComparer",function(){return{att:1048832,a:4,m:[{a:4,n:".ctor",t:1,p:[$n[0].Boolean],pi:[{n:"ignoreCase",pt:$n[0].Boolean,ps:0}],sn:"ctor"},{ov:!0,a:2,n:"Compare",t:8,pi:[{n:"x",pt:$n[0].String,ps:0},{n:"y",pt:$n[0].String,ps:1}],sn:"compare",rt:$n[0].Int32,p:[$n[0].String,$n[0].String],box:function($v){return H5.box($v,System.Int32)}},{ov:!0,a:2,n:"Equals",t:8,pi:[{n:"obj",pt:$n[0].Object,ps:0}],sn:"equals",rt:$n[0].Boolean,p:[$n[0].Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ov:!0,a:2,n:"Equals",t:8,pi:[{n:"x",pt:$n[0].String,ps:0},{n:"y",pt:$n[0].String,ps:1}],sn:"equals2",rt:$n[0].Boolean,p:[$n[0].String,$n[0].String],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ov:!0,a:2,n:"GetHashCode",t:8,sn:"getHashCode",rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}},{ov:!0,a:2,n:"GetHashCode",t:8,pi:[{n:"obj",pt:$n[0].String,ps:0}],sn:"getHashCode2",rt:$n[0].Int32,p:[$n[0].String],box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"_ignoreCase",t:4,rt:$n[0].Boolean,sn:"_ignoreCase",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}}]}},$n);$m("System.TimeSpan",function(){return{att:1048841,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].Int64],pi:[{n:"ticks",pt:$n[0].Int64,ps:0}],sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].Int32,$n[0].Int32,$n[0].Int32],pi:[{n:"hours",pt:$n[0].Int32,ps:0},{n:"minutes",pt:$n[0].Int32,ps:1},{n:"seconds",pt:$n[0].Int32,ps:2}],sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].Int32,$n[0].Int32,$n[0].Int32,$n[0].Int32],pi:[{n:"days",pt:$n[0].Int32,ps:0},{n:"hours",pt:$n[0].Int32,ps:1},{n:"minutes",pt:$n[0].Int32,ps:2},{n:"seconds",pt:$n[0].Int32,ps:3}],sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].Int32,$n[0].Int32,$n[0].Int32,$n[0].Int32,$n[0].Int32],pi:[{n:"days",pt:$n[0].Int32,ps:0},{n:"hours",pt:$n[0].Int32,ps:1},{n:"minutes",pt:$n[0].Int32,ps:2},{n:"seconds",pt:$n[0].Int32,ps:3},{n:"milliseconds",pt:$n[0].Int32,ps:4}],sn:"ctor"},{a:2,n:"Add",t:8,pi:[{n:"ts",pt:$n[0].TimeSpan,ps:0}],sn:"add",rt:$n[0].TimeSpan,p:[$n[0].TimeSpan]},{a:2,n:"Compare",is:!0,t:8,pi:[{n:"t1",pt:$n[0].TimeSpan,ps:0},{n:"t2",pt:$n[0].TimeSpan,ps:1}],tpc:0,def:function(t1,t2){return t1.compareTo(t2)},rt:$n[0].Int32,p:[$n[0].TimeSpan,$n[0].TimeSpan],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"CompareTo",t:8,pi:[{n:"value",pt:$n[0].Object,ps:0}],sn:"compareTo",rt:$n[0].Int32,p:[$n[0].Object],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"CompareTo",t:8,pi:[{n:"value",pt:$n[0].TimeSpan,ps:0}],sn:"compareTo",rt:$n[0].Int32,p:[$n[0].TimeSpan],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"Duration",t:8,sn:"duration",rt:$n[0].TimeSpan},{a:2,n:"Equals",t:8,pi:[{n:"obj",pt:$n[0].TimeSpan,ps:0}],sn:"equalsT",rt:$n[0].Boolean,p:[$n[0].TimeSpan],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Equals",is:!0,t:8,pi:[{n:"t1",pt:$n[0].TimeSpan,ps:0},{n:"t2",pt:$n[0].TimeSpan,ps:1}],tpc:0,def:function(t1,t2){return t1.ticks.eq(t2.ticks)},rt:$n[0].Boolean,p:[$n[0].TimeSpan,$n[0].TimeSpan],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Format",t:8,pi:[{n:"format",pt:$n[0].String,ps:0}],sn:"toString",rt:$n[0].String,p:[$n[0].String]},{a:2,n:"Format",t:8,pi:[{n:"format",pt:$n[0].String,ps:0},{n:"provider",pt:$n[0].IFormatProvider,ps:1}],sn:"toString",rt:$n[0].String,p:[$n[0].String,$n[0].IFormatProvider]},{a:2,n:"FromDays",is:!0,t:8,pi:[{n:"value",pt:$n[0].Double,ps:0}],sn:"fromDays",rt:$n[0].TimeSpan,p:[$n[0].Double]},{a:2,n:"FromHours",is:!0,t:8,pi:[{n:"value",pt:$n[0].Double,ps:0}],sn:"fromHours",rt:$n[0].TimeSpan,p:[$n[0].Double]},{a:2,n:"FromMilliseconds",is:!0,t:8,pi:[{n:"value",pt:$n[0].Double,ps:0}],sn:"fromMilliseconds",rt:$n[0].TimeSpan,p:[$n[0].Double]},{a:2,n:"FromMinutes",is:!0,t:8,pi:[{n:"value",pt:$n[0].Double,ps:0}],sn:"fromMinutes",rt:$n[0].TimeSpan,p:[$n[0].Double]},{a:2,n:"FromSeconds",is:!0,t:8,pi:[{n:"value",pt:$n[0].Double,ps:0}],sn:"fromSeconds",rt:$n[0].TimeSpan,p:[$n[0].Double]},{a:2,n:"FromTicks",is:!0,t:8,pi:[{n:"value",pt:$n[0].Int64,ps:0}],sn:"fromTicks",rt:$n[0].TimeSpan,p:[$n[0].Int64]},{a:2,n:"Negate",t:8,sn:"negate",rt:$n[0].TimeSpan},{a:2,n:"Parse",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0}],sn:"parse",rt:$n[0].TimeSpan,p:[$n[0].String]},{a:2,n:"Parse",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0},{n:"provider",pt:$n[0].IFormatProvider,ps:1}],sn:"parse",rt:$n[0].TimeSpan,p:[$n[0].String,$n[0].IFormatProvider]},{a:2,n:"Subtract",t:8,pi:[{n:"ts",pt:$n[0].TimeSpan,ps:0}],sn:"subtract",rt:$n[0].TimeSpan,p:[$n[0].TimeSpan]},{a:4,n:"TimeToTicks",is:!0,t:8,pi:[{n:"hour",pt:$n[0].Int32,ps:0},{n:"minute",pt:$n[0].Int32,ps:1},{n:"second",pt:$n[0].Int32,ps:2}],tpc:0,def:function(hour,minute,second){return TimeToTicks(hour,minute,second)},rt:$n[0].Int64,p:[$n[0].Int32,$n[0].Int32,$n[0].Int32]},{a:2,n:"ToString",t:8,pi:[{n:"format",pt:$n[0].String,ps:0}],sn:"toString",rt:$n[0].String,p:[$n[0].String]},{a:2,n:"ToString",t:8,pi:[{n:"format",pt:$n[0].String,ps:0},{n:"provider",pt:$n[0].IFormatProvider,ps:1}],sn:"format",rt:$n[0].String,p:[$n[0].String,$n[0].IFormatProvider]},{a:2,n:"TryParse",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0},{n:"result",out:!0,pt:$n[0].TimeSpan,ps:1}],tpc:0,def:function(s,result){return System.TimeSpan.tryParse(s,null,result)},rt:$n[0].Boolean,p:[$n[0].String,$n[0].TimeSpan],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"TryParse",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0},{n:"provider",pt:$n[0].IFormatProvider,ps:1},{n:"result",out:!0,pt:$n[0].TimeSpan,ps:2}],tpc:0,def:function(s,provider,result){return System.TimeSpan.tryParse(s,provider,result)},rt:$n[0].Boolean,p:[$n[0].String,$n[0].IFormatProvider,$n[0].TimeSpan],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"op_Addition",is:!0,t:8,pi:[{n:"t1",pt:$n[0].TimeSpan,ps:0},{n:"t2",pt:$n[0].TimeSpan,ps:1}],tpc:0,def:function(t1,t2){return System.TimeSpan.add(t1,t2)},rt:$n[0].TimeSpan,p:[$n[0].TimeSpan,$n[0].TimeSpan]},{a:2,n:"op_Equality",is:!0,t:8,pi:[{n:"t1",pt:$n[0].TimeSpan,ps:0},{n:"t2",pt:$n[0].TimeSpan,ps:1}],tpc:0,def:function(t1,t2){return System.TimeSpan.eq(t1,t2)},rt:$n[0].Boolean,p:[$n[0].TimeSpan,$n[0].TimeSpan],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"op_GreaterThan",is:!0,t:8,pi:[{n:"t1",pt:$n[0].TimeSpan,ps:0},{n:"t2",pt:$n[0].TimeSpan,ps:1}],tpc:0,def:function(t1,t2){return System.TimeSpan.gt(t1,t2)},rt:$n[0].Boolean,p:[$n[0].TimeSpan,$n[0].TimeSpan],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"op_GreaterThanOrEqual",is:!0,t:8,pi:[{n:"t1",pt:$n[0].TimeSpan,ps:0},{n:"t2",pt:$n[0].TimeSpan,ps:1}],tpc:0,def:function(t1,t2){return System.TimeSpan.gte(t1,t2)},rt:$n[0].Boolean,p:[$n[0].TimeSpan,$n[0].TimeSpan],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"op_Inequality",is:!0,t:8,pi:[{n:"t1",pt:$n[0].TimeSpan,ps:0},{n:"t2",pt:$n[0].TimeSpan,ps:1}],tpc:0,def:function(t1,t2){return System.TimeSpan.neq(t1,t2)},rt:$n[0].Boolean,p:[$n[0].TimeSpan,$n[0].TimeSpan],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"op_LessThan",is:!0,t:8,pi:[{n:"t1",pt:$n[0].TimeSpan,ps:0},{n:"t2",pt:$n[0].TimeSpan,ps:1}],tpc:0,def:function(t1,t2){return System.TimeSpan.lt(t1,t2)},rt:$n[0].Boolean,p:[$n[0].TimeSpan,$n[0].TimeSpan],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"op_LessThanOrEqual",is:!0,t:8,pi:[{n:"t1",pt:$n[0].TimeSpan,ps:0},{n:"t2",pt:$n[0].TimeSpan,ps:1}],tpc:0,def:function(t1,t2){return System.TimeSpan.lte(t1,t2)},rt:$n[0].Boolean,p:[$n[0].TimeSpan,$n[0].TimeSpan],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"op_Subtraction",is:!0,t:8,pi:[{n:"t1",pt:$n[0].TimeSpan,ps:0},{n:"t2",pt:$n[0].TimeSpan,ps:1}],tpc:0,def:function(t1,t2){return System.TimeSpan.sub(t1,t2)},rt:$n[0].TimeSpan,p:[$n[0].TimeSpan,$n[0].TimeSpan]},{a:2,n:"op_UnaryNegation",is:!0,t:8,pi:[{n:"t",pt:$n[0].TimeSpan,ps:0}],tpc:0,def:function(t){return System.TimeSpan.neg(t)},rt:$n[0].TimeSpan,p:[$n[0].TimeSpan]},{a:2,n:"op_UnaryPlus",is:!0,t:8,pi:[{n:"t",pt:$n[0].TimeSpan,ps:0}],tpc:0,def:function(t){return System.TimeSpan.plus(t)},rt:$n[0].TimeSpan,p:[$n[0].TimeSpan]},{a:2,n:"Days",t:16,rt:$n[0].Int32,g:{a:2,n:"get_Days",t:8,tpc:0,def:function(){return this.getDays()},rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}}},{a:2,n:"Hours",t:16,rt:$n[0].Int32,g:{a:2,n:"get_Hours",t:8,tpc:0,def:function(){return this.getHours()},rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}}},{a:2,n:"Milliseconds",t:16,rt:$n[0].Int32,g:{a:2,n:"get_Milliseconds",t:8,tpc:0,def:function(){return this.getMilliseconds()},rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}}},{a:2,n:"Minutes",t:16,rt:$n[0].Int32,g:{a:2,n:"get_Minutes",t:8,tpc:0,def:function(){return this.getMinutes()},rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}}},{a:2,n:"Seconds",t:16,rt:$n[0].Int32,g:{a:2,n:"get_Seconds",t:8,tpc:0,def:function(){return this.getSeconds()},rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}}},{a:2,n:"Ticks",t:16,rt:$n[0].Int64,g:{a:2,n:"get_Ticks",t:8,tpc:0,def:function(){return this.getTicks()},rt:$n[0].Int64}},{a:2,n:"TotalDays",t:16,rt:$n[0].Double,g:{a:2,n:"get_TotalDays",t:8,tpc:0,def:function(){return this.getTotalDays()},rt:$n[0].Double,box:function($v){return H5.box($v,System.Double,System.Double.format,System.Double.getHashCode)}}},{a:2,n:"TotalHours",t:16,rt:$n[0].Double,g:{a:2,n:"get_TotalHours",t:8,tpc:0,def:function(){return this.getTotalHours()},rt:$n[0].Double,box:function($v){return H5.box($v,System.Double,System.Double.format,System.Double.getHashCode)}}},{a:2,n:"TotalMilliseconds",t:16,rt:$n[0].Double,g:{a:2,n:"get_TotalMilliseconds",t:8,tpc:0,def:function(){return this.getTotalMilliseconds()},rt:$n[0].Double,box:function($v){return H5.box($v,System.Double,System.Double.format,System.Double.getHashCode)}}},{a:2,n:"TotalMinutes",t:16,rt:$n[0].Double,g:{a:2,n:"get_TotalMinutes",t:8,tpc:0,def:function(){return this.getTotalMinutes()},rt:$n[0].Double,box:function($v){return H5.box($v,System.Double,System.Double.format,System.Double.getHashCode)}}},{a:2,n:"TotalSeconds",t:16,rt:$n[0].Double,g:{a:2,n:"get_TotalSeconds",t:8,tpc:0,def:function(){return this.getTotalSeconds()},rt:$n[0].Double,box:function($v){return H5.box($v,System.Double,System.Double.format,System.Double.getHashCode)}}},{a:2,n:"MaxValue",is:!0,t:4,rt:$n[0].TimeSpan,sn:"maxValue",ro:!0},{a:2,n:"MinValue",is:!0,t:4,rt:$n[0].TimeSpan,sn:"minValue",ro:!0},{a:2,n:"TicksPerDay",is:!0,t:4,rt:$n[0].Int64,sn:"TicksPerDay"},{a:2,n:"TicksPerHour",is:!0,t:4,rt:$n[0].Int64,sn:"TicksPerHour"},{a:2,n:"TicksPerMillisecond",is:!0,t:4,rt:$n[0].Int64,sn:"TicksPerMillisecond"},{a:2,n:"TicksPerMinute",is:!0,t:4,rt:$n[0].Int64,sn:"TicksPerMinute"},{a:2,n:"TicksPerSecond",is:!0,t:4,rt:$n[0].Int64,sn:"TicksPerSecond"},{a:2,n:"Zero",is:!0,t:4,rt:$n[0].TimeSpan,sn:"zero",ro:!0},{a:4,n:"_ticks",t:4,rt:$n[0].Int64,sn:"_ticks"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Int32,sn:"Days",box:function($v){return H5.box($v,System.Int32)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Int32,sn:"Hours",box:function($v){return H5.box($v,System.Int32)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Int32,sn:"Milliseconds",box:function($v){return H5.box($v,System.Int32)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Int32,sn:"Minutes",box:function($v){return H5.box($v,System.Int32)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Int32,sn:"Seconds",box:function($v){return H5.box($v,System.Int32)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Int64,sn:"Ticks"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Double,sn:"TotalDays",box:function($v){return H5.box($v,System.Double,System.Double.format,System.Double.getHashCode)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Double,sn:"TotalHours",box:function($v){return H5.box($v,System.Double,System.Double.format,System.Double.getHashCode)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Double,sn:"TotalMilliseconds",box:function($v){return H5.box($v,System.Double,System.Double.format,System.Double.getHashCode)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Double,sn:"TotalMinutes",box:function($v){return H5.box($v,System.Double,System.Double.format,System.Double.getHashCode)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Double,sn:"TotalSeconds",box:function($v){return H5.box($v,System.Double,System.Double.format,System.Double.getHashCode)}}]}},$n);$m("System.Tuple$1",function(T1){return{att:1048833,a:2,m:[{a:2,n:".ctor",t:1,p:[T1],pi:[{n:"item1",pt:T1,ps:0}],def:function(item1){return{Item1:item1}}},{ov:!0,a:2,n:"Equals",t:8,pi:[{n:"o",pt:$n[0].Object,ps:0}],tpc:0,def:function(o){return H5.objectEquals(this,o,!0)},rt:$n[0].Boolean,p:[$n[0].Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ov:!0,a:2,n:"GetHashCode",t:8,tpc:0,def:function(){return H5.getHashCode(this,!1,!0)},rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"Item1",t:16,rt:T1,g:{a:2,n:"get_Item1",t:8,tpc:0,def:function(){return this.Item1},rt:T1}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:T1,sn:"Item1"}]}},$n);$m("System.Tuple$2",function(T1,T2){return{att:1048833,a:2,m:[{a:2,n:".ctor",t:1,p:[T1,T2],pi:[{n:"item1",pt:T1,ps:0},{n:"item2",pt:T2,ps:1}],def:function(item1,item2){return{Item1:item1,Item2:item2}}},{ov:!0,a:2,n:"Equals",t:8,pi:[{n:"o",pt:$n[0].Object,ps:0}],tpc:0,def:function(o){return H5.objectEquals(this,o,!0)},rt:$n[0].Boolean,p:[$n[0].Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ov:!0,a:2,n:"GetHashCode",t:8,tpc:0,def:function(){return H5.getHashCode(this,!1,!0)},rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"Item1",t:16,rt:T1,g:{a:2,n:"get_Item1",t:8,tpc:0,def:function(){return this.Item1},rt:T1}},{a:2,n:"Item2",t:16,rt:T2,g:{a:2,n:"get_Item2",t:8,tpc:0,def:function(){return this.Item2},rt:T2}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:T1,sn:"Item1"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:T2,sn:"Item2"}]}},$n);$m("System.Tuple$3",function(T1,T2,T3){return{att:1048833,a:2,m:[{a:2,n:".ctor",t:1,p:[T1,T2,T3],pi:[{n:"item1",pt:T1,ps:0},{n:"item2",pt:T2,ps:1},{n:"item3",pt:T3,ps:2}],def:function(item1,item2,item3){return{Item1:item1,Item2:item2,Item3:item3}}},{ov:!0,a:2,n:"Equals",t:8,pi:[{n:"o",pt:$n[0].Object,ps:0}],tpc:0,def:function(o){return H5.objectEquals(this,o,!0)},rt:$n[0].Boolean,p:[$n[0].Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ov:!0,a:2,n:"GetHashCode",t:8,tpc:0,def:function(){return H5.getHashCode(this,!1,!0)},rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"Item1",t:16,rt:T1,g:{a:2,n:"get_Item1",t:8,tpc:0,def:function(){return this.Item1},rt:T1}},{a:2,n:"Item2",t:16,rt:T2,g:{a:2,n:"get_Item2",t:8,tpc:0,def:function(){return this.Item2},rt:T2}},{a:2,n:"Item3",t:16,rt:T3,g:{a:2,n:"get_Item3",t:8,tpc:0,def:function(){return this.Item3},rt:T3}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:T1,sn:"Item1"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:T2,sn:"Item2"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:T3,sn:"Item3"}]}},$n);$m("System.Tuple$4",function(T1,T2,T3,T4){return{att:1048833,a:2,m:[{a:2,n:".ctor",t:1,p:[T1,T2,T3,T4],pi:[{n:"item1",pt:T1,ps:0},{n:"item2",pt:T2,ps:1},{n:"item3",pt:T3,ps:2},{n:"item4",pt:T4,ps:3}],def:function(item1,item2,item3,item4){return{Item1:item1,Item2:item2,Item3:item3,Item4:item4}}},{ov:!0,a:2,n:"Equals",t:8,pi:[{n:"o",pt:$n[0].Object,ps:0}],tpc:0,def:function(o){return H5.objectEquals(this,o,!0)},rt:$n[0].Boolean,p:[$n[0].Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ov:!0,a:2,n:"GetHashCode",t:8,tpc:0,def:function(){return H5.getHashCode(this,!1,!0)},rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"Item1",t:16,rt:T1,g:{a:2,n:"get_Item1",t:8,tpc:0,def:function(){return this.Item1},rt:T1}},{a:2,n:"Item2",t:16,rt:T2,g:{a:2,n:"get_Item2",t:8,tpc:0,def:function(){return this.Item2},rt:T2}},{a:2,n:"Item3",t:16,rt:T3,g:{a:2,n:"get_Item3",t:8,tpc:0,def:function(){return this.Item3},rt:T3}},{a:2,n:"Item4",t:16,rt:T4,g:{a:2,n:"get_Item4",t:8,tpc:0,def:function(){return this.Item4},rt:T4}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:T1,sn:"Item1"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:T2,sn:"Item2"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:T3,sn:"Item3"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:T4,sn:"Item4"}]}},$n);$m("System.Tuple$5",function(T1,T2,T3,T4,T5){return{att:1048833,a:2,m:[{a:2,n:".ctor",t:1,p:[T1,T2,T3,T4,T5],pi:[{n:"item1",pt:T1,ps:0},{n:"item2",pt:T2,ps:1},{n:"item3",pt:T3,ps:2},{n:"item4",pt:T4,ps:3},{n:"item5",pt:T5,ps:4}],def:function(item1,item2,item3,item4,item5){return{Item1:item1,Item2:item2,Item3:item3,Item4:item4,Item5:item5}}},{ov:!0,a:2,n:"Equals",t:8,pi:[{n:"o",pt:$n[0].Object,ps:0}],tpc:0,def:function(o){return H5.objectEquals(this,o,!0)},rt:$n[0].Boolean,p:[$n[0].Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ov:!0,a:2,n:"GetHashCode",t:8,tpc:0,def:function(){return H5.getHashCode(this,!1,!0)},rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"Item1",t:16,rt:T1,g:{a:2,n:"get_Item1",t:8,tpc:0,def:function(){return this.Item1},rt:T1}},{a:2,n:"Item2",t:16,rt:T2,g:{a:2,n:"get_Item2",t:8,tpc:0,def:function(){return this.Item2},rt:T2}},{a:2,n:"Item3",t:16,rt:T3,g:{a:2,n:"get_Item3",t:8,tpc:0,def:function(){return this.Item3},rt:T3}},{a:2,n:"Item4",t:16,rt:T4,g:{a:2,n:"get_Item4",t:8,tpc:0,def:function(){return this.Item4},rt:T4}},{a:2,n:"Item5",t:16,rt:T5,g:{a:2,n:"get_Item5",t:8,tpc:0,def:function(){return this.Item5},rt:T5}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:T1,sn:"Item1"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:T2,sn:"Item2"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:T3,sn:"Item3"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:T4,sn:"Item4"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:T5,sn:"Item5"}]}},$n);$m("System.Tuple$6",function(T1,T2,T3,T4,T5,T6){return{att:1048833,a:2,m:[{a:2,n:".ctor",t:1,p:[T1,T2,T3,T4,T5,T6],pi:[{n:"item1",pt:T1,ps:0},{n:"item2",pt:T2,ps:1},{n:"item3",pt:T3,ps:2},{n:"item4",pt:T4,ps:3},{n:"item5",pt:T5,ps:4},{n:"item6",pt:T6,ps:5}],def:function(item1,item2,item3,item4,item5,item6){return{Item1:item1,Item2:item2,Item3:item3,Item4:item4,Item5:item5,Item6:item6}}},{ov:!0,a:2,n:"Equals",t:8,pi:[{n:"o",pt:$n[0].Object,ps:0}],tpc:0,def:function(o){return H5.objectEquals(this,o,!0)},rt:$n[0].Boolean,p:[$n[0].Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ov:!0,a:2,n:"GetHashCode",t:8,tpc:0,def:function(){return H5.getHashCode(this,!1,!0)},rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"Item1",t:16,rt:T1,g:{a:2,n:"get_Item1",t:8,tpc:0,def:function(){return this.Item1},rt:T1}},{a:2,n:"Item2",t:16,rt:T2,g:{a:2,n:"get_Item2",t:8,tpc:0,def:function(){return this.Item2},rt:T2}},{a:2,n:"Item3",t:16,rt:T3,g:{a:2,n:"get_Item3",t:8,tpc:0,def:function(){return this.Item3},rt:T3}},{a:2,n:"Item4",t:16,rt:T4,g:{a:2,n:"get_Item4",t:8,tpc:0,def:function(){return this.Item4},rt:T4}},{a:2,n:"Item5",t:16,rt:T5,g:{a:2,n:"get_Item5",t:8,tpc:0,def:function(){return this.Item5},rt:T5}},{a:2,n:"Item6",t:16,rt:T6,g:{a:2,n:"get_Item6",t:8,tpc:0,def:function(){return this.Item6},rt:T6}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:T1,sn:"Item1"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:T2,sn:"Item2"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:T3,sn:"Item3"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:T4,sn:"Item4"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:T5,sn:"Item5"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:T6,sn:"Item6"}]}},$n);$m("System.Tuple$7",function(T1,T2,T3,T4,T5,T6,T7){return{att:1048833,a:2,m:[{a:2,n:".ctor",t:1,p:[T1,T2,T3,T4,T5,T6,T7],pi:[{n:"item1",pt:T1,ps:0},{n:"item2",pt:T2,ps:1},{n:"item3",pt:T3,ps:2},{n:"item4",pt:T4,ps:3},{n:"item5",pt:T5,ps:4},{n:"item6",pt:T6,ps:5},{n:"item7",pt:T7,ps:6}],def:function(item1,item2,item3,item4,item5,item6,item7){return{Item1:item1,Item2:item2,Item3:item3,Item4:item4,Item5:item5,Item6:item6,Item7:item7}}},{ov:!0,a:2,n:"Equals",t:8,pi:[{n:"o",pt:$n[0].Object,ps:0}],tpc:0,def:function(o){return H5.objectEquals(this,o,!0)},rt:$n[0].Boolean,p:[$n[0].Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ov:!0,a:2,n:"GetHashCode",t:8,tpc:0,def:function(){return H5.getHashCode(this,!1,!0)},rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"Item1",t:16,rt:T1,g:{a:2,n:"get_Item1",t:8,tpc:0,def:function(){return this.Item1},rt:T1}},{a:2,n:"Item2",t:16,rt:T2,g:{a:2,n:"get_Item2",t:8,tpc:0,def:function(){return this.Item2},rt:T2}},{a:2,n:"Item3",t:16,rt:T3,g:{a:2,n:"get_Item3",t:8,tpc:0,def:function(){return this.Item3},rt:T3}},{a:2,n:"Item4",t:16,rt:T4,g:{a:2,n:"get_Item4",t:8,tpc:0,def:function(){return this.Item4},rt:T4}},{a:2,n:"Item5",t:16,rt:T5,g:{a:2,n:"get_Item5",t:8,tpc:0,def:function(){return this.Item5},rt:T5}},{a:2,n:"Item6",t:16,rt:T6,g:{a:2,n:"get_Item6",t:8,tpc:0,def:function(){return this.Item6},rt:T6}},{a:2,n:"Item7",t:16,rt:T7,g:{a:2,n:"get_Item7",t:8,tpc:0,def:function(){return this.Item7},rt:T7}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:T1,sn:"Item1"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:T2,sn:"Item2"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:T3,sn:"Item3"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:T4,sn:"Item4"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:T5,sn:"Item5"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:T6,sn:"Item6"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:T7,sn:"Item7"}]}},$n);$m("System.Tuple$8",function(T1,T2,T3,T4,T5,T6,T7,TRest){return{att:1048833,a:2,m:[{a:2,n:".ctor",t:1,p:[T1,T2,T3,T4,T5,T6,T7,TRest],pi:[{n:"item1",pt:T1,ps:0},{n:"item2",pt:T2,ps:1},{n:"item3",pt:T3,ps:2},{n:"item4",pt:T4,ps:3},{n:"item5",pt:T5,ps:4},{n:"item6",pt:T6,ps:5},{n:"item7",pt:T7,ps:6},{n:"rest",pt:TRest,ps:7}],def:function(item1,item2,item3,item4,item5,item6,item7,rest){return{Item1:item1,Item2:item2,Item3:item3,Item4:item4,Item5:item5,Item6:item6,Item7:item7,rest:rest}}},{ov:!0,a:2,n:"Equals",t:8,pi:[{n:"o",pt:$n[0].Object,ps:0}],tpc:0,def:function(o){return H5.objectEquals(this,o,!0)},rt:$n[0].Boolean,p:[$n[0].Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ov:!0,a:2,n:"GetHashCode",t:8,tpc:0,def:function(){return H5.getHashCode(this,!1,!0)},rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"Item1",t:16,rt:T1,g:{a:2,n:"get_Item1",t:8,tpc:0,def:function(){return this.Item1},rt:T1}},{a:2,n:"Item2",t:16,rt:T2,g:{a:2,n:"get_Item2",t:8,tpc:0,def:function(){return this.Item2},rt:T2}},{a:2,n:"Item3",t:16,rt:T3,g:{a:2,n:"get_Item3",t:8,tpc:0,def:function(){return this.Item3},rt:T3}},{a:2,n:"Item4",t:16,rt:T4,g:{a:2,n:"get_Item4",t:8,tpc:0,def:function(){return this.Item4},rt:T4}},{a:2,n:"Item5",t:16,rt:T5,g:{a:2,n:"get_Item5",t:8,tpc:0,def:function(){return this.Item5},rt:T5}},{a:2,n:"Item6",t:16,rt:T6,g:{a:2,n:"get_Item6",t:8,tpc:0,def:function(){return this.Item6},rt:T6}},{a:2,n:"Item7",t:16,rt:T7,g:{a:2,n:"get_Item7",t:8,tpc:0,def:function(){return this.Item7},rt:T7}},{a:2,n:"Rest",t:16,rt:TRest,g:{a:2,n:"get_Rest",t:8,tpc:0,def:function(){return this.rest},rt:TRest}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:T1,sn:"Item1"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:T2,sn:"Item2"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:T3,sn:"Item3"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:T4,sn:"Item4"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:T5,sn:"Item5"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:T6,sn:"Item6"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:T7,sn:"Item7"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:TRest,sn:"Rest"}]}},$n);$m("System.Tuple",function(){return{att:1048961,a:2,s:!0,m:[{a:2,n:"Create",is:!0,t:8,pi:[{n:"item1",pt:System.Object,ps:0}],tpc:1,def:function(T1,item1){return{Item1:item1}},rt:$n[0].Tuple$1(System.Object),p:[System.Object]},{a:2,n:"Create",is:!0,t:8,pi:[{n:"item1",pt:System.Object,ps:0},{n:"item2",pt:System.Object,ps:1}],tpc:2,def:function(T1,T2,item1,item2){return{Item1:item1,Item2:item2}},rt:$n[0].Tuple$2(System.Object,System.Object),p:[System.Object,System.Object]},{a:2,n:"Create",is:!0,t:8,pi:[{n:"item1",pt:System.Object,ps:0},{n:"item2",pt:System.Object,ps:1},{n:"item3",pt:System.Object,ps:2}],tpc:3,def:function(T1,T2,T3,item1,item2,item3){return{Item1:item1,Item2:item2,Item3:item3}},rt:$n[0].Tuple$3(System.Object,System.Object,System.Object),p:[System.Object,System.Object,System.Object]},{a:2,n:"Create",is:!0,t:8,pi:[{n:"item1",pt:System.Object,ps:0},{n:"item2",pt:System.Object,ps:1},{n:"item3",pt:System.Object,ps:2},{n:"item4",pt:System.Object,ps:3}],tpc:4,def:function(T1,T2,T3,T4,item1,item2,item3,item4){return{Item1:item1,Item2:item2,Item3:item3,Item4:item4}},rt:$n[0].Tuple$4(System.Object,System.Object,System.Object,System.Object),p:[System.Object,System.Object,System.Object,System.Object]},{a:2,n:"Create",is:!0,t:8,pi:[{n:"item1",pt:System.Object,ps:0},{n:"item2",pt:System.Object,ps:1},{n:"item3",pt:System.Object,ps:2},{n:"item4",pt:System.Object,ps:3},{n:"item5",pt:System.Object,ps:4}],tpc:5,def:function(T1,T2,T3,T4,T5,item1,item2,item3,item4,item5){return{Item1:item1,Item2:item2,Item3:item3,Item4:item4,Item5:item5}},rt:$n[0].Tuple$5(System.Object,System.Object,System.Object,System.Object,System.Object),p:[System.Object,System.Object,System.Object,System.Object,System.Object]},{a:2,n:"Create",is:!0,t:8,pi:[{n:"item1",pt:System.Object,ps:0},{n:"item2",pt:System.Object,ps:1},{n:"item3",pt:System.Object,ps:2},{n:"item4",pt:System.Object,ps:3},{n:"item5",pt:System.Object,ps:4},{n:"item6",pt:System.Object,ps:5}],tpc:6,def:function(T1,T2,T3,T4,T5,T6,item1,item2,item3,item4,item5,item6){return{Item1:item1,Item2:item2,Item3:item3,Item4:item4,Item5:item5,Item6:item6}},rt:$n[0].Tuple$6(System.Object,System.Object,System.Object,System.Object,System.Object,System.Object),p:[System.Object,System.Object,System.Object,System.Object,System.Object,System.Object]},{a:2,n:"Create",is:!0,t:8,pi:[{n:"item1",pt:System.Object,ps:0},{n:"item2",pt:System.Object,ps:1},{n:"item3",pt:System.Object,ps:2},{n:"item4",pt:System.Object,ps:3},{n:"item5",pt:System.Object,ps:4},{n:"item6",pt:System.Object,ps:5},{n:"item7",pt:System.Object,ps:6}],tpc:7,def:function(T1,T2,T3,T4,T5,T6,T7,item1,item2,item3,item4,item5,item6,item7){return{Item1:item1,Item2:item2,Item3:item3,Item4:item4,Item5:item5,Item6:item6,Item7:item7}},rt:$n[0].Tuple$7(System.Object,System.Object,System.Object,System.Object,System.Object,System.Object,System.Object),p:[System.Object,System.Object,System.Object,System.Object,System.Object,System.Object,System.Object]},{a:2,n:"Create",is:!0,t:8,pi:[{n:"item1",pt:System.Object,ps:0},{n:"item2",pt:System.Object,ps:1},{n:"item3",pt:System.Object,ps:2},{n:"item4",pt:System.Object,ps:3},{n:"item5",pt:System.Object,ps:4},{n:"item6",pt:System.Object,ps:5},{n:"item7",pt:System.Object,ps:6},{n:"rest",pt:System.Object,ps:7}],tpc:8,def:function(T1,T2,T3,T4,T5,T6,T7,TRest,item1,item2,item3,item4,item5,item6,item7,rest){return{Item1:item1,Item2:item2,Item3:item3,Item4:item4,Item5:item5,Item6:item6,Item7:item7,rest:rest}},rt:$n[0].Tuple$8(System.Object,System.Object,System.Object,System.Object,System.Object,System.Object,System.Object,System.Object),p:[System.Object,System.Object,System.Object,System.Object,System.Object,System.Object,System.Object,System.Object]}]}},$n);$m("System.TypeCode",function(){return{att:257,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:"Boolean",is:!0,t:4,rt:$n[0].TypeCode,sn:"Boolean",box:function($v){return H5.box($v,System.TypeCode,System.Enum.toStringFn(System.TypeCode))}},{a:2,n:"Byte",is:!0,t:4,rt:$n[0].TypeCode,sn:"Byte",box:function($v){return H5.box($v,System.TypeCode,System.Enum.toStringFn(System.TypeCode))}},{a:2,n:"Char",is:!0,t:4,rt:$n[0].TypeCode,sn:"Char",box:function($v){return H5.box($v,System.TypeCode,System.Enum.toStringFn(System.TypeCode))}},{a:2,n:"DBNull",is:!0,t:4,rt:$n[0].TypeCode,sn:"DBNull",box:function($v){return H5.box($v,System.TypeCode,System.Enum.toStringFn(System.TypeCode))}},{a:2,n:"DateTime",is:!0,t:4,rt:$n[0].TypeCode,sn:"DateTime",box:function($v){return H5.box($v,System.TypeCode,System.Enum.toStringFn(System.TypeCode))}},{a:2,n:"Decimal",is:!0,t:4,rt:$n[0].TypeCode,sn:"Decimal",box:function($v){return H5.box($v,System.TypeCode,System.Enum.toStringFn(System.TypeCode))}},{a:2,n:"Double",is:!0,t:4,rt:$n[0].TypeCode,sn:"Double",box:function($v){return H5.box($v,System.TypeCode,System.Enum.toStringFn(System.TypeCode))}},{a:2,n:"Empty",is:!0,t:4,rt:$n[0].TypeCode,sn:"Empty",box:function($v){return H5.box($v,System.TypeCode,System.Enum.toStringFn(System.TypeCode))}},{a:2,n:"Int16",is:!0,t:4,rt:$n[0].TypeCode,sn:"Int16",box:function($v){return H5.box($v,System.TypeCode,System.Enum.toStringFn(System.TypeCode))}},{a:2,n:"Int32",is:!0,t:4,rt:$n[0].TypeCode,sn:"Int32",box:function($v){return H5.box($v,System.TypeCode,System.Enum.toStringFn(System.TypeCode))}},{a:2,n:"Int64",is:!0,t:4,rt:$n[0].TypeCode,sn:"Int64",box:function($v){return H5.box($v,System.TypeCode,System.Enum.toStringFn(System.TypeCode))}},{a:2,n:"Object",is:!0,t:4,rt:$n[0].TypeCode,sn:"Object",box:function($v){return H5.box($v,System.TypeCode,System.Enum.toStringFn(System.TypeCode))}},{a:2,n:"SByte",is:!0,t:4,rt:$n[0].TypeCode,sn:"SByte",box:function($v){return H5.box($v,System.TypeCode,System.Enum.toStringFn(System.TypeCode))}},{a:2,n:"Single",is:!0,t:4,rt:$n[0].TypeCode,sn:"Single",box:function($v){return H5.box($v,System.TypeCode,System.Enum.toStringFn(System.TypeCode))}},{a:2,n:"String",is:!0,t:4,rt:$n[0].TypeCode,sn:"String",box:function($v){return H5.box($v,System.TypeCode,System.Enum.toStringFn(System.TypeCode))}},{a:2,n:"UInt16",is:!0,t:4,rt:$n[0].TypeCode,sn:"UInt16",box:function($v){return H5.box($v,System.TypeCode,System.Enum.toStringFn(System.TypeCode))}},{a:2,n:"UInt32",is:!0,t:4,rt:$n[0].TypeCode,sn:"UInt32",box:function($v){return H5.box($v,System.TypeCode,System.Enum.toStringFn(System.TypeCode))}},{a:2,n:"UInt64",is:!0,t:4,rt:$n[0].TypeCode,sn:"UInt64",box:function($v){return H5.box($v,System.TypeCode,System.Enum.toStringFn(System.TypeCode))}}]}},$n);$m("System.TypeCodeValues",function(){return{att:1048960,a:4,s:!0,m:[{a:2,n:"Boolean",is:!0,t:4,rt:$n[0].String,sn:"Boolean"},{a:2,n:"Byte",is:!0,t:4,rt:$n[0].String,sn:"Byte"},{a:2,n:"Char",is:!0,t:4,rt:$n[0].String,sn:"Char"},{a:2,n:"DBNull",is:!0,t:4,rt:$n[0].String,sn:"DBNull"},{a:2,n:"DateTime",is:!0,t:4,rt:$n[0].String,sn:"DateTime"},{a:2,n:"Decimal",is:!0,t:4,rt:$n[0].String,sn:"Decimal"},{a:2,n:"Double",is:!0,t:4,rt:$n[0].String,sn:"Double"},{a:2,n:"Empty",is:!0,t:4,rt:$n[0].String,sn:"Empty"},{a:2,n:"Int16",is:!0,t:4,rt:$n[0].String,sn:"Int16"},{a:2,n:"Int32",is:!0,t:4,rt:$n[0].String,sn:"Int32"},{a:2,n:"Int64",is:!0,t:4,rt:$n[0].String,sn:"Int64"},{a:2,n:"Object",is:!0,t:4,rt:$n[0].String,sn:"Object"},{a:2,n:"SByte",is:!0,t:4,rt:$n[0].String,sn:"SByte"},{a:2,n:"Single",is:!0,t:4,rt:$n[0].String,sn:"Single"},{a:2,n:"String",is:!0,t:4,rt:$n[0].String,sn:"String"},{a:2,n:"UInt16",is:!0,t:4,rt:$n[0].String,sn:"UInt16"},{a:2,n:"UInt32",is:!0,t:4,rt:$n[0].String,sn:"UInt32"},{a:2,n:"UInt64",is:!0,t:4,rt:$n[0].String,sn:"UInt64"}]}},$n);$m("System.UInt16",function(){return{att:1048841,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,def:function(){return Number}},{a:1,n:".ctor",t:1,p:[$n[0].Int32],pi:[{n:"i",pt:$n[0].Int32,ps:0}],def:function(i){return Number}},{a:2,n:"CompareTo",t:8,pi:[{n:"obj",pt:$n[0].Object,ps:0}],tpc:0,def:function(obj){return H5.compare(this,obj)},rt:$n[0].Int32,p:[$n[0].Object],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"CompareTo",t:8,pi:[{n:"other",pt:$n[0].UInt16,ps:0}],tpc:0,def:function(other){return H5.compare(this,other)},rt:$n[0].Int32,p:[$n[0].UInt16],box:function($v){return H5.box($v,System.Int32)}},{ov:!0,a:2,n:"Equals",t:8,pi:[{n:"other",pt:$n[0].Object,ps:0}],tpc:0,def:function(other){return System.UInt16.equals(this,other)},rt:$n[0].Boolean,p:[$n[0].Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Equals",t:8,pi:[{n:"other",pt:$n[0].UInt16,ps:0}],tpc:0,def:function(other){return this===other},rt:$n[0].Boolean,p:[$n[0].UInt16],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Format",t:8,pi:[{n:"format",pt:$n[0].String,ps:0}],tpc:0,def:function(format){return System.UInt16.format(this,format)},rt:$n[0].String,p:[$n[0].String]},{a:2,n:"Format",t:8,pi:[{n:"format",pt:$n[0].String,ps:0},{n:"provider",pt:$n[0].IFormatProvider,ps:1}],tpc:0,def:function(format,provider){return System.UInt16.format(this,format,provider)},rt:$n[0].String,p:[$n[0].String,$n[0].IFormatProvider]},{a:2,n:"Parse",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0}],tpc:0,def:function(s){return System.UInt16.parse(s)},rt:$n[0].UInt16,p:[$n[0].String],box:function($v){return H5.box($v,System.UInt16)}},{a:2,n:"Parse",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0},{n:"radix",pt:$n[0].Int32,ps:1}],tpc:0,def:function(s,radix){return System.UInt16.parse(s,radix)},rt:$n[0].UInt16,p:[$n[0].String,$n[0].Int32],box:function($v){return H5.box($v,System.UInt16)}},{a:2,n:"ToString",t:8,pi:[{n:"radix",pt:$n[0].Int32,ps:0}],sn:"toString",rt:$n[0].String,p:[$n[0].Int32]},{a:2,n:"ToString",t:8,pi:[{n:"format",pt:$n[0].String,ps:0}],tpc:0,def:function(format){return System.UInt16.format(this,format)},rt:$n[0].String,p:[$n[0].String]},{a:2,n:"ToString",t:8,pi:[{n:"format",pt:$n[0].String,ps:0},{n:"provider",pt:$n[0].IFormatProvider,ps:1}],tpc:0,def:function(format,provider){return System.UInt16.format(this,format,provider)},rt:$n[0].String,p:[$n[0].String,$n[0].IFormatProvider]},{a:2,n:"TryParse",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0},{n:"result",out:!0,pt:$n[0].UInt16,ps:1}],tpc:0,def:function(s,result){return System.UInt16.tryParse(s,result)},rt:$n[0].Boolean,p:[$n[0].String,$n[0].UInt16],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"TryParse",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0},{n:"result",out:!0,pt:$n[0].UInt16,ps:1},{n:"radix",pt:$n[0].Int32,ps:2}],tpc:0,def:function(s,result,radix){return System.UInt16.tryParse(s,result,radix)},rt:$n[0].Boolean,p:[$n[0].String,$n[0].UInt16,$n[0].Int32],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"MaxValue",is:!0,t:4,rt:$n[0].UInt16,sn:"MaxValue",box:function($v){return H5.box($v,System.UInt16)}},{a:2,n:"MinValue",is:!0,t:4,rt:$n[0].UInt16,sn:"MinValue",box:function($v){return H5.box($v,System.UInt16)}}]}},$n);$m("System.UInt32",function(){return{att:1048841,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,def:function(){return Number}},{a:1,n:".ctor",t:1,p:[$n[0].Int32],pi:[{n:"i",pt:$n[0].Int32,ps:0}],def:function(i){return Number}},{a:2,n:"CompareTo",t:8,pi:[{n:"obj",pt:$n[0].Object,ps:0}],tpc:0,def:function(obj){return H5.compare(this,obj)},rt:$n[0].Int32,p:[$n[0].Object],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"CompareTo",t:8,pi:[{n:"other",pt:$n[0].UInt32,ps:0}],tpc:0,def:function(other){return H5.compare(this,other)},rt:$n[0].Int32,p:[$n[0].UInt32],box:function($v){return H5.box($v,System.Int32)}},{ov:!0,a:2,n:"Equals",t:8,pi:[{n:"other",pt:$n[0].Object,ps:0}],tpc:0,def:function(other){return System.UInt32.equals(this,other)},rt:$n[0].Boolean,p:[$n[0].Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Equals",t:8,pi:[{n:"other",pt:$n[0].UInt32,ps:0}],tpc:0,def:function(other){return this===other},rt:$n[0].Boolean,p:[$n[0].UInt32],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Format",t:8,pi:[{n:"format",pt:$n[0].String,ps:0}],tpc:0,def:function(format){return System.UInt32.format(this,format)},rt:$n[0].String,p:[$n[0].String]},{a:2,n:"Format",t:8,pi:[{n:"format",pt:$n[0].String,ps:0},{n:"provider",pt:$n[0].IFormatProvider,ps:1}],tpc:0,def:function(format,provider){return System.UInt32.format(this,format,provider)},rt:$n[0].String,p:[$n[0].String,$n[0].IFormatProvider]},{a:2,n:"Parse",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0}],tpc:0,def:function(s){return System.UInt32.parse(s)},rt:$n[0].UInt32,p:[$n[0].String],box:function($v){return H5.box($v,System.UInt32)}},{a:2,n:"Parse",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0},{n:"radix",pt:$n[0].Int32,ps:1}],tpc:0,def:function(s,radix){return System.UInt32.parse(s,radix)},rt:$n[0].UInt32,p:[$n[0].String,$n[0].Int32],box:function($v){return H5.box($v,System.UInt32)}},{a:2,n:"ToString",t:8,pi:[{n:"radix",pt:$n[0].Int32,ps:0}],sn:"toString",rt:$n[0].String,p:[$n[0].Int32]},{a:2,n:"ToString",t:8,pi:[{n:"format",pt:$n[0].String,ps:0}],tpc:0,def:function(format){return System.UInt32.format(this,format)},rt:$n[0].String,p:[$n[0].String]},{a:2,n:"ToString",t:8,pi:[{n:"format",pt:$n[0].String,ps:0},{n:"provider",pt:$n[0].IFormatProvider,ps:1}],tpc:0,def:function(format,provider){return System.UInt32.format(this,format,provider)},rt:$n[0].String,p:[$n[0].String,$n[0].IFormatProvider]},{a:2,n:"TryParse",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0},{n:"result",out:!0,pt:$n[0].UInt32,ps:1}],tpc:0,def:function(s,result){return System.UInt32.tryParse(s,result)},rt:$n[0].Boolean,p:[$n[0].String,$n[0].UInt32],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"TryParse",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0},{n:"result",out:!0,pt:$n[0].UInt32,ps:1},{n:"radix",pt:$n[0].Int32,ps:2}],tpc:0,def:function(s,result,radix){return System.UInt32.tryParse(s,result,radix)},rt:$n[0].Boolean,p:[$n[0].String,$n[0].UInt32,$n[0].Int32],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"MaxValue",is:!0,t:4,rt:$n[0].UInt32,sn:"MaxValue",box:function($v){return H5.box($v,System.UInt32)}},{a:2,n:"MinValue",is:!0,t:4,rt:$n[0].UInt32,sn:"MinValue",box:function($v){return H5.box($v,System.UInt32)}}]}},$n);$m("System.UInt64",function(){return{att:1048841,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:1,n:".ctor",t:1,p:[$n[0].Int32],pi:[{n:"i",pt:$n[0].Int32,ps:0}],sn:"ctor"},{a:2,n:"CompareTo",t:8,pi:[{n:"obj",pt:$n[0].Object,ps:0}],sn:"compareTo",rt:$n[0].Int32,p:[$n[0].Object],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"CompareTo",t:8,pi:[{n:"other",pt:$n[0].UInt64,ps:0}],sn:"compareTo",rt:$n[0].Int32,p:[$n[0].UInt64],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"Equals",t:8,pi:[{n:"other",pt:$n[0].UInt64,ps:0}],sn:"equalsT",rt:$n[0].Boolean,p:[$n[0].UInt64],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Format",t:8,pi:[{n:"format",pt:$n[0].String,ps:0}],sn:"format",rt:$n[0].String,p:[$n[0].String]},{a:2,n:"Format",t:8,pi:[{n:"format",pt:$n[0].String,ps:0},{n:"provider",pt:$n[0].IFormatProvider,ps:1}],sn:"format",rt:$n[0].String,p:[$n[0].String,$n[0].IFormatProvider]},{a:2,n:"Parse",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0}],tpc:0,def:function(s){return System.UInt64.parse(s)},rt:$n[0].UInt64,p:[$n[0].String]},{a:2,n:"ToString",t:8,pi:[{n:"radix",pt:$n[0].Int32,ps:0}],sn:"toString",rt:$n[0].String,p:[$n[0].Int32]},{a:2,n:"ToString",t:8,pi:[{n:"format",pt:$n[0].String,ps:0}],sn:"toString",rt:$n[0].String,p:[$n[0].String]},{a:2,n:"ToString",t:8,pi:[{n:"format",pt:$n[0].String,ps:0},{n:"provider",pt:$n[0].IFormatProvider,ps:1}],sn:"format",rt:$n[0].String,p:[$n[0].String,$n[0].IFormatProvider]},{a:2,n:"TryParse",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0},{n:"result",out:!0,pt:$n[0].UInt64,ps:1}],tpc:0,def:function(s,result){return System.UInt64.tryParse(s,result)},rt:$n[0].Boolean,p:[$n[0].String,$n[0].UInt64],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"op_Explicit",is:!0,t:8,pi:[{n:"value",pt:$n[0].Double,ps:0}],sn:"op_Explicit",rt:$n[0].UInt64,p:[$n[0].Double]},{a:2,n:"op_Explicit",is:!0,t:8,pi:[{n:"value",pt:$n[0].Single,ps:0}],sn:"op_Explicit",rt:$n[0].UInt64,p:[$n[0].Single]},{a:2,n:"op_Explicit",is:!0,t:8,pi:[{n:"value",pt:$n[0].UInt64,ps:0}],sn:"op_Explicit",rt:$n[0].Byte,p:[$n[0].UInt64],box:function($v){return H5.box($v,System.Byte)}},{a:2,n:"op_Explicit",is:!0,t:8,pi:[{n:"value",pt:$n[0].UInt64,ps:0}],sn:"op_Explicit",rt:$n[0].Char,p:[$n[0].UInt64],box:function($v){return H5.box($v,System.Char,String.fromCharCode,System.Char.getHashCode)}},{a:2,n:"op_Explicit",is:!0,t:8,pi:[{n:"value",pt:$n[0].UInt64,ps:0}],sn:"op_Explicit",rt:$n[0].Double,p:[$n[0].UInt64],box:function($v){return H5.box($v,System.Double,System.Double.format,System.Double.getHashCode)}},{a:2,n:"op_Explicit",is:!0,t:8,pi:[{n:"value",pt:$n[0].UInt64,ps:0}],sn:"op_Explicit",rt:$n[0].Int16,p:[$n[0].UInt64],box:function($v){return H5.box($v,System.Int16)}},{a:2,n:"op_Explicit",is:!0,t:8,pi:[{n:"value",pt:$n[0].UInt64,ps:0}],sn:"op_Explicit",rt:$n[0].Int32,p:[$n[0].UInt64],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"op_Explicit",is:!0,t:8,pi:[{n:"value",pt:$n[0].UInt64,ps:0}],sn:"op_Explicit",rt:$n[0].SByte,p:[$n[0].UInt64],box:function($v){return H5.box($v,System.SByte)}},{a:2,n:"op_Explicit",is:!0,t:8,pi:[{n:"value",pt:$n[0].UInt64,ps:0}],sn:"op_Explicit",rt:$n[0].Single,p:[$n[0].UInt64],box:function($v){return H5.box($v,System.Single,System.Single.format,System.Single.getHashCode)}},{a:2,n:"op_Explicit",is:!0,t:8,pi:[{n:"value",pt:$n[0].UInt64,ps:0}],sn:"op_Explicit",rt:$n[0].UInt16,p:[$n[0].UInt64],box:function($v){return H5.box($v,System.UInt16)}},{a:2,n:"op_Explicit",is:!0,t:8,pi:[{n:"value",pt:$n[0].UInt64,ps:0}],sn:"op_Explicit",rt:$n[0].UInt32,p:[$n[0].UInt64],box:function($v){return H5.box($v,System.UInt32)}},{a:2,n:"op_Implicit",is:!0,t:8,pi:[{n:"value",pt:$n[0].Byte,ps:0}],sn:"op_Implicit",rt:$n[0].UInt64,p:[$n[0].Byte]},{a:2,n:"op_Implicit",is:!0,t:8,pi:[{n:"value",pt:$n[0].Char,ps:0}],sn:"op_Implicit",rt:$n[0].UInt64,p:[$n[0].Char]},{a:2,n:"op_Implicit",is:!0,t:8,pi:[{n:"value",pt:$n[0].Int16,ps:0}],sn:"op_Implicit",rt:$n[0].UInt64,p:[$n[0].Int16]},{a:2,n:"op_Implicit",is:!0,t:8,pi:[{n:"value",pt:$n[0].Int32,ps:0}],sn:"op_Implicit",rt:$n[0].UInt64,p:[$n[0].Int32]},{a:2,n:"op_Implicit",is:!0,t:8,pi:[{n:"value",pt:$n[0].SByte,ps:0}],sn:"op_Implicit",rt:$n[0].UInt64,p:[$n[0].SByte]},{a:2,n:"op_Implicit",is:!0,t:8,pi:[{n:"value",pt:$n[0].UInt16,ps:0}],sn:"op_Implicit",rt:$n[0].UInt64,p:[$n[0].UInt16]},{a:2,n:"op_Implicit",is:!0,t:8,pi:[{n:"value",pt:$n[0].UInt32,ps:0}],sn:"op_Implicit",rt:$n[0].UInt64,p:[$n[0].UInt32]},{a:2,n:"MaxValue",is:!0,t:4,rt:$n[0].UInt64,sn:"MaxValue"},{a:2,n:"MinValue",is:!0,t:4,rt:$n[0].UInt64,sn:"MinValue"}]}},$n);$m("System.Uri",function(){return{att:1048577,a:2,m:[{a:2,n:".ctor",t:1,p:[$n[0].String],pi:[{n:"uriString",pt:$n[0].String,ps:0}],sn:"ctor"},{a:2,n:"op_Equality",is:!0,t:8,pi:[{n:"uri1",pt:$n[0].Uri,ps:0},{n:"uri2",pt:$n[0].Uri,ps:1}],tpc:0,def:function(uri1,uri2){return System.Uri.equals(uri1,uri2)},rt:$n[0].Boolean,p:[$n[0].Uri,$n[0].Uri],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"op_Inequality",is:!0,t:8,pi:[{n:"uri1",pt:$n[0].Uri,ps:0},{n:"uri2",pt:$n[0].Uri,ps:1}],tpc:0,def:function(uri1,uri2){return System.Uri.notEquals(uri1,uri2)},rt:$n[0].Boolean,p:[$n[0].Uri,$n[0].Uri],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"AbsoluteUri",t:16,rt:$n[0].String,g:{a:2,n:"get_AbsoluteUri",t:8,tpc:0,def:function(){return this.getAbsoluteUri()},rt:$n[0].String}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"AbsoluteUri"}]}},$n);$m("System.ITupleInternal",function(){return{att:1048736,a:4,m:[{ab:!0,a:2,n:"GetHashCode",t:8,pi:[{n:"comparer",pt:$n[6].IEqualityComparer,ps:0}],sn:"System$ITupleInternal$GetHashCode",rt:$n[0].Int32,p:[$n[6].IEqualityComparer],box:function($v){return H5.box($v,System.Int32)}},{ab:!0,a:2,n:"ToStringEnd",t:8,sn:"System$ITupleInternal$ToStringEnd",rt:$n[0].String},{ab:!0,a:2,n:"Size",t:16,rt:$n[0].Int32,g:{ab:!0,a:2,n:"get_Size",t:8,rt:$n[0].Int32,fg:"System$ITupleInternal$Size",box:function($v){return H5.box($v,System.Int32)}},fn:"System$ITupleInternal$Size"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Int32,sn:"System$ITupleInternal$Size",box:function($v){return H5.box($v,System.Int32)}}]}},$n);$m("System.ValueTuple$1",function(T1){return{att:1048841,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[T1],pi:[{n:"item1",pt:T1,ps:0}],sn:"$ctor1"},{a:2,n:"CompareTo",t:8,pi:[{n:"other",pt:$n[0].ValueTuple$1(T1),ps:0}],sn:"compareTo",rt:$n[0].Int32,p:[$n[0].ValueTuple$1(T1)],box:function($v){return H5.box($v,System.Int32)}},{ov:!0,a:2,n:"Equals",t:8,pi:[{n:"obj",pt:$n[0].Object,ps:0}],sn:"equals",rt:$n[0].Boolean,p:[$n[0].Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Equals",t:8,pi:[{n:"other",pt:$n[0].ValueTuple$1(T1),ps:0}],sn:"equalsT",rt:$n[0].Boolean,p:[$n[0].ValueTuple$1(T1)],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ov:!0,a:2,n:"GetHashCode",t:8,sn:"getHashCode",rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}},{ov:!0,a:2,n:"ToString",t:8,sn:"toString",rt:$n[0].String},{a:1,n:"s_t1Comparer",is:!0,t:16,rt:$n[3].EqualityComparer$1(T1),g:{a:1,n:"get_s_t1Comparer",t:8,rt:$n[3].EqualityComparer$1(T1),fg:"s_t1Comparer",is:!0},fn:"s_t1Comparer"},{a:2,n:"Item1",t:4,rt:T1,sn:"Item1"}]}},$n);$m("System.ValueTuple$2",function(T1,T2){return{att:1048841,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[T1,T2],pi:[{n:"item1",pt:T1,ps:0},{n:"item2",pt:T2,ps:1}],sn:"$ctor1"},{a:2,n:"CompareTo",t:8,pi:[{n:"other",pt:$n[0].ValueTuple$2(T1,T2),ps:0}],sn:"compareTo",rt:$n[0].Int32,p:[$n[0].ValueTuple$2(T1,T2)],box:function($v){return H5.box($v,System.Int32)}},{ov:!0,a:2,n:"Equals",t:8,pi:[{n:"obj",pt:$n[0].Object,ps:0}],sn:"equals",rt:$n[0].Boolean,p:[$n[0].Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Equals",t:8,pi:[{n:"other",pt:$n[0].ValueTuple$2(T1,T2),ps:0}],sn:"equalsT",rt:$n[0].Boolean,p:[$n[0].ValueTuple$2(T1,T2)],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ov:!0,a:2,n:"GetHashCode",t:8,sn:"getHashCode",rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"GetHashCodeCore",t:8,pi:[{n:"comparer",pt:$n[6].IEqualityComparer,ps:0}],sn:"GetHashCodeCore",rt:$n[0].Int32,p:[$n[6].IEqualityComparer],box:function($v){return H5.box($v,System.Int32)}},{ov:!0,a:2,n:"ToString",t:8,sn:"toString",rt:$n[0].String},{a:1,n:"s_t1Comparer",is:!0,t:16,rt:$n[3].EqualityComparer$1(T1),g:{a:1,n:"get_s_t1Comparer",t:8,rt:$n[3].EqualityComparer$1(T1),fg:"s_t1Comparer",is:!0},fn:"s_t1Comparer"},{a:1,n:"s_t2Comparer",is:!0,t:16,rt:$n[3].EqualityComparer$1(T2),g:{a:1,n:"get_s_t2Comparer",t:8,rt:$n[3].EqualityComparer$1(T2),fg:"s_t2Comparer",is:!0},fn:"s_t2Comparer"},{a:2,n:"Item1",t:4,rt:T1,sn:"Item1"},{a:2,n:"Item2",t:4,rt:T2,sn:"Item2"}]}},$n);$m("System.ValueTuple$3",function(T1,T2,T3){return{att:1048841,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[T1,T2,T3],pi:[{n:"item1",pt:T1,ps:0},{n:"item2",pt:T2,ps:1},{n:"item3",pt:T3,ps:2}],sn:"$ctor1"},{a:2,n:"CompareTo",t:8,pi:[{n:"other",pt:$n[0].ValueTuple$3(T1,T2,T3),ps:0}],sn:"compareTo",rt:$n[0].Int32,p:[$n[0].ValueTuple$3(T1,T2,T3)],box:function($v){return H5.box($v,System.Int32)}},{ov:!0,a:2,n:"Equals",t:8,pi:[{n:"obj",pt:$n[0].Object,ps:0}],sn:"equals",rt:$n[0].Boolean,p:[$n[0].Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Equals",t:8,pi:[{n:"other",pt:$n[0].ValueTuple$3(T1,T2,T3),ps:0}],sn:"equalsT",rt:$n[0].Boolean,p:[$n[0].ValueTuple$3(T1,T2,T3)],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ov:!0,a:2,n:"GetHashCode",t:8,sn:"getHashCode",rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"GetHashCodeCore",t:8,pi:[{n:"comparer",pt:$n[6].IEqualityComparer,ps:0}],sn:"GetHashCodeCore",rt:$n[0].Int32,p:[$n[6].IEqualityComparer],box:function($v){return H5.box($v,System.Int32)}},{ov:!0,a:2,n:"ToString",t:8,sn:"toString",rt:$n[0].String},{a:1,n:"s_t1Comparer",is:!0,t:16,rt:$n[3].EqualityComparer$1(T1),g:{a:1,n:"get_s_t1Comparer",t:8,rt:$n[3].EqualityComparer$1(T1),fg:"s_t1Comparer",is:!0},fn:"s_t1Comparer"},{a:1,n:"s_t2Comparer",is:!0,t:16,rt:$n[3].EqualityComparer$1(T2),g:{a:1,n:"get_s_t2Comparer",t:8,rt:$n[3].EqualityComparer$1(T2),fg:"s_t2Comparer",is:!0},fn:"s_t2Comparer"},{a:1,n:"s_t3Comparer",is:!0,t:16,rt:$n[3].EqualityComparer$1(T3),g:{a:1,n:"get_s_t3Comparer",t:8,rt:$n[3].EqualityComparer$1(T3),fg:"s_t3Comparer",is:!0},fn:"s_t3Comparer"},{a:2,n:"Item1",t:4,rt:T1,sn:"Item1"},{a:2,n:"Item2",t:4,rt:T2,sn:"Item2"},{a:2,n:"Item3",t:4,rt:T3,sn:"Item3"}]}},$n);$m("System.ValueTuple$4",function(T1,T2,T3,T4){return{att:1048841,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[T1,T2,T3,T4],pi:[{n:"item1",pt:T1,ps:0},{n:"item2",pt:T2,ps:1},{n:"item3",pt:T3,ps:2},{n:"item4",pt:T4,ps:3}],sn:"$ctor1"},{a:2,n:"CompareTo",t:8,pi:[{n:"other",pt:$n[0].ValueTuple$4(T1,T2,T3,T4),ps:0}],sn:"compareTo",rt:$n[0].Int32,p:[$n[0].ValueTuple$4(T1,T2,T3,T4)],box:function($v){return H5.box($v,System.Int32)}},{ov:!0,a:2,n:"Equals",t:8,pi:[{n:"obj",pt:$n[0].Object,ps:0}],sn:"equals",rt:$n[0].Boolean,p:[$n[0].Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Equals",t:8,pi:[{n:"other",pt:$n[0].ValueTuple$4(T1,T2,T3,T4),ps:0}],sn:"equalsT",rt:$n[0].Boolean,p:[$n[0].ValueTuple$4(T1,T2,T3,T4)],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ov:!0,a:2,n:"GetHashCode",t:8,sn:"getHashCode",rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"GetHashCodeCore",t:8,pi:[{n:"comparer",pt:$n[6].IEqualityComparer,ps:0}],sn:"GetHashCodeCore",rt:$n[0].Int32,p:[$n[6].IEqualityComparer],box:function($v){return H5.box($v,System.Int32)}},{ov:!0,a:2,n:"ToString",t:8,sn:"toString",rt:$n[0].String},{a:1,n:"s_t1Comparer",is:!0,t:16,rt:$n[3].EqualityComparer$1(T1),g:{a:1,n:"get_s_t1Comparer",t:8,rt:$n[3].EqualityComparer$1(T1),fg:"s_t1Comparer",is:!0},fn:"s_t1Comparer"},{a:1,n:"s_t2Comparer",is:!0,t:16,rt:$n[3].EqualityComparer$1(T2),g:{a:1,n:"get_s_t2Comparer",t:8,rt:$n[3].EqualityComparer$1(T2),fg:"s_t2Comparer",is:!0},fn:"s_t2Comparer"},{a:1,n:"s_t3Comparer",is:!0,t:16,rt:$n[3].EqualityComparer$1(T3),g:{a:1,n:"get_s_t3Comparer",t:8,rt:$n[3].EqualityComparer$1(T3),fg:"s_t3Comparer",is:!0},fn:"s_t3Comparer"},{a:1,n:"s_t4Comparer",is:!0,t:16,rt:$n[3].EqualityComparer$1(T4),g:{a:1,n:"get_s_t4Comparer",t:8,rt:$n[3].EqualityComparer$1(T4),fg:"s_t4Comparer",is:!0},fn:"s_t4Comparer"},{a:2,n:"Item1",t:4,rt:T1,sn:"Item1"},{a:2,n:"Item2",t:4,rt:T2,sn:"Item2"},{a:2,n:"Item3",t:4,rt:T3,sn:"Item3"},{a:2,n:"Item4",t:4,rt:T4,sn:"Item4"}]}},$n);$m("System.ValueTuple$5",function(T1,T2,T3,T4,T5){return{att:1048841,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[T1,T2,T3,T4,T5],pi:[{n:"item1",pt:T1,ps:0},{n:"item2",pt:T2,ps:1},{n:"item3",pt:T3,ps:2},{n:"item4",pt:T4,ps:3},{n:"item5",pt:T5,ps:4}],sn:"$ctor1"},{a:2,n:"CompareTo",t:8,pi:[{n:"other",pt:$n[0].ValueTuple$5(T1,T2,T3,T4,T5),ps:0}],sn:"compareTo",rt:$n[0].Int32,p:[$n[0].ValueTuple$5(T1,T2,T3,T4,T5)],box:function($v){return H5.box($v,System.Int32)}},{ov:!0,a:2,n:"Equals",t:8,pi:[{n:"obj",pt:$n[0].Object,ps:0}],sn:"equals",rt:$n[0].Boolean,p:[$n[0].Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Equals",t:8,pi:[{n:"other",pt:$n[0].ValueTuple$5(T1,T2,T3,T4,T5),ps:0}],sn:"equalsT",rt:$n[0].Boolean,p:[$n[0].ValueTuple$5(T1,T2,T3,T4,T5)],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ov:!0,a:2,n:"GetHashCode",t:8,sn:"getHashCode",rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"GetHashCodeCore",t:8,pi:[{n:"comparer",pt:$n[6].IEqualityComparer,ps:0}],sn:"GetHashCodeCore",rt:$n[0].Int32,p:[$n[6].IEqualityComparer],box:function($v){return H5.box($v,System.Int32)}},{ov:!0,a:2,n:"ToString",t:8,sn:"toString",rt:$n[0].String},{a:1,n:"s_t1Comparer",is:!0,t:16,rt:$n[3].EqualityComparer$1(T1),g:{a:1,n:"get_s_t1Comparer",t:8,rt:$n[3].EqualityComparer$1(T1),fg:"s_t1Comparer",is:!0},fn:"s_t1Comparer"},{a:1,n:"s_t2Comparer",is:!0,t:16,rt:$n[3].EqualityComparer$1(T2),g:{a:1,n:"get_s_t2Comparer",t:8,rt:$n[3].EqualityComparer$1(T2),fg:"s_t2Comparer",is:!0},fn:"s_t2Comparer"},{a:1,n:"s_t3Comparer",is:!0,t:16,rt:$n[3].EqualityComparer$1(T3),g:{a:1,n:"get_s_t3Comparer",t:8,rt:$n[3].EqualityComparer$1(T3),fg:"s_t3Comparer",is:!0},fn:"s_t3Comparer"},{a:1,n:"s_t4Comparer",is:!0,t:16,rt:$n[3].EqualityComparer$1(T4),g:{a:1,n:"get_s_t4Comparer",t:8,rt:$n[3].EqualityComparer$1(T4),fg:"s_t4Comparer",is:!0},fn:"s_t4Comparer"},{a:1,n:"s_t5Comparer",is:!0,t:16,rt:$n[3].EqualityComparer$1(T5),g:{a:1,n:"get_s_t5Comparer",t:8,rt:$n[3].EqualityComparer$1(T5),fg:"s_t5Comparer",is:!0},fn:"s_t5Comparer"},{a:2,n:"Item1",t:4,rt:T1,sn:"Item1"},{a:2,n:"Item2",t:4,rt:T2,sn:"Item2"},{a:2,n:"Item3",t:4,rt:T3,sn:"Item3"},{a:2,n:"Item4",t:4,rt:T4,sn:"Item4"},{a:2,n:"Item5",t:4,rt:T5,sn:"Item5"}]}},$n);$m("System.ValueTuple$6",function(T1,T2,T3,T4,T5,T6){return{att:1048841,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[T1,T2,T3,T4,T5,T6],pi:[{n:"item1",pt:T1,ps:0},{n:"item2",pt:T2,ps:1},{n:"item3",pt:T3,ps:2},{n:"item4",pt:T4,ps:3},{n:"item5",pt:T5,ps:4},{n:"item6",pt:T6,ps:5}],sn:"$ctor1"},{a:2,n:"CompareTo",t:8,pi:[{n:"other",pt:$n[0].ValueTuple$6(T1,T2,T3,T4,T5,T6),ps:0}],sn:"compareTo",rt:$n[0].Int32,p:[$n[0].ValueTuple$6(T1,T2,T3,T4,T5,T6)],box:function($v){return H5.box($v,System.Int32)}},{ov:!0,a:2,n:"Equals",t:8,pi:[{n:"obj",pt:$n[0].Object,ps:0}],sn:"equals",rt:$n[0].Boolean,p:[$n[0].Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Equals",t:8,pi:[{n:"other",pt:$n[0].ValueTuple$6(T1,T2,T3,T4,T5,T6),ps:0}],sn:"equalsT",rt:$n[0].Boolean,p:[$n[0].ValueTuple$6(T1,T2,T3,T4,T5,T6)],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ov:!0,a:2,n:"GetHashCode",t:8,sn:"getHashCode",rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"GetHashCodeCore",t:8,pi:[{n:"comparer",pt:$n[6].IEqualityComparer,ps:0}],sn:"GetHashCodeCore",rt:$n[0].Int32,p:[$n[6].IEqualityComparer],box:function($v){return H5.box($v,System.Int32)}},{ov:!0,a:2,n:"ToString",t:8,sn:"toString",rt:$n[0].String},{a:1,n:"s_t1Comparer",is:!0,t:16,rt:$n[3].EqualityComparer$1(T1),g:{a:1,n:"get_s_t1Comparer",t:8,rt:$n[3].EqualityComparer$1(T1),fg:"s_t1Comparer",is:!0},fn:"s_t1Comparer"},{a:1,n:"s_t2Comparer",is:!0,t:16,rt:$n[3].EqualityComparer$1(T2),g:{a:1,n:"get_s_t2Comparer",t:8,rt:$n[3].EqualityComparer$1(T2),fg:"s_t2Comparer",is:!0},fn:"s_t2Comparer"},{a:1,n:"s_t3Comparer",is:!0,t:16,rt:$n[3].EqualityComparer$1(T3),g:{a:1,n:"get_s_t3Comparer",t:8,rt:$n[3].EqualityComparer$1(T3),fg:"s_t3Comparer",is:!0},fn:"s_t3Comparer"},{a:1,n:"s_t4Comparer",is:!0,t:16,rt:$n[3].EqualityComparer$1(T4),g:{a:1,n:"get_s_t4Comparer",t:8,rt:$n[3].EqualityComparer$1(T4),fg:"s_t4Comparer",is:!0},fn:"s_t4Comparer"},{a:1,n:"s_t5Comparer",is:!0,t:16,rt:$n[3].EqualityComparer$1(T5),g:{a:1,n:"get_s_t5Comparer",t:8,rt:$n[3].EqualityComparer$1(T5),fg:"s_t5Comparer",is:!0},fn:"s_t5Comparer"},{a:1,n:"s_t6Comparer",is:!0,t:16,rt:$n[3].EqualityComparer$1(T6),g:{a:1,n:"get_s_t6Comparer",t:8,rt:$n[3].EqualityComparer$1(T6),fg:"s_t6Comparer",is:!0},fn:"s_t6Comparer"},{a:2,n:"Item1",t:4,rt:T1,sn:"Item1"},{a:2,n:"Item2",t:4,rt:T2,sn:"Item2"},{a:2,n:"Item3",t:4,rt:T3,sn:"Item3"},{a:2,n:"Item4",t:4,rt:T4,sn:"Item4"},{a:2,n:"Item5",t:4,rt:T5,sn:"Item5"},{a:2,n:"Item6",t:4,rt:T6,sn:"Item6"}]}},$n);$m("System.ValueTuple$7",function(T1,T2,T3,T4,T5,T6,T7){return{att:1048841,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[T1,T2,T3,T4,T5,T6,T7],pi:[{n:"item1",pt:T1,ps:0},{n:"item2",pt:T2,ps:1},{n:"item3",pt:T3,ps:2},{n:"item4",pt:T4,ps:3},{n:"item5",pt:T5,ps:4},{n:"item6",pt:T6,ps:5},{n:"item7",pt:T7,ps:6}],sn:"$ctor1"},{a:2,n:"CompareTo",t:8,pi:[{n:"other",pt:$n[0].ValueTuple$7(T1,T2,T3,T4,T5,T6,T7),ps:0}],sn:"compareTo",rt:$n[0].Int32,p:[$n[0].ValueTuple$7(T1,T2,T3,T4,T5,T6,T7)],box:function($v){return H5.box($v,System.Int32)}},{ov:!0,a:2,n:"Equals",t:8,pi:[{n:"obj",pt:$n[0].Object,ps:0}],sn:"equals",rt:$n[0].Boolean,p:[$n[0].Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Equals",t:8,pi:[{n:"other",pt:$n[0].ValueTuple$7(T1,T2,T3,T4,T5,T6,T7),ps:0}],sn:"equalsT",rt:$n[0].Boolean,p:[$n[0].ValueTuple$7(T1,T2,T3,T4,T5,T6,T7)],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ov:!0,a:2,n:"GetHashCode",t:8,sn:"getHashCode",rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"GetHashCodeCore",t:8,pi:[{n:"comparer",pt:$n[6].IEqualityComparer,ps:0}],sn:"GetHashCodeCore",rt:$n[0].Int32,p:[$n[6].IEqualityComparer],box:function($v){return H5.box($v,System.Int32)}},{ov:!0,a:2,n:"ToString",t:8,sn:"toString",rt:$n[0].String},{a:1,n:"s_t1Comparer",is:!0,t:16,rt:$n[3].EqualityComparer$1(T1),g:{a:1,n:"get_s_t1Comparer",t:8,rt:$n[3].EqualityComparer$1(T1),fg:"s_t1Comparer",is:!0},fn:"s_t1Comparer"},{a:1,n:"s_t2Comparer",is:!0,t:16,rt:$n[3].EqualityComparer$1(T2),g:{a:1,n:"get_s_t2Comparer",t:8,rt:$n[3].EqualityComparer$1(T2),fg:"s_t2Comparer",is:!0},fn:"s_t2Comparer"},{a:1,n:"s_t3Comparer",is:!0,t:16,rt:$n[3].EqualityComparer$1(T3),g:{a:1,n:"get_s_t3Comparer",t:8,rt:$n[3].EqualityComparer$1(T3),fg:"s_t3Comparer",is:!0},fn:"s_t3Comparer"},{a:1,n:"s_t4Comparer",is:!0,t:16,rt:$n[3].EqualityComparer$1(T4),g:{a:1,n:"get_s_t4Comparer",t:8,rt:$n[3].EqualityComparer$1(T4),fg:"s_t4Comparer",is:!0},fn:"s_t4Comparer"},{a:1,n:"s_t5Comparer",is:!0,t:16,rt:$n[3].EqualityComparer$1(T5),g:{a:1,n:"get_s_t5Comparer",t:8,rt:$n[3].EqualityComparer$1(T5),fg:"s_t5Comparer",is:!0},fn:"s_t5Comparer"},{a:1,n:"s_t6Comparer",is:!0,t:16,rt:$n[3].EqualityComparer$1(T6),g:{a:1,n:"get_s_t6Comparer",t:8,rt:$n[3].EqualityComparer$1(T6),fg:"s_t6Comparer",is:!0},fn:"s_t6Comparer"},{a:1,n:"s_t7Comparer",is:!0,t:16,rt:$n[3].EqualityComparer$1(T7),g:{a:1,n:"get_s_t7Comparer",t:8,rt:$n[3].EqualityComparer$1(T7),fg:"s_t7Comparer",is:!0},fn:"s_t7Comparer"},{a:2,n:"Item1",t:4,rt:T1,sn:"Item1"},{a:2,n:"Item2",t:4,rt:T2,sn:"Item2"},{a:2,n:"Item3",t:4,rt:T3,sn:"Item3"},{a:2,n:"Item4",t:4,rt:T4,sn:"Item4"},{a:2,n:"Item5",t:4,rt:T5,sn:"Item5"},{a:2,n:"Item6",t:4,rt:T6,sn:"Item6"},{a:2,n:"Item7",t:4,rt:T7,sn:"Item7"}]}},$n);$m("System.ValueTuple$8",function(T1,T2,T3,T4,T5,T6,T7,TRest){return{att:1048841,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[T1,T2,T3,T4,T5,T6,T7,TRest],pi:[{n:"item1",pt:T1,ps:0},{n:"item2",pt:T2,ps:1},{n:"item3",pt:T3,ps:2},{n:"item4",pt:T4,ps:3},{n:"item5",pt:T5,ps:4},{n:"item6",pt:T6,ps:5},{n:"item7",pt:T7,ps:6},{n:"rest",pt:TRest,ps:7}],sn:"$ctor1"},{a:2,n:"CompareTo",t:8,pi:[{n:"other",pt:$n[0].ValueTuple$8(T1,T2,T3,T4,T5,T6,T7,TRest),ps:0}],sn:"compareTo",rt:$n[0].Int32,p:[$n[0].ValueTuple$8(T1,T2,T3,T4,T5,T6,T7,TRest)],box:function($v){return H5.box($v,System.Int32)}},{ov:!0,a:2,n:"Equals",t:8,pi:[{n:"obj",pt:$n[0].Object,ps:0}],sn:"equals",rt:$n[0].Boolean,p:[$n[0].Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Equals",t:8,pi:[{n:"other",pt:$n[0].ValueTuple$8(T1,T2,T3,T4,T5,T6,T7,TRest),ps:0}],sn:"equalsT",rt:$n[0].Boolean,p:[$n[0].ValueTuple$8(T1,T2,T3,T4,T5,T6,T7,TRest)],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ov:!0,a:2,n:"GetHashCode",t:8,sn:"getHashCode",rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"GetHashCodeCore",t:8,pi:[{n:"comparer",pt:$n[6].IEqualityComparer,ps:0}],sn:"GetHashCodeCore",rt:$n[0].Int32,p:[$n[6].IEqualityComparer],box:function($v){return H5.box($v,System.Int32)}},{ov:!0,a:2,n:"ToString",t:8,sn:"toString",rt:$n[0].String},{a:1,n:"s_t1Comparer",is:!0,t:16,rt:$n[3].EqualityComparer$1(T1),g:{a:1,n:"get_s_t1Comparer",t:8,rt:$n[3].EqualityComparer$1(T1),fg:"s_t1Comparer",is:!0},fn:"s_t1Comparer"},{a:1,n:"s_t2Comparer",is:!0,t:16,rt:$n[3].EqualityComparer$1(T2),g:{a:1,n:"get_s_t2Comparer",t:8,rt:$n[3].EqualityComparer$1(T2),fg:"s_t2Comparer",is:!0},fn:"s_t2Comparer"},{a:1,n:"s_t3Comparer",is:!0,t:16,rt:$n[3].EqualityComparer$1(T3),g:{a:1,n:"get_s_t3Comparer",t:8,rt:$n[3].EqualityComparer$1(T3),fg:"s_t3Comparer",is:!0},fn:"s_t3Comparer"},{a:1,n:"s_t4Comparer",is:!0,t:16,rt:$n[3].EqualityComparer$1(T4),g:{a:1,n:"get_s_t4Comparer",t:8,rt:$n[3].EqualityComparer$1(T4),fg:"s_t4Comparer",is:!0},fn:"s_t4Comparer"},{a:1,n:"s_t5Comparer",is:!0,t:16,rt:$n[3].EqualityComparer$1(T5),g:{a:1,n:"get_s_t5Comparer",t:8,rt:$n[3].EqualityComparer$1(T5),fg:"s_t5Comparer",is:!0},fn:"s_t5Comparer"},{a:1,n:"s_t6Comparer",is:!0,t:16,rt:$n[3].EqualityComparer$1(T6),g:{a:1,n:"get_s_t6Comparer",t:8,rt:$n[3].EqualityComparer$1(T6),fg:"s_t6Comparer",is:!0},fn:"s_t6Comparer"},{a:1,n:"s_t7Comparer",is:!0,t:16,rt:$n[3].EqualityComparer$1(T7),g:{a:1,n:"get_s_t7Comparer",t:8,rt:$n[3].EqualityComparer$1(T7),fg:"s_t7Comparer",is:!0},fn:"s_t7Comparer"},{a:1,n:"s_tRestComparer",is:!0,t:16,rt:$n[3].EqualityComparer$1(TRest),g:{a:1,n:"get_s_tRestComparer",t:8,rt:$n[3].EqualityComparer$1(TRest),fg:"s_tRestComparer",is:!0},fn:"s_tRestComparer"},{a:2,n:"Item1",t:4,rt:T1,sn:"Item1"},{a:2,n:"Item2",t:4,rt:T2,sn:"Item2"},{a:2,n:"Item3",t:4,rt:T3,sn:"Item3"},{a:2,n:"Item4",t:4,rt:T4,sn:"Item4"},{a:2,n:"Item5",t:4,rt:T5,sn:"Item5"},{a:2,n:"Item6",t:4,rt:T6,sn:"Item6"},{a:2,n:"Item7",t:4,rt:T7,sn:"Item7"},{a:2,n:"Rest",t:4,rt:TRest,sn:"Rest"}]}},$n);$m("System.ValueTuple",function(){return{att:1048841,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:4,n:"CombineHashCodes",is:!0,t:8,pi:[{n:"h1",pt:$n[0].Int32,ps:0},{n:"h2",pt:$n[0].Int32,ps:1}],sn:"CombineHashCodes",rt:$n[0].Int32,p:[$n[0].Int32,$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"CombineHashCodes",is:!0,t:8,pi:[{n:"h1",pt:$n[0].Int32,ps:0},{n:"h2",pt:$n[0].Int32,ps:1},{n:"h3",pt:$n[0].Int32,ps:2}],sn:"CombineHashCodes$1",rt:$n[0].Int32,p:[$n[0].Int32,$n[0].Int32,$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"CombineHashCodes",is:!0,t:8,pi:[{n:"h1",pt:$n[0].Int32,ps:0},{n:"h2",pt:$n[0].Int32,ps:1},{n:"h3",pt:$n[0].Int32,ps:2},{n:"h4",pt:$n[0].Int32,ps:3}],sn:"CombineHashCodes$2",rt:$n[0].Int32,p:[$n[0].Int32,$n[0].Int32,$n[0].Int32,$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"CombineHashCodes",is:!0,t:8,pi:[{n:"h1",pt:$n[0].Int32,ps:0},{n:"h2",pt:$n[0].Int32,ps:1},{n:"h3",pt:$n[0].Int32,ps:2},{n:"h4",pt:$n[0].Int32,ps:3},{n:"h5",pt:$n[0].Int32,ps:4}],sn:"CombineHashCodes$3",rt:$n[0].Int32,p:[$n[0].Int32,$n[0].Int32,$n[0].Int32,$n[0].Int32,$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"CombineHashCodes",is:!0,t:8,pi:[{n:"h1",pt:$n[0].Int32,ps:0},{n:"h2",pt:$n[0].Int32,ps:1},{n:"h3",pt:$n[0].Int32,ps:2},{n:"h4",pt:$n[0].Int32,ps:3},{n:"h5",pt:$n[0].Int32,ps:4},{n:"h6",pt:$n[0].Int32,ps:5}],sn:"CombineHashCodes$4",rt:$n[0].Int32,p:[$n[0].Int32,$n[0].Int32,$n[0].Int32,$n[0].Int32,$n[0].Int32,$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"CombineHashCodes",is:!0,t:8,pi:[{n:"h1",pt:$n[0].Int32,ps:0},{n:"h2",pt:$n[0].Int32,ps:1},{n:"h3",pt:$n[0].Int32,ps:2},{n:"h4",pt:$n[0].Int32,ps:3},{n:"h5",pt:$n[0].Int32,ps:4},{n:"h6",pt:$n[0].Int32,ps:5},{n:"h7",pt:$n[0].Int32,ps:6}],sn:"CombineHashCodes$5",rt:$n[0].Int32,p:[$n[0].Int32,$n[0].Int32,$n[0].Int32,$n[0].Int32,$n[0].Int32,$n[0].Int32,$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"CombineHashCodes",is:!0,t:8,pi:[{n:"h1",pt:$n[0].Int32,ps:0},{n:"h2",pt:$n[0].Int32,ps:1},{n:"h3",pt:$n[0].Int32,ps:2},{n:"h4",pt:$n[0].Int32,ps:3},{n:"h5",pt:$n[0].Int32,ps:4},{n:"h6",pt:$n[0].Int32,ps:5},{n:"h7",pt:$n[0].Int32,ps:6},{n:"h8",pt:$n[0].Int32,ps:7}],sn:"CombineHashCodes$6",rt:$n[0].Int32,p:[$n[0].Int32,$n[0].Int32,$n[0].Int32,$n[0].Int32,$n[0].Int32,$n[0].Int32,$n[0].Int32,$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"CompareTo",t:8,pi:[{n:"other",pt:$n[0].ValueTuple,ps:0}],sn:"compareTo",rt:$n[0].Int32,p:[$n[0].ValueTuple],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"Create",is:!0,t:8,sn:"Create",rt:$n[0].ValueTuple},{a:2,n:"Create",is:!0,t:8,pi:[{n:"item1",pt:System.Object,ps:0}],tpc:1,tprm:["T1"],sn:"Create$1",rt:$n[0].ValueTuple$1(System.Object),p:[System.Object]},{a:2,n:"Create",is:!0,t:8,pi:[{n:"item1",pt:System.Object,ps:0},{n:"item2",pt:System.Object,ps:1}],tpc:2,tprm:["T1","T2"],sn:"Create$2",rt:$n[0].ValueTuple$2(System.Object,System.Object),p:[System.Object,System.Object]},{a:2,n:"Create",is:!0,t:8,pi:[{n:"item1",pt:System.Object,ps:0},{n:"item2",pt:System.Object,ps:1},{n:"item3",pt:System.Object,ps:2}],tpc:3,tprm:["T1","T2","T3"],sn:"Create$3",rt:$n[0].ValueTuple$3(System.Object,System.Object,System.Object),p:[System.Object,System.Object,System.Object]},{a:2,n:"Create",is:!0,t:8,pi:[{n:"item1",pt:System.Object,ps:0},{n:"item2",pt:System.Object,ps:1},{n:"item3",pt:System.Object,ps:2},{n:"item4",pt:System.Object,ps:3}],tpc:4,tprm:["T1","T2","T3","T4"],sn:"Create$4",rt:$n[0].ValueTuple$4(System.Object,System.Object,System.Object,System.Object),p:[System.Object,System.Object,System.Object,System.Object]},{a:2,n:"Create",is:!0,t:8,pi:[{n:"item1",pt:System.Object,ps:0},{n:"item2",pt:System.Object,ps:1},{n:"item3",pt:System.Object,ps:2},{n:"item4",pt:System.Object,ps:3},{n:"item5",pt:System.Object,ps:4}],tpc:5,tprm:["T1","T2","T3","T4","T5"],sn:"Create$5",rt:$n[0].ValueTuple$5(System.Object,System.Object,System.Object,System.Object,System.Object),p:[System.Object,System.Object,System.Object,System.Object,System.Object]},{a:2,n:"Create",is:!0,t:8,pi:[{n:"item1",pt:System.Object,ps:0},{n:"item2",pt:System.Object,ps:1},{n:"item3",pt:System.Object,ps:2},{n:"item4",pt:System.Object,ps:3},{n:"item5",pt:System.Object,ps:4},{n:"item6",pt:System.Object,ps:5}],tpc:6,tprm:["T1","T2","T3","T4","T5","T6"],sn:"Create$6",rt:$n[0].ValueTuple$6(System.Object,System.Object,System.Object,System.Object,System.Object,System.Object),p:[System.Object,System.Object,System.Object,System.Object,System.Object,System.Object]},{a:2,n:"Create",is:!0,t:8,pi:[{n:"item1",pt:System.Object,ps:0},{n:"item2",pt:System.Object,ps:1},{n:"item3",pt:System.Object,ps:2},{n:"item4",pt:System.Object,ps:3},{n:"item5",pt:System.Object,ps:4},{n:"item6",pt:System.Object,ps:5},{n:"item7",pt:System.Object,ps:6}],tpc:7,tprm:["T1","T2","T3","T4","T5","T6","T7"],sn:"Create$7",rt:$n[0].ValueTuple$7(System.Object,System.Object,System.Object,System.Object,System.Object,System.Object,System.Object),p:[System.Object,System.Object,System.Object,System.Object,System.Object,System.Object,System.Object]},{a:2,n:"Create",is:!0,t:8,pi:[{n:"item1",pt:System.Object,ps:0},{n:"item2",pt:System.Object,ps:1},{n:"item3",pt:System.Object,ps:2},{n:"item4",pt:System.Object,ps:3},{n:"item5",pt:System.Object,ps:4},{n:"item6",pt:System.Object,ps:5},{n:"item7",pt:System.Object,ps:6},{n:"item8",pt:System.Object,ps:7}],tpc:8,tprm:["T1","T2","T3","T4","T5","T6","T7","T8"],sn:"Create$8",rt:$n[0].ValueTuple$8(System.Object,System.Object,System.Object,System.Object,System.Object,System.Object,System.Object,System.ValueTuple$1(System.Object)),p:[System.Object,System.Object,System.Object,System.Object,System.Object,System.Object,System.Object,System.Object]},{ov:!0,a:2,n:"Equals",t:8,pi:[{n:"obj",pt:$n[0].Object,ps:0}],sn:"equals",rt:$n[0].Boolean,p:[$n[0].Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Equals",t:8,pi:[{n:"other",pt:$n[0].ValueTuple,ps:0}],sn:"equalsT",rt:$n[0].Boolean,p:[$n[0].ValueTuple],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ov:!0,a:2,n:"GetHashCode",t:8,sn:"getHashCode",rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}},{ov:!0,a:2,n:"ToString",t:8,sn:"toString",rt:$n[0].String}]}},$n);$m("System.Version",function(){return{nested:[$n[0].Version.ParseFailureKind,$n[0].Version.VersionResult],att:1048833,a:2,m:[{a:2,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].String],pi:[{n:"version",pt:$n[0].String,ps:0}],sn:"$ctor4"},{a:2,n:".ctor",t:1,p:[$n[0].Int32,$n[0].Int32],pi:[{n:"major",pt:$n[0].Int32,ps:0},{n:"minor",pt:$n[0].Int32,ps:1}],sn:"$ctor1"},{a:2,n:".ctor",t:1,p:[$n[0].Int32,$n[0].Int32,$n[0].Int32],pi:[{n:"major",pt:$n[0].Int32,ps:0},{n:"minor",pt:$n[0].Int32,ps:1},{n:"build",pt:$n[0].Int32,ps:2}],sn:"$ctor2"},{a:2,n:".ctor",t:1,p:[$n[0].Int32,$n[0].Int32,$n[0].Int32,$n[0].Int32],pi:[{n:"major",pt:$n[0].Int32,ps:0},{n:"minor",pt:$n[0].Int32,ps:1},{n:"build",pt:$n[0].Int32,ps:2},{n:"revision",pt:$n[0].Int32,ps:3}],sn:"$ctor3"},{a:1,n:"AppendPositiveNumber",is:!0,t:8,pi:[{n:"num",pt:$n[0].Int32,ps:0},{n:"sb",pt:$n[8].StringBuilder,ps:1}],sn:"appendPositiveNumber",rt:$n[0].Void,p:[$n[0].Int32,$n[8].StringBuilder]},{a:2,n:"Clone",t:8,sn:"clone",rt:$n[0].Object},{a:2,n:"CompareTo",t:8,pi:[{n:"version",pt:$n[0].Object,ps:0}],sn:"compareTo$1",rt:$n[0].Int32,p:[$n[0].Object],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"CompareTo",t:8,pi:[{n:"value",pt:$n[0].Version,ps:0}],sn:"compareTo",rt:$n[0].Int32,p:[$n[0].Version],box:function($v){return H5.box($v,System.Int32)}},{ov:!0,a:2,n:"Equals",t:8,pi:[{n:"obj",pt:$n[0].Object,ps:0}],sn:"equals",rt:$n[0].Boolean,p:[$n[0].Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Equals",t:8,pi:[{n:"obj",pt:$n[0].Version,ps:0}],sn:"equalsT",rt:$n[0].Boolean,p:[$n[0].Version],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ov:!0,a:2,n:"GetHashCode",t:8,sn:"getHashCode",rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"Parse",is:!0,t:8,pi:[{n:"input",pt:$n[0].String,ps:0}],sn:"parse",rt:$n[0].Version,p:[$n[0].String]},{ov:!0,a:2,n:"ToString",t:8,sn:"toString",rt:$n[0].String},{a:2,n:"ToString",t:8,pi:[{n:"fieldCount",pt:$n[0].Int32,ps:0}],sn:"toString$1",rt:$n[0].String,p:[$n[0].Int32]},{a:2,n:"TryParse",is:!0,t:8,pi:[{n:"input",pt:$n[0].String,ps:0},{n:"result",out:!0,pt:$n[0].Version,ps:1}],sn:"tryParse",rt:$n[0].Boolean,p:[$n[0].String,$n[0].Version],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"TryParseComponent",is:!0,t:8,pi:[{n:"component",pt:$n[0].String,ps:0},{n:"componentName",pt:$n[0].String,ps:1},{n:"result",ref:!0,pt:$n[0].Version.VersionResult,ps:2},{n:"parsedComponent",out:!0,pt:$n[0].Int32,ps:3}],sn:"tryParseComponent",rt:$n[0].Boolean,p:[$n[0].String,$n[0].String,$n[0].Version.VersionResult,$n[0].Int32],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"TryParseVersion",is:!0,t:8,pi:[{n:"version",pt:$n[0].String,ps:0},{n:"result",ref:!0,pt:$n[0].Version.VersionResult,ps:1}],sn:"tryParseVersion",rt:$n[0].Boolean,p:[$n[0].String,$n[0].Version.VersionResult],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"op_Equality",is:!0,t:8,pi:[{n:"v1",pt:$n[0].Version,ps:0},{n:"v2",pt:$n[0].Version,ps:1}],sn:"op_Equality",rt:$n[0].Boolean,p:[$n[0].Version,$n[0].Version],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"op_GreaterThan",is:!0,t:8,pi:[{n:"v1",pt:$n[0].Version,ps:0},{n:"v2",pt:$n[0].Version,ps:1}],sn:"op_GreaterThan",rt:$n[0].Boolean,p:[$n[0].Version,$n[0].Version],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"op_GreaterThanOrEqual",is:!0,t:8,pi:[{n:"v1",pt:$n[0].Version,ps:0},{n:"v2",pt:$n[0].Version,ps:1}],sn:"op_GreaterThanOrEqual",rt:$n[0].Boolean,p:[$n[0].Version,$n[0].Version],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"op_Inequality",is:!0,t:8,pi:[{n:"v1",pt:$n[0].Version,ps:0},{n:"v2",pt:$n[0].Version,ps:1}],sn:"op_Inequality",rt:$n[0].Boolean,p:[$n[0].Version,$n[0].Version],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"op_LessThan",is:!0,t:8,pi:[{n:"v1",pt:$n[0].Version,ps:0},{n:"v2",pt:$n[0].Version,ps:1}],sn:"op_LessThan",rt:$n[0].Boolean,p:[$n[0].Version,$n[0].Version],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"op_LessThanOrEqual",is:!0,t:8,pi:[{n:"v1",pt:$n[0].Version,ps:0},{n:"v2",pt:$n[0].Version,ps:1}],sn:"op_LessThanOrEqual",rt:$n[0].Boolean,p:[$n[0].Version,$n[0].Version],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Build",t:16,rt:$n[0].Int32,g:{a:2,n:"get_Build",t:8,rt:$n[0].Int32,fg:"Build",box:function($v){return H5.box($v,System.Int32)}},fn:"Build"},{a:2,n:"Major",t:16,rt:$n[0].Int32,g:{a:2,n:"get_Major",t:8,rt:$n[0].Int32,fg:"Major",box:function($v){return H5.box($v,System.Int32)}},fn:"Major"},{a:2,n:"MajorRevision",t:16,rt:$n[0].Int16,g:{a:2,n:"get_MajorRevision",t:8,rt:$n[0].Int16,fg:"MajorRevision",box:function($v){return H5.box($v,System.Int16)}},fn:"MajorRevision"},{a:2,n:"Minor",t:16,rt:$n[0].Int32,g:{a:2,n:"get_Minor",t:8,rt:$n[0].Int32,fg:"Minor",box:function($v){return H5.box($v,System.Int32)}},fn:"Minor"},{a:2,n:"MinorRevision",t:16,rt:$n[0].Int16,g:{a:2,n:"get_MinorRevision",t:8,rt:$n[0].Int16,fg:"MinorRevision",box:function($v){return H5.box($v,System.Int16)}},fn:"MinorRevision"},{a:2,n:"Revision",t:16,rt:$n[0].Int32,g:{a:2,n:"get_Revision",t:8,rt:$n[0].Int32,fg:"Revision",box:function($v){return H5.box($v,System.Int32)}},fn:"Revision"},{a:1,n:"SeparatorsArray",is:!0,t:4,rt:$n[0].Char,sn:"separatorsArray",ro:!0,box:function($v){return H5.box($v,System.Char,String.fromCharCode,System.Char.getHashCode)}},{a:1,n:"ZERO_CHAR_VALUE",is:!0,t:4,rt:$n[0].Int32,sn:"ZERO_CHAR_VALUE",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"_Build",t:4,rt:$n[0].Int32,sn:"_Build",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"_Major",t:4,rt:$n[0].Int32,sn:"_Major",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"_Minor",t:4,rt:$n[0].Int32,sn:"_Minor",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"_Revision",t:4,rt:$n[0].Int32,sn:"_Revision",box:function($v){return H5.box($v,System.Int32)}}]}},$n);$m("System.Version.ParseFailureKind",function(){return{td:$n[0].Version,att:261,a:4,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:"ArgumentException",is:!0,t:4,rt:$n[0].Version.ParseFailureKind,sn:"ArgumentException",box:function($v){return H5.box($v,System.Version.ParseFailureKind,System.Enum.toStringFn(System.Version.ParseFailureKind))}},{a:2,n:"ArgumentNullException",is:!0,t:4,rt:$n[0].Version.ParseFailureKind,sn:"ArgumentNullException",box:function($v){return H5.box($v,System.Version.ParseFailureKind,System.Enum.toStringFn(System.Version.ParseFailureKind))}},{a:2,n:"ArgumentOutOfRangeException",is:!0,t:4,rt:$n[0].Version.ParseFailureKind,sn:"ArgumentOutOfRangeException",box:function($v){return H5.box($v,System.Version.ParseFailureKind,System.Enum.toStringFn(System.Version.ParseFailureKind))}},{a:2,n:"FormatException",is:!0,t:4,rt:$n[0].Version.ParseFailureKind,sn:"FormatException",box:function($v){return H5.box($v,System.Version.ParseFailureKind,System.Enum.toStringFn(System.Version.ParseFailureKind))}}]}},$n);$m("System.Version.VersionResult",function(){return{td:$n[0].Version,att:1048845,a:4,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:4,n:"GetVersionParseException",t:8,sn:"getVersionParseException",rt:$n[0].Exception},{a:4,n:"Init",t:8,pi:[{n:"argumentName",pt:$n[0].String,ps:0},{n:"canThrow",pt:$n[0].Boolean,ps:1}],sn:"init",rt:$n[0].Void,p:[$n[0].String,$n[0].Boolean]},{a:4,n:"SetFailure",t:8,pi:[{n:"failure",pt:$n[0].Version.ParseFailureKind,ps:0}],sn:"setFailure",rt:$n[0].Void,p:[$n[0].Version.ParseFailureKind]},{a:4,n:"SetFailure",t:8,pi:[{n:"failure",pt:$n[0].Version.ParseFailureKind,ps:0},{n:"argument",pt:$n[0].String,ps:1}],sn:"setFailure$1",rt:$n[0].Void,p:[$n[0].Version.ParseFailureKind,$n[0].String]},{a:4,n:"m_argumentName",t:4,rt:$n[0].String,sn:"m_argumentName"},{a:4,n:"m_canThrow",t:4,rt:$n[0].Boolean,sn:"m_canThrow",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:4,n:"m_exceptionArgument",t:4,rt:$n[0].String,sn:"m_exceptionArgument"},{a:4,n:"m_failure",t:4,rt:$n[0].Version.ParseFailureKind,sn:"m_failure",box:function($v){return H5.box($v,System.Version.ParseFailureKind,System.Enum.toStringFn(System.Version.ParseFailureKind))}},{a:4,n:"m_parsedVersion",t:4,rt:$n[0].Version,sn:"m_parsedVersion"}]}},$n);$m("System.Net.WebSockets.ClientWebSocket",function(){return{att:1048577,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:"Abort",t:8,sn:"abort",rt:$n[0].Void},{a:2,n:"CloseAsync",t:8,pi:[{n:"closeStatus",pt:$n[9].WebSocketCloseStatus,ps:0},{n:"statusDescription",pt:$n[0].String,ps:1},{n:"cancellationToken",pt:$n[2].CancellationToken,ps:2}],sn:"closeAsync",rt:$n[10].Task,p:[$n[9].WebSocketCloseStatus,$n[0].String,$n[2].CancellationToken]},{a:2,n:"CloseOutputAsync",t:8,pi:[{n:"closeStatus",pt:$n[9].WebSocketCloseStatus,ps:0},{n:"statusDescription",pt:$n[0].String,ps:1},{n:"cancellationToken",pt:$n[2].CancellationToken,ps:2}],sn:"closeOutputAsync",rt:$n[10].Task,p:[$n[9].WebSocketCloseStatus,$n[0].String,$n[2].CancellationToken]},{a:2,n:"ConnectAsync",t:8,pi:[{n:"uri",pt:$n[0].Uri,ps:0},{n:"cancellationToken",pt:$n[2].CancellationToken,ps:1}],sn:"connectAsync",rt:$n[10].Task,p:[$n[0].Uri,$n[2].CancellationToken]},{a:2,n:"Dispose",t:8,sn:"dispose",rt:$n[0].Void},{a:2,n:"ReceiveAsync",t:8,pi:[{n:"buffer",pt:$n[0].ArraySegment,ps:0},{n:"cancellationToken",pt:$n[2].CancellationToken,ps:1}],sn:"receiveAsync",rt:$n[10].Task$1(System.Net.WebSockets.WebSocketReceiveResult),p:[$n[0].ArraySegment,$n[2].CancellationToken]},{a:2,n:"SendAsync",t:8,pi:[{n:"buffer",pt:$n[0].ArraySegment,ps:0},{n:"messageType",pt:$n[9].WebSocketMessageType,ps:1},{n:"endOfMessage",dv:!0,o:!0,pt:$n[0].Boolean,ps:2},{n:"cancellationToken",dv:null,o:!0,pt:$n[2].CancellationToken,ps:3}],sn:"sendAsync",rt:$n[10].Task,p:[$n[0].ArraySegment,$n[9].WebSocketMessageType,$n[0].Boolean,$n[2].CancellationToken]},{a:2,n:"CloseStatus",t:16,rt:$n[0].Nullable$1(System.Net.WebSockets.WebSocketCloseStatus),g:{a:2,n:"get_CloseStatus",t:8,tpc:0,def:function(){return this.getCloseStatus()},rt:$n[0].Nullable$1(System.Net.WebSockets.WebSocketCloseStatus)}},{a:2,n:"CloseStatusDescription",t:16,rt:$n[0].String,g:{a:2,n:"get_CloseStatusDescription",t:8,tpc:0,def:function(){return this.getCloseStatusDescription()},rt:$n[0].String}},{a:2,n:"Options",t:16,rt:$n[9].ClientWebSocketOptions,g:{a:2,n:"get_Options",t:8,tpc:0,def:function(){return this.getOptions()},rt:$n[9].ClientWebSocketOptions}},{a:2,n:"State",t:16,rt:$n[9].WebSocketState,g:{a:2,n:"get_State",t:8,tpc:0,def:function(){return this.getState()},rt:$n[9].WebSocketState}},{a:2,n:"SubProtocol",t:16,rt:$n[0].String,g:{a:2,n:"get_SubProtocol",t:8,tpc:0,def:function(){return this.getSubProtocol()},rt:$n[0].String}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Nullable$1(System.Net.WebSockets.WebSocketCloseStatus),sn:"CloseStatus"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"CloseStatusDescription"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[9].ClientWebSocketOptions,sn:"Options"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[9].WebSocketState,sn:"State"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"SubProtocol"}]}},$n);$m("System.Net.WebSockets.ClientWebSocketOptions",function(){return{att:1048577,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:"AddSubProtocol",t:8,pi:[{n:"subProtocol",pt:$n[0].String,ps:0}],sn:"AddSubProtocol",rt:$n[0].Void,p:[$n[0].String]}]}},$n);$m("System.Net.WebSockets.WebSocketReceiveResult",function(){return{att:1048577,a:2,m:[{a:2,n:".ctor",t:1,p:[$n[0].Int32,$n[9].WebSocketMessageType,$n[0].Boolean],pi:[{n:"count",pt:$n[0].Int32,ps:0},{n:"messageType",pt:$n[9].WebSocketMessageType,ps:1},{n:"endOfMessage",pt:$n[0].Boolean,ps:2}],sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].Int32,$n[9].WebSocketMessageType,$n[0].Boolean,$n[0].Nullable$1(System.Net.WebSockets.WebSocketCloseStatus),$n[0].String],pi:[{n:"count",pt:$n[0].Int32,ps:0},{n:"messageType",pt:$n[9].WebSocketMessageType,ps:1},{n:"endOfMessage",pt:$n[0].Boolean,ps:2},{n:"closeStatus",pt:$n[0].Nullable$1(System.Net.WebSockets.WebSocketCloseStatus),ps:3},{n:"closeStatusDescription",pt:$n[0].String,ps:4}],sn:"ctor"},{a:2,n:"CloseStatus",t:16,rt:$n[0].Nullable$1(System.Net.WebSockets.WebSocketCloseStatus),g:{a:2,n:"get_CloseStatus",t:8,tpc:0,def:function(){return this.getCloseStatus()},rt:$n[0].Nullable$1(System.Net.WebSockets.WebSocketCloseStatus)}},{a:2,n:"CloseStatusDescription",t:16,rt:$n[0].String,g:{a:2,n:"get_CloseStatusDescription",t:8,tpc:0,def:function(){return this.getCloseStatusDescription()},rt:$n[0].String}},{a:2,n:"Count",t:16,rt:$n[0].Int32,g:{a:2,n:"get_Count",t:8,tpc:0,def:function(){return this.getCount()},rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}}},{a:2,n:"EndOfMessage",t:16,rt:$n[0].Boolean,g:{a:2,n:"get_EndOfMessage",t:8,tpc:0,def:function(){return this.getEndOfMessage()},rt:$n[0].Boolean,box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}}},{a:2,n:"MessageType",t:16,rt:$n[9].WebSocketMessageType,g:{a:2,n:"get_MessageType",t:8,tpc:0,def:function(){return this.getMessageType()},rt:$n[9].WebSocketMessageType}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Nullable$1(System.Net.WebSockets.WebSocketCloseStatus),sn:"CloseStatus"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"CloseStatusDescription"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Int32,sn:"Count",box:function($v){return H5.box($v,System.Int32)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Boolean,sn:"EndOfMessage",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[9].WebSocketMessageType,sn:"MessageType"}]}},$n);$m("System.Threading.CancellationToken",function(){return{att:1048841,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].Boolean],pi:[{n:"canceled",pt:$n[0].Boolean,ps:0}],sn:"ctor"},{a:2,n:"Register",t:8,pi:[{n:"callback",pt:Function,ps:0}],sn:"register",rt:$n[2].CancellationTokenRegistration,p:[Function]},{a:2,n:"Register",t:8,pi:[{n:"callback",pt:Function,ps:0},{n:"useSynchronizationContext",pt:$n[0].Boolean,ps:1}],tpc:0,def:function(callback,useSynchronizationContext){return this.register(callback)},rt:$n[2].CancellationTokenRegistration,p:[Function,$n[0].Boolean]},{a:2,n:"Register",t:8,pi:[{n:"callback",pt:Function,ps:0},{n:"state",pt:$n[0].Object,ps:1}],sn:"register",rt:$n[2].CancellationTokenRegistration,p:[Function,$n[0].Object]},{a:2,n:"Register",t:8,pi:[{n:"callback",pt:Function,ps:0},{n:"state",pt:$n[0].Object,ps:1},{n:"useSynchronizationContext",pt:$n[0].Boolean,ps:2}],tpc:0,def:function(callback,state,useSynchronizationContext){return this.register(callback,state)},rt:$n[2].CancellationTokenRegistration,p:[Function,$n[0].Object,$n[0].Boolean]},{a:2,n:"ThrowIfCancellationRequested",t:8,sn:"throwIfCancellationRequested",rt:$n[0].Void},{a:2,n:"CanBeCanceled",t:16,rt:$n[0].Boolean,g:{a:2,n:"get_CanBeCanceled",t:8,tpc:0,def:function(){return this.getCanBeCanceled()},rt:$n[0].Boolean,box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}}},{a:2,n:"IsCancellationRequested",t:16,rt:$n[0].Boolean,g:{a:2,n:"get_IsCancellationRequested",t:8,tpc:0,def:function(){return this.getIsCancellationRequested()},rt:$n[0].Boolean,box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}}},{a:2,n:"None",is:!0,t:16,rt:$n[2].CancellationToken,g:{a:2,n:"get_None",t:8,rt:$n[2].CancellationToken,fg:"none",is:!0},fn:"none"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Boolean,sn:"CanBeCanceled",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Boolean,sn:"IsCancellationRequested",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,backing:!0,n:"k__BackingField",is:!0,t:4,rt:$n[2].CancellationToken,sn:"none"}]}},$n);$m("System.Threading.CancellationTokenRegistration",function(){return{att:1048841,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:"Dispose",t:8,sn:"dispose",rt:$n[0].Void},{a:2,n:"Equals",t:8,pi:[{n:"other",pt:$n[2].CancellationTokenRegistration,ps:0}],sn:"equalsT",rt:$n[0].Boolean,p:[$n[2].CancellationTokenRegistration],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"op_Equality",is:!0,t:8,pi:[{n:"left",pt:$n[2].CancellationTokenRegistration,ps:0},{n:"right",pt:$n[2].CancellationTokenRegistration,ps:1}],tpc:0,def:function(left,right){return H5.equals(left,right)},rt:$n[0].Boolean,p:[$n[2].CancellationTokenRegistration,$n[2].CancellationTokenRegistration],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"op_Inequality",is:!0,t:8,pi:[{n:"left",pt:$n[2].CancellationTokenRegistration,ps:0},{n:"right",pt:$n[2].CancellationTokenRegistration,ps:1}],tpc:0,def:function(left,right){return!H5.equals(left,right)},rt:$n[0].Boolean,p:[$n[2].CancellationTokenRegistration,$n[2].CancellationTokenRegistration],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}}]}},$n);$m("System.Threading.CancellationTokenSource",function(){return{att:1048577,a:2,m:[{a:2,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].Int32],pi:[{n:"millisecondsDelay",pt:$n[0].Int32,ps:0}],sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].TimeSpan],pi:[{n:"delay",pt:$n[0].TimeSpan,ps:0}],def:function(delay){return new System.Threading.CancellationTokenSource(delay.ticks/1e4)}},{a:2,n:"Cancel",t:8,sn:"cancel",rt:$n[0].Void},{a:2,n:"Cancel",t:8,pi:[{n:"throwOnFirstException",pt:$n[0].Boolean,ps:0}],sn:"cancel",rt:$n[0].Void,p:[$n[0].Boolean]},{a:2,n:"CancelAfter",t:8,pi:[{n:"millisecondsDelay",pt:$n[0].Int32,ps:0}],sn:"cancelAfter",rt:$n[0].Void,p:[$n[0].Int32]},{a:2,n:"CancelAfter",t:8,pi:[{n:"delay",pt:$n[0].TimeSpan,ps:0}],tpc:0,def:function(delay){return this.cancelAfter(delay.ticks/1e4)},rt:$n[0].Void,p:[$n[0].TimeSpan]},{a:2,n:"CreateLinkedTokenSource",is:!0,t:8,pi:[{n:"tokens",ip:!0,pt:System.Array.type(System.Threading.CancellationToken),ps:0}],tpc:0,def:function(tokens){return System.Threading.CancellationTokenSource.createLinked(tokens)},rt:$n[2].CancellationTokenSource,p:[System.Array.type(System.Threading.CancellationToken)]},{a:2,n:"CreateLinkedTokenSource",is:!0,t:8,pi:[{n:"token1",pt:$n[2].CancellationToken,ps:0},{n:"token2",pt:$n[2].CancellationToken,ps:1}],sn:"createLinked",rt:$n[2].CancellationTokenSource,p:[$n[2].CancellationToken,$n[2].CancellationToken]},{a:2,n:"Dispose",t:8,sn:"dispose",rt:$n[0].Void},{a:2,n:"IsCancellationRequested",t:16,rt:$n[0].Boolean,g:{a:2,n:"get_IsCancellationRequested",t:8,rt:$n[0].Boolean,fg:"isCancellationRequested",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},s:{a:1,n:"set_IsCancellationRequested",t:8,p:[$n[0].Boolean],rt:$n[0].Void,fs:"isCancellationRequested"},fn:"isCancellationRequested"},{a:2,n:"Token",t:16,rt:$n[2].CancellationToken,g:{a:2,n:"get_Token",t:8,rt:$n[2].CancellationToken,fg:"token"},s:{a:1,n:"set_Token",t:8,p:[$n[2].CancellationToken],rt:$n[0].Void,fs:"token"},fn:"token"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Boolean,sn:"isCancellationRequested",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[2].CancellationToken,sn:"token"}]}},$n);$m("System.Threading.Lock",function(){return{nested:[$n[2].Lock.Scope],att:1048833,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:"Enter",t:8,sn:"Enter",rt:$n[0].Void},{a:2,n:"EnterScope",t:8,sn:"EnterScope",rt:$n[2].Lock.Scope},{a:2,n:"Exit",t:8,sn:"Exit",rt:$n[0].Void}]}},$n);$m("System.Threading.Lock.Scope",function(){return{td:$n[2].Lock,att:1048842,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:"Dispose",t:8,sn:"System$IDisposable$Dispose",rt:$n[0].Void}]}},$n);$m("System.Threading.Timer",function(){return{att:1048833,a:2,m:[{a:2,n:".ctor",t:1,p:[Function],pi:[{n:"callback",pt:Function,ps:0}],sn:"ctor"},{a:2,n:".ctor",t:1,p:[Function,$n[0].Object,$n[0].Int32,$n[0].Int32],pi:[{n:"callback",pt:Function,ps:0},{n:"state",pt:$n[0].Object,ps:1},{n:"dueTime",pt:$n[0].Int32,ps:2},{n:"period",pt:$n[0].Int32,ps:3}],sn:"$ctor1"},{a:2,n:".ctor",t:1,p:[Function,$n[0].Object,$n[0].Int64,$n[0].Int64],pi:[{n:"callback",pt:Function,ps:0},{n:"state",pt:$n[0].Object,ps:1},{n:"dueTime",pt:$n[0].Int64,ps:2},{n:"period",pt:$n[0].Int64,ps:3}],sn:"$ctor2"},{a:2,n:".ctor",t:1,p:[Function,$n[0].Object,$n[0].TimeSpan,$n[0].TimeSpan],pi:[{n:"callback",pt:Function,ps:0},{n:"state",pt:$n[0].Object,ps:1},{n:"dueTime",pt:$n[0].TimeSpan,ps:2},{n:"period",pt:$n[0].TimeSpan,ps:3}],sn:"$ctor3"},{a:2,n:".ctor",t:1,p:[Function,$n[0].Object,$n[0].UInt32,$n[0].UInt32],pi:[{n:"callback",pt:Function,ps:0},{n:"state",pt:$n[0].Object,ps:1},{n:"dueTime",pt:$n[0].UInt32,ps:2},{n:"period",pt:$n[0].UInt32,ps:3}],sn:"$ctor4"},{a:2,n:"Change",t:8,pi:[{n:"dueTime",pt:$n[0].Int32,ps:0},{n:"period",pt:$n[0].Int32,ps:1}],sn:"Change",rt:$n[0].Boolean,p:[$n[0].Int32,$n[0].Int32],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Change",t:8,pi:[{n:"dueTime",pt:$n[0].Int64,ps:0},{n:"period",pt:$n[0].Int64,ps:1}],sn:"Change$1",rt:$n[0].Boolean,p:[$n[0].Int64,$n[0].Int64],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Change",t:8,pi:[{n:"dueTime",pt:$n[0].TimeSpan,ps:0},{n:"period",pt:$n[0].TimeSpan,ps:1}],sn:"Change$2",rt:$n[0].Boolean,p:[$n[0].TimeSpan,$n[0].TimeSpan],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Change",t:8,pi:[{n:"dueTime",pt:$n[0].UInt32,ps:0},{n:"period",pt:$n[0].UInt32,ps:1}],sn:"Change$3",rt:$n[0].Boolean,p:[$n[0].UInt32,$n[0].UInt32],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"ChangeTimer",t:8,pi:[{n:"dueTime",pt:$n[0].Int64,ps:0},{n:"period",pt:$n[0].Int64,ps:1}],sn:"ChangeTimer",rt:$n[0].Boolean,p:[$n[0].Int64,$n[0].Int64],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"ClearTimeout",t:8,sn:"ClearTimeout",rt:$n[0].Void},{a:2,n:"Dispose",t:8,sn:"Dispose",rt:$n[0].Void},{a:1,n:"HandleCallback",t:8,sn:"HandleCallback",rt:$n[0].Void},{a:1,n:"RunTimer",t:8,pi:[{n:"period",pt:$n[0].Int64,ps:0},{n:"checkDispose",dv:!0,o:!0,pt:$n[0].Boolean,ps:1}],sn:"RunTimer",rt:$n[0].Boolean,p:[$n[0].Int64,$n[0].Boolean],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"TimerSetup",t:8,pi:[{n:"callback",pt:Function,ps:0},{n:"state",pt:$n[0].Object,ps:1},{n:"dueTime",pt:$n[0].Int64,ps:2},{n:"period",pt:$n[0].Int64,ps:3}],sn:"TimerSetup",rt:$n[0].Boolean,p:[Function,$n[0].Object,$n[0].Int64,$n[0].Int64],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"EXC_DISPOSED",is:!0,t:4,rt:$n[0].String,sn:"EXC_DISPOSED"},{a:1,n:"EXC_LESS",is:!0,t:4,rt:$n[0].String,sn:"EXC_LESS"},{a:1,n:"EXC_MORE",is:!0,t:4,rt:$n[0].String,sn:"EXC_MORE"},{a:1,n:"MAX_SUPPORTED_TIMEOUT",is:!0,t:4,rt:$n[0].UInt32,sn:"MAX_SUPPORTED_TIMEOUT",box:function($v){return H5.box($v,System.UInt32)}},{a:1,n:"disposed",t:4,rt:$n[0].Boolean,sn:"disposed",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:4,n:"dueTime",t:4,rt:$n[0].Int64,sn:"dueTime"},{a:1,n:"id",t:4,rt:$n[0].Nullable$1(System.Int32),sn:"id",box:function($v){return H5.box($v,System.Int32,System.Nullable.toString,System.Nullable.getHashCode)}},{a:4,n:"period",t:4,rt:$n[0].Int64,sn:"period"},{a:1,n:"state",t:4,rt:$n[0].Object,sn:"state"},{a:1,n:"timerCallback",t:4,rt:Function,sn:"timerCallback"}]}},$n);$m("System.Threading.Tasks.TaskCanceledException",function(){return{att:1056769,a:2,at:[new System.SerializableAttribute],m:[{a:2,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].String],pi:[{n:"message",pt:$n[0].String,ps:0}],sn:"$ctor1"},{a:2,n:".ctor",t:1,p:[$n[10].Task],pi:[{n:"task",pt:$n[10].Task,ps:0}],sn:"$ctor3"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[0].Exception],pi:[{n:"message",pt:$n[0].String,ps:0},{n:"innerException",pt:$n[0].Exception,ps:1}],sn:"$ctor2"},{a:2,n:"Task",t:16,rt:$n[10].Task,g:{a:2,n:"get_Task",t:8,rt:$n[10].Task,fg:"Task"},fn:"Task"},{a:1,n:"_canceledTask",t:4,rt:$n[10].Task,sn:"_canceledTask",ro:!0}]}},$n);$m("System.Threading.Tasks.TaskSchedulerException",function(){return{att:1056769,a:2,at:[new System.SerializableAttribute],m:[{a:2,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].Exception],pi:[{n:"innerException",pt:$n[0].Exception,ps:0}],sn:"$ctor1"},{a:2,n:".ctor",t:1,p:[$n[0].String],pi:[{n:"message",pt:$n[0].String,ps:0}],sn:"$ctor2"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[0].Exception],pi:[{n:"message",pt:$n[0].String,ps:0},{n:"innerException",pt:$n[0].Exception,ps:1}],sn:"$ctor3"}]}},$n);$m("System.Threading.Tasks.Task",function(){return{att:1048577,a:2,m:[{a:2,n:".ctor",t:1,p:[Function],pi:[{n:"action",pt:Function,ps:0}],sn:"ctor"},{a:2,n:".ctor",t:1,p:[Function,$n[0].Object],pi:[{n:"action",pt:Function,ps:0},{n:"state",pt:$n[0].Object,ps:1}],sn:"ctor"},{a:2,n:"Complete",t:8,pi:[{n:"result",dv:null,o:!0,pt:$n[0].Object,ps:0}],sn:"complete",rt:$n[0].Void,p:[$n[0].Object]},{a:2,n:"ContinueWith",t:8,pi:[{n:"continuationAction",pt:Function,ps:0}],sn:"continueWith",rt:$n[10].Task,p:[Function]},{a:2,n:"ContinueWith",t:8,pi:[{n:"continuationFunction",pt:Function,ps:0}],tpc:1,tprm:["TResult"],sn:"continueWith",rt:$n[10].Task$1(System.Object),p:[Function]},{a:2,n:"Delay",is:!0,t:8,pi:[{n:"millisecondDelay",pt:$n[0].Int32,ps:0}],sn:"delay",rt:$n[10].Task,p:[$n[0].Int32]},{a:2,n:"Delay",is:!0,t:8,pi:[{n:"delay",pt:$n[0].TimeSpan,ps:0}],sn:"delay",rt:$n[10].Task,p:[$n[0].TimeSpan]},{a:2,n:"Delay",is:!0,t:8,pi:[{n:"millisecondsDelay",pt:$n[0].Int32,ps:0},{n:"cancellationToken",pt:$n[2].CancellationToken,ps:1}],sn:"delay",rt:$n[10].Task,p:[$n[0].Int32,$n[2].CancellationToken]},{a:2,n:"Delay",is:!0,t:8,pi:[{n:"delay",pt:$n[0].TimeSpan,ps:0},{n:"cancellationToken",pt:$n[2].CancellationToken,ps:1}],sn:"delay",rt:$n[10].Task,p:[$n[0].TimeSpan,$n[2].CancellationToken]},{a:2,n:"Dispose",t:8,sn:"dispose",rt:$n[0].Void},{a:2,n:"FromCallback",is:!0,t:8,pi:[{n:"target",pt:$n[0].Object,ps:0},{n:"method",pt:$n[0].String,ps:1},{n:"otherArguments",ip:!0,pt:$n[0].Array.type(System.Object),ps:2}],sn:"fromCallback",rt:$n[10].Task,p:[$n[0].Object,$n[0].String,$n[0].Array.type(System.Object)]},{a:2,n:"FromCallback",is:!0,t:8,pi:[{n:"target",pt:$n[0].Object,ps:0},{n:"method",pt:$n[0].String,ps:1},{n:"otherArguments",ip:!0,pt:$n[0].Array.type(System.Object),ps:2}],tpc:1,tprm:["TResult"],sn:"fromCallback",rt:$n[10].Task$1(System.Object),p:[$n[0].Object,$n[0].String,$n[0].Array.type(System.Object)]},{a:2,n:"FromCallbackResult",is:!0,t:8,pi:[{n:"target",pt:$n[0].Object,ps:0},{n:"method",pt:$n[0].String,ps:1},{n:"resultHandler",pt:Function,ps:2},{n:"otherArguments",ip:!0,pt:$n[0].Array.type(System.Object),ps:3}],sn:"fromCallbackResult",rt:$n[10].Task,p:[$n[0].Object,$n[0].String,Function,$n[0].Array.type(System.Object)]},{a:2,n:"FromCallbackResult",is:!0,t:8,pi:[{n:"target",pt:$n[0].Object,ps:0},{n:"method",pt:$n[0].String,ps:1},{n:"resultHandler",pt:Function,ps:2},{n:"otherArguments",ip:!0,pt:$n[0].Array.type(System.Object),ps:3}],tpc:1,tprm:["TResult"],sn:"fromCallbackResult",rt:$n[10].Task$1(System.Object),p:[$n[0].Object,$n[0].String,Function,$n[0].Array.type(System.Object)]},{a:2,n:"FromException",is:!0,t:8,pi:[{n:"exception",pt:$n[0].Exception,ps:0}],tpc:0,def:function(exception){return System.Threading.Tasks.Task.fromException(exception,null)},rt:$n[10].Task,p:[$n[0].Exception]},{a:2,n:"FromException",is:!0,t:8,pi:[{n:"exception",pt:$n[0].Exception,ps:0}],tpc:1,def:function(TResult,exception){return System.Threading.Tasks.Task.fromException(exception,TResult)},rt:$n[10].Task$1(System.Object),p:[$n[0].Exception]},{a:2,n:"FromPromise",is:!0,t:8,pi:[{n:"promise",pt:H5.IPromise,ps:0}],sn:"fromPromise",rt:$n[10].Task$1(System.Array.type(System.Object)),p:[H5.IPromise]},{a:2,n:"FromPromise",is:!0,t:8,pi:[{n:"promise",pt:H5.IPromise,ps:0},{n:"resultHandler",pt:Function,ps:1}],tpc:1,tprm:["TResult"],sn:"fromPromise",rt:$n[10].Task$1(System.Object),p:[H5.IPromise,Function]},{a:2,n:"FromPromise",is:!0,t:8,pi:[{n:"promise",pt:H5.IPromise,ps:0},{n:"resultHandler",pt:Function,ps:1},{n:"errorHandler",pt:Function,ps:2}],tpc:1,tprm:["TResult"],sn:"fromPromise",rt:$n[10].Task$1(System.Object),p:[H5.IPromise,Function,Function]},{a:2,n:"FromPromise",is:!0,t:8,pi:[{n:"promise",pt:H5.IPromise,ps:0},{n:"resultHandler",pt:Function,ps:1},{n:"errorHandler",pt:Function,ps:2},{n:"progressHandler",pt:Function,ps:3}],tpc:1,tprm:["TResult"],sn:"fromPromise",rt:$n[10].Task$1(System.Object),p:[H5.IPromise,Function,Function,Function]},{a:2,n:"FromResult",is:!0,t:8,pi:[{n:"result",pt:System.Object,ps:0}],tpc:1,def:function(TResult,result){return System.Threading.Tasks.Task.fromResult(result,TResult)},rt:$n[10].Task$1(System.Object),p:[System.Object]},{a:2,n:"GetAwaiter",t:8,sn:"getAwaiter",rt:$n[10].TaskAwaiter},{a:2,n:"Run",is:!0,t:8,pi:[{n:"action",pt:Function,ps:0}],sn:"run",rt:$n[10].Task,p:[Function]},{a:2,n:"Run",is:!0,t:8,pi:[{n:"function",pt:Function,ps:0}],tpc:1,tprm:["TResult"],sn:"run",rt:$n[10].Task$1(System.Object),p:[Function]},{a:2,n:"Start",t:8,sn:"start",rt:$n[0].Void},{a:2,n:"Wait",t:8,sn:"wait",rt:$n[0].Void},{a:2,n:"Wait",t:8,pi:[{n:"millisecondsTimeout",pt:$n[0].Int32,ps:0}],sn:"wait",rt:$n[0].Boolean,p:[$n[0].Int32],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Wait",t:8,pi:[{n:"cancellationToken",pt:$n[2].CancellationToken,ps:0}],sn:"wait",rt:$n[0].Void,p:[$n[2].CancellationToken]},{a:2,n:"Wait",t:8,pi:[{n:"timeout",pt:$n[0].TimeSpan,ps:0}],sn:"wait",rt:$n[0].Boolean,p:[$n[0].TimeSpan],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Wait",t:8,pi:[{n:"millisecondsTimeout",pt:$n[0].Int32,ps:0},{n:"cancellationToken",pt:$n[2].CancellationToken,ps:1}],sn:"wait",rt:$n[0].Boolean,p:[$n[0].Int32,$n[2].CancellationToken],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"WaitTask",t:8,sn:"wait",rt:$n[10].Task},{a:2,n:"WaitTask",t:8,pi:[{n:"millisecondsTimeout",pt:$n[0].Int32,ps:0}],sn:"waitt",rt:$n[10].Task$1(System.Boolean),p:[$n[0].Int32]},{a:2,n:"WaitTask",t:8,pi:[{n:"cancellationToken",pt:$n[2].CancellationToken,ps:0}],sn:"wait",rt:$n[10].Task,p:[$n[2].CancellationToken]},{a:2,n:"WaitTask",t:8,pi:[{n:"timeout",pt:$n[0].TimeSpan,ps:0}],sn:"waitt",rt:$n[10].Task$1(System.Boolean),p:[$n[0].TimeSpan]},{a:2,n:"WaitTask",t:8,pi:[{n:"millisecondsTimeout",pt:$n[0].Int32,ps:0},{n:"cancellationToken",pt:$n[2].CancellationToken,ps:1}],sn:"waitt",rt:$n[10].Task$1(System.Boolean),p:[$n[0].Int32,$n[2].CancellationToken]},{a:2,n:"WhenAll",is:!0,t:8,pi:[{n:"tasks",pt:$n[3].IEnumerable$1(System.Threading.Tasks.Task),ps:0}],sn:"whenAll",rt:$n[10].Task,p:[$n[3].IEnumerable$1(System.Threading.Tasks.Task)]},{a:2,n:"WhenAll",is:!0,t:8,pi:[{n:"tasks",pt:$n[3].IEnumerable$1(System.Threading.Tasks.Task$1(System.Object)),ps:0}],tpc:1,tprm:["TResult"],sn:"whenAll",rt:$n[10].Task$1(System.Array.type(System.Object)),p:[$n[3].IEnumerable$1(System.Threading.Tasks.Task$1(System.Object))]},{a:2,n:"WhenAll",is:!0,t:8,pi:[{n:"tasks",ip:!0,pt:System.Array.type(System.Threading.Tasks.Task),ps:0}],sn:"whenAll",rt:$n[10].Task,p:[System.Array.type(System.Threading.Tasks.Task)]},{a:2,n:"WhenAll",is:!0,t:8,pi:[{n:"tasks",ip:!0,pt:System.Array.type(System.Threading.Tasks.Task$1(System.Object)),ps:0}],tpc:1,tprm:["TResult"],sn:"whenAll",rt:$n[10].Task$1(System.Array.type(System.Object)),p:[System.Array.type(System.Threading.Tasks.Task$1(System.Object))]},{a:2,n:"WhenAny",is:!0,t:8,pi:[{n:"tasks",pt:$n[3].IEnumerable$1(System.Threading.Tasks.Task),ps:0}],sn:"whenAny",rt:$n[10].Task$1(System.Threading.Tasks.Task),p:[$n[3].IEnumerable$1(System.Threading.Tasks.Task)]},{a:2,n:"WhenAny",is:!0,t:8,pi:[{n:"tasks",pt:$n[3].IEnumerable$1(System.Threading.Tasks.Task$1(System.Object)),ps:0}],tpc:1,tprm:["TResult"],sn:"whenAny",rt:$n[10].Task$1(System.Threading.Tasks.Task$1(System.Object)),p:[$n[3].IEnumerable$1(System.Threading.Tasks.Task$1(System.Object))]},{a:2,n:"WhenAny",is:!0,t:8,pi:[{n:"tasks",ip:!0,pt:System.Array.type(System.Threading.Tasks.Task),ps:0}],sn:"whenAny",rt:$n[10].Task$1(System.Threading.Tasks.Task),p:[System.Array.type(System.Threading.Tasks.Task)]},{a:2,n:"WhenAny",is:!0,t:8,pi:[{n:"tasks",ip:!0,pt:System.Array.type(System.Threading.Tasks.Task$1(System.Object)),ps:0}],tpc:1,tprm:["TResult"],sn:"whenAny",rt:$n[10].Task$1(System.Threading.Tasks.Task$1(System.Object)),p:[System.Array.type(System.Threading.Tasks.Task$1(System.Object))]},{a:2,n:"AsyncState",t:16,rt:$n[0].Object,g:{a:2,n:"get_AsyncState",t:8,rt:$n[0].Object,fg:"AsyncState"},fn:"AsyncState"},{a:2,n:"CompletedTask",is:!0,t:16,rt:$n[10].Task,g:{a:2,n:"get_CompletedTask",is:!0,t:8,tpc:0,def:function(){return System.Threading.Tasks.Task.fromResult({},null)},rt:$n[10].Task}},{a:2,n:"Exception",t:16,rt:$n[0].AggregateException,g:{a:2,n:"get_Exception",t:8,tpc:0,def:function(){return this.getException()},rt:$n[0].AggregateException}},{a:2,n:"IsCanceled",t:16,rt:$n[0].Boolean,g:{a:2,n:"get_IsCanceled",t:8,tpc:0,def:function(){return this.isCanceled()},rt:$n[0].Boolean,box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}}},{a:2,n:"IsCompleted",t:16,rt:$n[0].Boolean,g:{a:2,n:"get_IsCompleted",t:8,tpc:0,def:function(){return this.isCompleted()},rt:$n[0].Boolean,box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}}},{a:2,n:"IsFaulted",t:16,rt:$n[0].Boolean,g:{a:2,n:"get_IsFaulted",t:8,tpc:0,def:function(){return this.isFaulted()},rt:$n[0].Boolean,box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}}},{a:2,n:"Status",t:16,rt:$n[10].TaskStatus,g:{a:2,n:"get_Status",t:8,rt:$n[10].TaskStatus,fg:"status",box:function($v){return H5.box($v,System.Threading.Tasks.TaskStatus,System.Enum.toStringFn(System.Threading.Tasks.TaskStatus))}},fn:"status"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Object,sn:"AsyncState"},{a:1,backing:!0,n:"k__BackingField",is:!0,t:4,rt:$n[10].Task,sn:"CompletedTask"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].AggregateException,sn:"Exception"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Boolean,sn:"IsCanceled",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Boolean,sn:"IsCompleted",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Boolean,sn:"IsFaulted",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[10].TaskStatus,sn:"status",box:function($v){return H5.box($v,System.Threading.Tasks.TaskStatus,System.Enum.toStringFn(System.Threading.Tasks.TaskStatus))}}]}},$n);$m("System.Threading.Tasks.Task$1",function(TResult){return{att:1048577,a:2,m:[{a:2,n:".ctor",t:1,p:[Function],pi:[{n:"function",pt:Function,ps:0}],sn:"ctor"},{a:2,n:".ctor",t:1,p:[Function,$n[0].Object],pi:[{n:"function",pt:Function,ps:0},{n:"state",pt:$n[0].Object,ps:1}],sn:"ctor"},{a:2,n:"ContinueWith",t:8,pi:[{n:"continuationAction",pt:Function,ps:0}],sn:"continueWith",rt:$n[10].Task,p:[Function]},{a:2,n:"ContinueWith",t:8,pi:[{n:"continuationFunction",pt:Function,ps:0}],sn:"continueWith",rt:$n[10].Task$1(System.Object),p:[Function]},{a:2,n:"GetAwaiter",t:8,sn:"getAwaiter",rt:$n[10].Task(TResult)},{a:2,n:"SetResult",t:8,pi:[{n:"result",pt:TResult,ps:0}],sn:"setResult",rt:$n[0].Void,p:[TResult]},{a:2,n:"Result",t:16,rt:TResult,g:{a:2,n:"get_Result",t:8,tpc:0,def:function(){return this.getResult()},rt:TResult}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:TResult,sn:"Result"}]}},$n);$m("System.Threading.Tasks.TaskCompletionSource",function(){return{att:1048577,a:2,m:[{a:2,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].Object],pi:[{n:"state",pt:$n[0].Object,ps:0}],sn:"ctor"},{a:2,n:"SetCanceled",t:8,sn:"setCanceled",rt:$n[0].Void},{a:2,n:"SetException",t:8,pi:[{n:"exceptions",pt:$n[3].IEnumerable$1(System.Exception),ps:0}],sn:"setException",rt:$n[0].Void,p:[$n[3].IEnumerable$1(System.Exception)]},{a:2,n:"SetException",t:8,pi:[{n:"exception",pt:$n[0].Exception,ps:0}],sn:"setException",rt:$n[0].Void,p:[$n[0].Exception]},{a:2,n:"SetResult",t:8,pi:[{n:"result",pt:System.Object,ps:0}],sn:"setResult",rt:$n[0].Void,p:[System.Object]},{a:2,n:"TrySetCanceled",t:8,sn:"trySetCanceled",rt:$n[0].Boolean,box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"TrySetException",t:8,pi:[{n:"exceptions",pt:$n[3].IEnumerable$1(System.Exception),ps:0}],sn:"trySetException",rt:$n[0].Boolean,p:[$n[3].IEnumerable$1(System.Exception)],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"TrySetException",t:8,pi:[{n:"exception",pt:$n[0].Exception,ps:0}],sn:"trySetException",rt:$n[0].Boolean,p:[$n[0].Exception],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"TrySetResult",t:8,pi:[{n:"result",pt:System.Object,ps:0}],sn:"trySetResult",rt:$n[0].Boolean,p:[System.Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Task",t:16,rt:$n[10].Task$1(System.Object),g:{a:2,n:"get_Task",t:8,rt:$n[10].Task$1(System.Object),fg:"task"},fn:"task"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[10].Task$1(System.Object),sn:"task"}]}},$n);$m("System.Threading.Tasks.ValueTask",function(){return{att:1048841,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].Boolean],pi:[{n:"completedSynchronously",pt:$n[0].Boolean,ps:0}],sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[10].Task],pi:[{n:"task",pt:$n[10].Task,ps:0}],sn:"ctor"},{a:2,n:"Completed",is:!0,t:8,sn:"completed",rt:$n[10].Task},{a:2,n:"GetAwaiter",t:8,sn:"getAwaiter",rt:$n[10].TaskAwaiter}]}},$n);$m("System.Threading.Tasks.ValueTask$1",function(TResult){return{att:1048841,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[10].Task$1(TResult)],pi:[{n:"task",pt:$n[10].Task$1(TResult),ps:0}],sn:"ctor"},{a:2,n:".ctor",t:1,p:[TResult],pi:[{n:"result",pt:TResult,ps:0}],sn:"ctor"},{a:2,n:"GetAwaiter",t:8,sn:"getAwaiter",rt:$n[10].Task(TResult)}]}},$n);$m("System.Text.StringBuilderCache",function(){return{att:1048960,a:4,s:!0,m:[{a:2,n:"Acquire",is:!0,t:8,pi:[{n:"capacity",dv:16,o:!0,pt:$n[0].Int32,ps:0}],sn:"Acquire",rt:$n[8].StringBuilder,p:[$n[0].Int32]},{a:2,n:"GetStringAndRelease",is:!0,t:8,pi:[{n:"sb",pt:$n[8].StringBuilder,ps:0}],sn:"GetStringAndRelease",rt:$n[0].String,p:[$n[8].StringBuilder]},{a:2,n:"Release",is:!0,t:8,pi:[{n:"sb",pt:$n[8].StringBuilder,ps:0}],sn:"Release",rt:$n[0].Void,p:[$n[8].StringBuilder]},{a:1,n:"DEFAULT_CAPACITY",is:!0,t:4,rt:$n[0].Int32,sn:"DEFAULT_CAPACITY",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"MAX_BUILDER_SIZE",is:!0,t:4,rt:$n[0].Int32,sn:"MAX_BUILDER_SIZE",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"t_cachedInstance",is:!0,t:4,rt:$n[8].StringBuilder,sn:"t_cachedInstance"}]}},$n);$m("System.Text.ASCIIEncoding",function(){return{att:1048577,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{ov:!0,a:3,n:"Decode",t:8,pi:[{n:"bytes",pt:$n[0].Array.type(System.Byte),ps:0},{n:"index",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2},{n:"chars",pt:$n[0].Array.type(System.Char),ps:3},{n:"charIndex",pt:$n[0].Int32,ps:4}],sn:"Decode$2",rt:$n[0].String,p:[$n[0].Array.type(System.Byte),$n[0].Int32,$n[0].Int32,$n[0].Array.type(System.Char),$n[0].Int32]},{ov:!0,a:3,n:"Encode",t:8,pi:[{n:"s",pt:$n[0].String,ps:0},{n:"outputBytes",pt:$n[0].Array.type(System.Byte),ps:1},{n:"outputIndex",pt:$n[0].Int32,ps:2},{n:"writtenBytes",out:!0,pt:$n[0].Int32,ps:3}],sn:"Encode$3",rt:$n[0].Array.type(System.Byte),p:[$n[0].String,$n[0].Array.type(System.Byte),$n[0].Int32,$n[0].Int32]},{ov:!0,a:2,n:"GetMaxByteCount",t:8,pi:[{n:"charCount",pt:$n[0].Int32,ps:0}],sn:"GetMaxByteCount",rt:$n[0].Int32,p:[$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{ov:!0,a:2,n:"GetMaxCharCount",t:8,pi:[{n:"byteCount",pt:$n[0].Int32,ps:0}],sn:"GetMaxCharCount",rt:$n[0].Int32,p:[$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{ov:!0,a:2,n:"CodePage",t:16,rt:$n[0].Int32,g:{ov:!0,a:2,n:"get_CodePage",t:8,rt:$n[0].Int32,fg:"CodePage",box:function($v){return H5.box($v,System.Int32)}},fn:"CodePage"},{ov:!0,a:2,n:"EncodingName",t:16,rt:$n[0].String,g:{ov:!0,a:2,n:"get_EncodingName",t:8,rt:$n[0].String,fg:"EncodingName"},fn:"EncodingName"}]}},$n);$m("System.Text.Encoding",function(){return{att:1048705,a:2,m:[{a:3,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:"Convert",is:!0,t:8,pi:[{n:"srcEncoding",pt:$n[8].Encoding,ps:0},{n:"dstEncoding",pt:$n[8].Encoding,ps:1},{n:"bytes",pt:$n[0].Array.type(System.Byte),ps:2}],sn:"Convert",rt:$n[0].Array.type(System.Byte),p:[$n[8].Encoding,$n[8].Encoding,$n[0].Array.type(System.Byte)]},{a:2,n:"Convert",is:!0,t:8,pi:[{n:"srcEncoding",pt:$n[8].Encoding,ps:0},{n:"dstEncoding",pt:$n[8].Encoding,ps:1},{n:"bytes",pt:$n[0].Array.type(System.Byte),ps:2},{n:"index",pt:$n[0].Int32,ps:3},{n:"count",pt:$n[0].Int32,ps:4}],sn:"Convert$1",rt:$n[0].Array.type(System.Byte),p:[$n[8].Encoding,$n[8].Encoding,$n[0].Array.type(System.Byte),$n[0].Int32,$n[0].Int32]},{a:3,n:"Decode",t:8,pi:[{n:"bytes",pt:$n[0].Array.type(System.Byte),ps:0}],sn:"Decode",rt:$n[0].String,p:[$n[0].Array.type(System.Byte)]},{a:3,n:"Decode",t:8,pi:[{n:"bytes",pt:$n[0].Array.type(System.Byte),ps:0},{n:"index",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2}],sn:"Decode$1",rt:$n[0].String,p:[$n[0].Array.type(System.Byte),$n[0].Int32,$n[0].Int32]},{ab:!0,a:3,n:"Decode",t:8,pi:[{n:"bytes",pt:$n[0].Array.type(System.Byte),ps:0},{n:"index",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2},{n:"chars",pt:$n[0].Array.type(System.Char),ps:3},{n:"charIndex",pt:$n[0].Int32,ps:4}],sn:"Decode$2",rt:$n[0].String,p:[$n[0].Array.type(System.Byte),$n[0].Int32,$n[0].Int32,$n[0].Array.type(System.Char),$n[0].Int32]},{a:3,n:"Encode",t:8,pi:[{n:"chars",pt:$n[0].Array.type(System.Char),ps:0}],sn:"Encode",rt:$n[0].Array.type(System.Byte),p:[$n[0].Array.type(System.Char)]},{a:3,n:"Encode",t:8,pi:[{n:"str",pt:$n[0].String,ps:0}],sn:"Encode$2",rt:$n[0].Array.type(System.Byte),p:[$n[0].String]},{a:3,n:"Encode",t:8,pi:[{n:"chars",pt:$n[0].Array.type(System.Char),ps:0},{n:"index",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2}],sn:"Encode$1",rt:$n[0].Array.type(System.Byte),p:[$n[0].Array.type(System.Char),$n[0].Int32,$n[0].Int32]},{ab:!0,a:3,n:"Encode",t:8,pi:[{n:"s",pt:$n[0].String,ps:0},{n:"outputBytes",pt:$n[0].Array.type(System.Byte),ps:1},{n:"outputIndex",pt:$n[0].Int32,ps:2},{n:"writtenBytes",out:!0,pt:$n[0].Int32,ps:3}],sn:"Encode$3",rt:$n[0].Array.type(System.Byte),p:[$n[0].String,$n[0].Array.type(System.Byte),$n[0].Int32,$n[0].Int32]},{a:3,n:"Encode",t:8,pi:[{n:"chars",pt:$n[0].Array.type(System.Char),ps:0},{n:"index",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2},{n:"outputBytes",pt:$n[0].Array.type(System.Byte),ps:3},{n:"outputIndex",pt:$n[0].Int32,ps:4}],sn:"Encode$4",rt:$n[0].Int32,p:[$n[0].Array.type(System.Char),$n[0].Int32,$n[0].Int32,$n[0].Array.type(System.Byte),$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{a:3,n:"Encode",t:8,pi:[{n:"s",pt:$n[0].String,ps:0},{n:"index",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2},{n:"outputBytes",pt:$n[0].Array.type(System.Byte),ps:3},{n:"outputIndex",pt:$n[0].Int32,ps:4}],sn:"Encode$5",rt:$n[0].Int32,p:[$n[0].String,$n[0].Int32,$n[0].Int32,$n[0].Array.type(System.Byte),$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"FromCharCode",is:!0,t:8,pi:[{n:"code",pt:$n[0].Int32,ps:0}],tpc:0,def:function(code){return System.String.fromCharCode(code)},rt:$n[0].String,p:[$n[0].Int32]},{v:!0,a:2,n:"GetByteCount",t:8,pi:[{n:"chars",pt:$n[0].Array.type(System.Char),ps:0}],sn:"GetByteCount",rt:$n[0].Int32,p:[$n[0].Array.type(System.Char)],box:function($v){return H5.box($v,System.Int32)}},{v:!0,a:2,n:"GetByteCount",t:8,pi:[{n:"s",pt:$n[0].String,ps:0}],sn:"GetByteCount$2",rt:$n[0].Int32,p:[$n[0].String],box:function($v){return H5.box($v,System.Int32)}},{v:!0,a:2,n:"GetByteCount",t:8,pi:[{n:"chars",pt:$n[0].Array.type(System.Char),ps:0},{n:"index",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2}],sn:"GetByteCount$1",rt:$n[0].Int32,p:[$n[0].Array.type(System.Char),$n[0].Int32,$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{v:!0,a:2,n:"GetBytes",t:8,pi:[{n:"chars",pt:$n[0].Array.type(System.Char),ps:0}],sn:"GetBytes",rt:$n[0].Array.type(System.Byte),p:[$n[0].Array.type(System.Char)]},{v:!0,a:2,n:"GetBytes",t:8,pi:[{n:"s",pt:$n[0].String,ps:0}],sn:"GetBytes$2",rt:$n[0].Array.type(System.Byte),p:[$n[0].String]},{v:!0,a:2,n:"GetBytes",t:8,pi:[{n:"chars",pt:$n[0].Array.type(System.Char),ps:0},{n:"index",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2}],sn:"GetBytes$1",rt:$n[0].Array.type(System.Byte),p:[$n[0].Array.type(System.Char),$n[0].Int32,$n[0].Int32]},{v:!0,a:2,n:"GetBytes",t:8,pi:[{n:"chars",pt:$n[0].Array.type(System.Char),ps:0},{n:"charIndex",pt:$n[0].Int32,ps:1},{n:"charCount",pt:$n[0].Int32,ps:2},{n:"bytes",pt:$n[0].Array.type(System.Byte),ps:3},{n:"byteIndex",pt:$n[0].Int32,ps:4}],sn:"GetBytes$3",rt:$n[0].Int32,p:[$n[0].Array.type(System.Char),$n[0].Int32,$n[0].Int32,$n[0].Array.type(System.Byte),$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{v:!0,a:2,n:"GetBytes",t:8,pi:[{n:"s",pt:$n[0].String,ps:0},{n:"charIndex",pt:$n[0].Int32,ps:1},{n:"charCount",pt:$n[0].Int32,ps:2},{n:"bytes",pt:$n[0].Array.type(System.Byte),ps:3},{n:"byteIndex",pt:$n[0].Int32,ps:4}],sn:"GetBytes$4",rt:$n[0].Int32,p:[$n[0].String,$n[0].Int32,$n[0].Int32,$n[0].Array.type(System.Byte),$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{v:!0,a:2,n:"GetCharCount",t:8,pi:[{n:"bytes",pt:$n[0].Array.type(System.Byte),ps:0}],sn:"GetCharCount",rt:$n[0].Int32,p:[$n[0].Array.type(System.Byte)],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"GetCharCount",t:8,pi:[{n:"bytes",pt:$n[0].Array.type(System.Byte),ps:0},{n:"index",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2}],sn:"GetCharCount$1",rt:$n[0].Int32,p:[$n[0].Array.type(System.Byte),$n[0].Int32,$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{v:!0,a:2,n:"GetChars",t:8,pi:[{n:"bytes",pt:$n[0].Array.type(System.Byte),ps:0}],sn:"GetChars",rt:$n[0].Array.type(System.Char),p:[$n[0].Array.type(System.Byte)]},{v:!0,a:2,n:"GetChars",t:8,pi:[{n:"bytes",pt:$n[0].Array.type(System.Byte),ps:0},{n:"index",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2}],sn:"GetChars$1",rt:$n[0].Array.type(System.Char),p:[$n[0].Array.type(System.Byte),$n[0].Int32,$n[0].Int32]},{a:2,n:"GetChars",t:8,pi:[{n:"bytes",pt:$n[0].Array.type(System.Byte),ps:0},{n:"byteIndex",pt:$n[0].Int32,ps:1},{n:"byteCount",pt:$n[0].Int32,ps:2},{n:"chars",pt:$n[0].Array.type(System.Char),ps:3},{n:"charIndex",pt:$n[0].Int32,ps:4}],sn:"GetChars$2",rt:$n[0].Int32,p:[$n[0].Array.type(System.Byte),$n[0].Int32,$n[0].Int32,$n[0].Array.type(System.Char),$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"GetEncoding",is:!0,t:8,pi:[{n:"codepage",pt:$n[0].Int32,ps:0}],sn:"GetEncoding",rt:$n[8].Encoding,p:[$n[0].Int32]},{a:2,n:"GetEncoding",is:!0,t:8,pi:[{n:"codepage",pt:$n[0].String,ps:0}],sn:"GetEncoding$1",rt:$n[8].Encoding,p:[$n[0].String]},{a:2,n:"GetEncodings",is:!0,t:8,sn:"GetEncodings",rt:System.Array.type(System.Text.EncodingInfo)},{ab:!0,a:2,n:"GetMaxByteCount",t:8,pi:[{n:"charCount",pt:$n[0].Int32,ps:0}],sn:"GetMaxByteCount",rt:$n[0].Int32,p:[$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{ab:!0,a:2,n:"GetMaxCharCount",t:8,pi:[{n:"byteCount",pt:$n[0].Int32,ps:0}],sn:"GetMaxCharCount",rt:$n[0].Int32,p:[$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{v:!0,a:2,n:"GetString",t:8,pi:[{n:"bytes",pt:$n[0].Array.type(System.Byte),ps:0}],sn:"GetString",rt:$n[0].String,p:[$n[0].Array.type(System.Byte)]},{v:!0,a:2,n:"GetString",t:8,pi:[{n:"bytes",pt:$n[0].Array.type(System.Byte),ps:0},{n:"index",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2}],sn:"GetString$1",rt:$n[0].String,p:[$n[0].Array.type(System.Byte),$n[0].Int32,$n[0].Int32]},{a:2,n:"ASCII",is:!0,t:16,rt:$n[8].Encoding,g:{a:2,n:"get_ASCII",t:8,rt:$n[8].Encoding,fg:"ASCII",is:!0},fn:"ASCII"},{a:2,n:"BigEndianUnicode",is:!0,t:16,rt:$n[8].Encoding,g:{a:2,n:"get_BigEndianUnicode",t:8,rt:$n[8].Encoding,fg:"BigEndianUnicode",is:!0},fn:"BigEndianUnicode"},{v:!0,a:2,n:"CodePage",t:16,rt:$n[0].Int32,g:{v:!0,a:2,n:"get_CodePage",t:8,rt:$n[0].Int32,fg:"CodePage",box:function($v){return H5.box($v,System.Int32)}},fn:"CodePage"},{a:2,n:"Default",is:!0,t:16,rt:$n[8].Encoding,g:{a:2,n:"get_Default",t:8,rt:$n[8].Encoding,fg:"Default",is:!0},fn:"Default"},{v:!0,a:2,n:"EncodingName",t:16,rt:$n[0].String,g:{v:!0,a:2,n:"get_EncodingName",t:8,rt:$n[0].String,fg:"EncodingName"},fn:"EncodingName"},{a:2,n:"UTF32",is:!0,t:16,rt:$n[8].Encoding,g:{a:2,n:"get_UTF32",t:8,rt:$n[8].Encoding,fg:"UTF32",is:!0},fn:"UTF32"},{a:2,n:"UTF7",is:!0,t:16,rt:$n[8].Encoding,g:{a:2,n:"get_UTF7",t:8,rt:$n[8].Encoding,fg:"UTF7",is:!0},fn:"UTF7"},{a:2,n:"UTF8",is:!0,t:16,rt:$n[8].Encoding,g:{a:2,n:"get_UTF8",t:8,rt:$n[8].Encoding,fg:"UTF8",is:!0},fn:"UTF8"},{a:2,n:"Unicode",is:!0,t:16,rt:$n[8].Encoding,g:{a:2,n:"get_Unicode",t:8,rt:$n[8].Encoding,fg:"Unicode",is:!0},fn:"Unicode"},{a:1,n:"__Property__Initializer__ASCII",is:!0,t:4,rt:$n[8].Encoding,sn:"__Property__Initializer__ASCII"},{a:1,n:"__Property__Initializer__BigEndianUnicode",is:!0,t:4,rt:$n[8].Encoding,sn:"__Property__Initializer__BigEndianUnicode"},{a:1,n:"__Property__Initializer__Default",is:!0,t:4,rt:$n[8].Encoding,sn:"__Property__Initializer__Default"},{a:1,n:"__Property__Initializer__UTF32",is:!0,t:4,rt:$n[8].Encoding,sn:"__Property__Initializer__UTF32"},{a:1,n:"__Property__Initializer__UTF7",is:!0,t:4,rt:$n[8].Encoding,sn:"__Property__Initializer__UTF7"},{a:1,n:"__Property__Initializer__UTF8",is:!0,t:4,rt:$n[8].Encoding,sn:"__Property__Initializer__UTF8"},{a:1,n:"__Property__Initializer__Unicode",is:!0,t:4,rt:$n[8].Encoding,sn:"__Property__Initializer__Unicode"},{a:1,n:"_encodings",is:!0,t:4,rt:System.Array.type(System.Text.EncodingInfo),sn:"_encodings"},{a:4,n:"_hasError",t:4,rt:$n[0].Boolean,sn:"_hasError",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:3,n:"fallbackCharacter",t:4,rt:$n[0].Char,sn:"fallbackCharacter",box:function($v){return H5.box($v,System.Char,String.fromCharCode,System.Char.getHashCode)}},{a:1,backing:!0,n:"k__BackingField",is:!0,t:4,rt:$n[8].Encoding,sn:"ASCII"},{a:1,backing:!0,n:"k__BackingField",is:!0,t:4,rt:$n[8].Encoding,sn:"BigEndianUnicode"},{a:1,backing:!0,n:"k__BackingField",is:!0,t:4,rt:$n[8].Encoding,sn:"Default"},{a:1,backing:!0,n:"k__BackingField",is:!0,t:4,rt:$n[8].Encoding,sn:"UTF32"},{a:1,backing:!0,n:"k__BackingField",is:!0,t:4,rt:$n[8].Encoding,sn:"UTF7"},{a:1,backing:!0,n:"k__BackingField",is:!0,t:4,rt:$n[8].Encoding,sn:"UTF8"},{a:1,backing:!0,n:"k__BackingField",is:!0,t:4,rt:$n[8].Encoding,sn:"Unicode"}]}},$n);$m("System.Text.EncodingInfo",function(){return{att:1048833,a:2,m:[{a:4,n:".ctor",t:1,p:[$n[0].Int32,$n[0].String,$n[0].String],pi:[{n:"codePage",pt:$n[0].Int32,ps:0},{n:"name",pt:$n[0].String,ps:1},{n:"displayName",pt:$n[0].String,ps:2}],sn:"ctor"},{ov:!0,a:2,n:"Equals",t:8,pi:[{n:"o",pt:$n[0].Object,ps:0}],sn:"equals",rt:$n[0].Boolean,p:[$n[0].Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"GetEncoding",t:8,sn:"GetEncoding",rt:$n[8].Encoding},{ov:!0,a:2,n:"GetHashCode",t:8,sn:"getHashCode",rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"CodePage",t:16,rt:$n[0].Int32,g:{a:2,n:"get_CodePage",t:8,rt:$n[0].Int32,fg:"CodePage",box:function($v){return H5.box($v,System.Int32)}},fn:"CodePage"},{a:2,n:"DisplayName",t:16,rt:$n[0].String,g:{a:2,n:"get_DisplayName",t:8,rt:$n[0].String,fg:"DisplayName"},fn:"DisplayName"},{a:2,n:"Name",t:16,rt:$n[0].String,g:{a:2,n:"get_Name",t:8,rt:$n[0].String,fg:"Name"},fn:"Name"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Int32,sn:"CodePage",box:function($v){return H5.box($v,System.Int32)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"DisplayName"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"Name"}]}},$n);$m("System.Text.StringBuilder",function(){return{att:1048577,a:2,m:[{a:2,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].Int32],pi:[{n:"capacity",pt:$n[0].Int32,ps:0}],def:function(capacity){return new System.Text.StringBuilder("",capacity)}},{a:2,n:".ctor",t:1,p:[$n[0].String],pi:[{n:"value",pt:$n[0].String,ps:0}],sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[0].Int32],pi:[{n:"value",pt:$n[0].String,ps:0},{n:"capacity",pt:$n[0].Int32,ps:1}],sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[0].Int32,$n[0].Int32],pi:[{n:"value",pt:$n[0].String,ps:0},{n:"startIndex",pt:$n[0].Int32,ps:1},{n:"length",pt:$n[0].Int32,ps:2}],sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[0].Int32,$n[0].Int32,$n[0].Int32],pi:[{n:"value",pt:$n[0].String,ps:0},{n:"startIndex",pt:$n[0].Int32,ps:1},{n:"length",pt:$n[0].Int32,ps:2},{n:"capacity",pt:$n[0].Int32,ps:3}],sn:"ctor"},{a:2,n:"Append",t:8,pi:[{n:"value",pt:$n[0].Boolean,ps:0}],sn:"append",rt:$n[8].StringBuilder,p:[$n[0].Boolean]},{a:2,n:"Append",t:8,pi:[{n:"value",pt:$n[0].Byte,ps:0}],sn:"append",rt:$n[8].StringBuilder,p:[$n[0].Byte]},{a:2,n:"Append",t:8,pi:[{n:"value",pt:$n[0].Char,ps:0}],tpc:0,def:function(value){return this.append(String.fromCharCode(value))},rt:$n[8].StringBuilder,p:[$n[0].Char]},{a:2,n:"Append",t:8,pi:[{n:"value",pt:$n[0].Decimal,ps:0}],sn:"append",rt:$n[8].StringBuilder,p:[$n[0].Decimal]},{a:2,n:"Append",t:8,pi:[{n:"value",pt:$n[0].Double,ps:0}],sn:"append",rt:$n[8].StringBuilder,p:[$n[0].Double]},{a:2,n:"Append",t:8,pi:[{n:"value",pt:$n[0].Int32,ps:0}],sn:"append",rt:$n[8].StringBuilder,p:[$n[0].Int32]},{a:2,n:"Append",t:8,pi:[{n:"value",pt:$n[0].Int64,ps:0}],tpc:0,def:function(value){return this.append(value.toString())},rt:$n[8].StringBuilder,p:[$n[0].Int64]},{a:2,n:"Append",t:8,pi:[{n:"value",pt:$n[0].Object,ps:0}],sn:"append",rt:$n[8].StringBuilder,p:[$n[0].Object]},{a:2,n:"Append",t:8,pi:[{n:"value",pt:$n[0].Single,ps:0}],sn:"append",rt:$n[8].StringBuilder,p:[$n[0].Single]},{a:2,n:"Append",t:8,pi:[{n:"value",pt:$n[0].String,ps:0}],sn:"append",rt:$n[8].StringBuilder,p:[$n[0].String]},{a:2,n:"Append",t:8,pi:[{n:"value",pt:$n[0].UInt32,ps:0}],sn:"append",rt:$n[8].StringBuilder,p:[$n[0].UInt32]},{a:2,n:"Append",t:8,pi:[{n:"value",pt:$n[0].UInt64,ps:0}],tpc:0,def:function(value){return this.append(value.toString())},rt:$n[8].StringBuilder,p:[$n[0].UInt64]},{a:2,n:"Append",t:8,pi:[{n:"value",pt:$n[0].Char,ps:0},{n:"repeatCount",pt:$n[0].Int32,ps:1}],tpc:0,def:function(value,repeatCount){return this.append(String.fromCharCode(value),repeatCount)},rt:$n[8].StringBuilder,p:[$n[0].Char,$n[0].Int32]},{a:2,n:"Append",t:8,pi:[{n:"value",pt:$n[0].String,ps:0},{n:"startIndex",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2}],sn:"append",rt:$n[8].StringBuilder,p:[$n[0].String,$n[0].Int32,$n[0].Int32]},{a:2,n:"AppendFormat",t:8,pi:[{n:"format",pt:$n[0].String,ps:0},{n:"args",ip:!0,pt:$n[0].Array.type(System.Object),ps:1}],sn:"appendFormat",rt:$n[8].StringBuilder,p:[$n[0].String,$n[0].Array.type(System.Object)]},{a:2,n:"AppendLine",t:8,sn:"appendLine",rt:$n[8].StringBuilder},{a:2,n:"AppendLine",t:8,pi:[{n:"value",pt:$n[0].String,ps:0}],sn:"appendLine",rt:$n[8].StringBuilder,p:[$n[0].String]},{a:2,n:"Clear",t:8,sn:"clear",rt:$n[8].StringBuilder},{a:2,n:"Equals",t:8,pi:[{n:"sb",pt:$n[8].StringBuilder,ps:0}],sn:"equals",rt:$n[0].Boolean,p:[$n[8].StringBuilder],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Insert",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0},{n:"value",pt:$n[0].Boolean,ps:1}],sn:"insert",rt:$n[8].StringBuilder,p:[$n[0].Int32,$n[0].Boolean]},{a:2,n:"Insert",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0},{n:"value",pt:$n[0].Char,ps:1}],tpc:0,def:function(index,value){return this.insert(index,String.fromCharCode(value))},rt:$n[8].StringBuilder,p:[$n[0].Int32,$n[0].Char]},{a:2,n:"Insert",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0},{n:"value",pt:$n[0].Decimal,ps:1}],sn:"insert",rt:$n[8].StringBuilder,p:[$n[0].Int32,$n[0].Decimal]},{a:2,n:"Insert",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0},{n:"value",pt:$n[0].Double,ps:1}],sn:"insert",rt:$n[8].StringBuilder,p:[$n[0].Int32,$n[0].Double]},{a:2,n:"Insert",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0},{n:"value",pt:$n[0].Int32,ps:1}],sn:"insert",rt:$n[8].StringBuilder,p:[$n[0].Int32,$n[0].Int32]},{a:2,n:"Insert",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0},{n:"value",pt:$n[0].Int64,ps:1}],tpc:0,def:function(index,value){return this.insert(index,value.toString())},rt:$n[8].StringBuilder,p:[$n[0].Int32,$n[0].Int64]},{a:2,n:"Insert",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0},{n:"value",pt:$n[0].Object,ps:1}],sn:"insert",rt:$n[8].StringBuilder,p:[$n[0].Int32,$n[0].Object]},{a:2,n:"Insert",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0},{n:"value",pt:$n[0].Single,ps:1}],sn:"insert",rt:$n[8].StringBuilder,p:[$n[0].Int32,$n[0].Single]},{a:2,n:"Insert",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0},{n:"value",pt:$n[0].String,ps:1}],sn:"insert",rt:$n[8].StringBuilder,p:[$n[0].Int32,$n[0].String]},{a:2,n:"Insert",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0},{n:"value",pt:$n[0].UInt32,ps:1}],sn:"insert",rt:$n[8].StringBuilder,p:[$n[0].Int32,$n[0].UInt32]},{a:2,n:"Insert",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0},{n:"value",pt:$n[0].UInt64,ps:1}],tpc:0,def:function(index,value){return this.insert(index,value.toString())},rt:$n[8].StringBuilder,p:[$n[0].Int32,$n[0].UInt64]},{a:2,n:"Insert",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0},{n:"value",pt:$n[0].String,ps:1},{n:"count",pt:$n[0].Int32,ps:2}],sn:"insert",rt:$n[8].StringBuilder,p:[$n[0].Int32,$n[0].String,$n[0].Int32]},{a:2,n:"Remove",t:8,pi:[{n:"startIndex",pt:$n[0].Int32,ps:0},{n:"length",pt:$n[0].Int32,ps:1}],sn:"remove",rt:$n[8].StringBuilder,p:[$n[0].Int32,$n[0].Int32]},{a:2,n:"Replace",t:8,pi:[{n:"oldChar",pt:$n[0].Char,ps:0},{n:"newChar",pt:$n[0].Char,ps:1}],tpc:0,def:function(oldChar,newChar){return this.replace(String.fromCharCode(oldChar),String.fromCharCode(newChar))},rt:$n[8].StringBuilder,p:[$n[0].Char,$n[0].Char]},{a:2,n:"Replace",t:8,pi:[{n:"oldValue",pt:$n[0].String,ps:0},{n:"newValue",pt:$n[0].String,ps:1}],sn:"replace",rt:$n[8].StringBuilder,p:[$n[0].String,$n[0].String]},{a:2,n:"Replace",t:8,pi:[{n:"oldChar",pt:$n[0].Char,ps:0},{n:"newChar",pt:$n[0].Char,ps:1},{n:"startIndex",pt:$n[0].Int32,ps:2},{n:"count",pt:$n[0].Int32,ps:3}],tpc:0,def:function(oldChar,newChar,startIndex,count){return this.replace(String.fromCharCode(oldChar),String.fromCharCode(newChar),startIndex,count)},rt:$n[8].StringBuilder,p:[$n[0].Char,$n[0].Char,$n[0].Int32,$n[0].Int32]},{a:2,n:"Replace",t:8,pi:[{n:"oldValue",pt:$n[0].String,ps:0},{n:"newValue",pt:$n[0].String,ps:1},{n:"startIndex",pt:$n[0].Int32,ps:2},{n:"count",pt:$n[0].Int32,ps:3}],sn:"replace",rt:$n[8].StringBuilder,p:[$n[0].String,$n[0].String,$n[0].Int32,$n[0].Int32]},{ov:!0,a:2,n:"ToString",t:8,sn:"toString",rt:$n[0].String},{a:2,n:"ToString",t:8,pi:[{n:"startIndex",pt:$n[0].Int32,ps:0},{n:"length",pt:$n[0].Int32,ps:1}],sn:"toString",rt:$n[0].String,p:[$n[0].Int32,$n[0].Int32]},{a:2,n:"Capacity",t:16,rt:$n[0].Int32,g:{a:2,n:"get_Capacity",t:8,tpc:0,def:function(){return this.getCapacity()},rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}},s:{a:2,n:"set_Capacity",t:8,pi:[{n:"value",pt:$n[0].Int32,ps:0}],tpc:0,def:function(value){return this.setCapacity(value)},rt:$n[0].Void,p:[$n[0].Int32]}},{a:2,n:"Item",t:16,rt:$n[0].Char,p:[$n[0].Int32],i:!0,ipi:[{n:"index",pt:$n[0].Int32,ps:0}],g:{a:2,n:"get_Item",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0}],sn:"getChar",rt:$n[0].Char,p:[$n[0].Int32],box:function($v){return H5.box($v,System.Char,String.fromCharCode,System.Char.getHashCode)}},s:{a:2,n:"set_Item",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0},{n:"value",pt:$n[0].Char,ps:1}],sn:"setChar",rt:$n[0].Void,p:[$n[0].Int32,$n[0].Char]}},{a:2,n:"Length",t:16,rt:$n[0].Int32,g:{a:2,n:"get_Length",t:8,tpc:0,def:function(){return this.getLength()},rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}},s:{a:2,n:"set_Length",t:8,pi:[{n:"value",pt:$n[0].Int32,ps:0}],tpc:0,def:function(value){return this.setLength(value)},rt:$n[0].Void,p:[$n[0].Int32]}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Int32,sn:"Capacity",box:function($v){return H5.box($v,System.Int32)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Char,sn:"Char",box:function($v){return H5.box($v,System.Char,String.fromCharCode,System.Char.getHashCode)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Int32,sn:"Length",box:function($v){return H5.box($v,System.Int32)}}]}},$n);$m("System.Text.UnicodeEncoding",function(){return{att:1048577,a:2,m:[{a:2,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].Boolean,$n[0].Boolean],pi:[{n:"bigEndian",pt:$n[0].Boolean,ps:0},{n:"byteOrderMark",pt:$n[0].Boolean,ps:1}],sn:"$ctor1"},{a:2,n:".ctor",t:1,p:[$n[0].Boolean,$n[0].Boolean,$n[0].Boolean],pi:[{n:"bigEndian",pt:$n[0].Boolean,ps:0},{n:"byteOrderMark",pt:$n[0].Boolean,ps:1},{n:"throwOnInvalidBytes",pt:$n[0].Boolean,ps:2}],sn:"$ctor2"},{ov:!0,a:3,n:"Decode",t:8,pi:[{n:"bytes",pt:$n[0].Array.type(System.Byte),ps:0},{n:"index",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2},{n:"chars",pt:$n[0].Array.type(System.Char),ps:3},{n:"charIndex",pt:$n[0].Int32,ps:4}],sn:"Decode$2",rt:$n[0].String,p:[$n[0].Array.type(System.Byte),$n[0].Int32,$n[0].Int32,$n[0].Array.type(System.Char),$n[0].Int32]},{ov:!0,a:3,n:"Encode",t:8,pi:[{n:"s",pt:$n[0].String,ps:0},{n:"outputBytes",pt:$n[0].Array.type(System.Byte),ps:1},{n:"outputIndex",pt:$n[0].Int32,ps:2},{n:"writtenBytes",out:!0,pt:$n[0].Int32,ps:3}],sn:"Encode$3",rt:$n[0].Array.type(System.Byte),p:[$n[0].String,$n[0].Array.type(System.Byte),$n[0].Int32,$n[0].Int32]},{ov:!0,a:2,n:"GetMaxByteCount",t:8,pi:[{n:"charCount",pt:$n[0].Int32,ps:0}],sn:"GetMaxByteCount",rt:$n[0].Int32,p:[$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{ov:!0,a:2,n:"GetMaxCharCount",t:8,pi:[{n:"byteCount",pt:$n[0].Int32,ps:0}],sn:"GetMaxCharCount",rt:$n[0].Int32,p:[$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{ov:!0,a:2,n:"CodePage",t:16,rt:$n[0].Int32,g:{ov:!0,a:2,n:"get_CodePage",t:8,rt:$n[0].Int32,fg:"CodePage",box:function($v){return H5.box($v,System.Int32)}},fn:"CodePage"},{ov:!0,a:2,n:"EncodingName",t:16,rt:$n[0].String,g:{ov:!0,a:2,n:"get_EncodingName",t:8,rt:$n[0].String,fg:"EncodingName"},fn:"EncodingName"},{a:1,n:"bigEndian",t:4,rt:$n[0].Boolean,sn:"bigEndian",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"byteOrderMark",t:4,rt:$n[0].Boolean,sn:"byteOrderMark",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"throwOnInvalid",t:4,rt:$n[0].Boolean,sn:"throwOnInvalid",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}}]}},$n);$m("System.Text.UTF32Encoding",function(){return{att:1048577,a:2,m:[{a:2,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].Boolean,$n[0].Boolean],pi:[{n:"bigEndian",pt:$n[0].Boolean,ps:0},{n:"byteOrderMark",pt:$n[0].Boolean,ps:1}],sn:"$ctor1"},{a:2,n:".ctor",t:1,p:[$n[0].Boolean,$n[0].Boolean,$n[0].Boolean],pi:[{n:"bigEndian",pt:$n[0].Boolean,ps:0},{n:"byteOrderMark",pt:$n[0].Boolean,ps:1},{n:"throwOnInvalidBytes",pt:$n[0].Boolean,ps:2}],sn:"$ctor2"},{ov:!0,a:3,n:"Decode",t:8,pi:[{n:"bytes",pt:$n[0].Array.type(System.Byte),ps:0},{n:"index",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2},{n:"chars",pt:$n[0].Array.type(System.Char),ps:3},{n:"charIndex",pt:$n[0].Int32,ps:4}],sn:"Decode$2",rt:$n[0].String,p:[$n[0].Array.type(System.Byte),$n[0].Int32,$n[0].Int32,$n[0].Array.type(System.Char),$n[0].Int32]},{ov:!0,a:3,n:"Encode",t:8,pi:[{n:"s",pt:$n[0].String,ps:0},{n:"outputBytes",pt:$n[0].Array.type(System.Byte),ps:1},{n:"outputIndex",pt:$n[0].Int32,ps:2},{n:"writtenBytes",out:!0,pt:$n[0].Int32,ps:3}],sn:"Encode$3",rt:$n[0].Array.type(System.Byte),p:[$n[0].String,$n[0].Array.type(System.Byte),$n[0].Int32,$n[0].Int32]},{ov:!0,a:2,n:"GetMaxByteCount",t:8,pi:[{n:"charCount",pt:$n[0].Int32,ps:0}],sn:"GetMaxByteCount",rt:$n[0].Int32,p:[$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{ov:!0,a:2,n:"GetMaxCharCount",t:8,pi:[{n:"byteCount",pt:$n[0].Int32,ps:0}],sn:"GetMaxCharCount",rt:$n[0].Int32,p:[$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"ToCodePoints",t:8,pi:[{n:"str",pt:$n[0].String,ps:0}],sn:"ToCodePoints",rt:$n[0].Array.type(System.Char),p:[$n[0].String]},{ov:!0,a:2,n:"CodePage",t:16,rt:$n[0].Int32,g:{ov:!0,a:2,n:"get_CodePage",t:8,rt:$n[0].Int32,fg:"CodePage",box:function($v){return H5.box($v,System.Int32)}},fn:"CodePage"},{ov:!0,a:2,n:"EncodingName",t:16,rt:$n[0].String,g:{ov:!0,a:2,n:"get_EncodingName",t:8,rt:$n[0].String,fg:"EncodingName"},fn:"EncodingName"},{a:1,n:"bigEndian",t:4,rt:$n[0].Boolean,sn:"bigEndian",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"byteOrderMark",t:4,rt:$n[0].Boolean,sn:"byteOrderMark",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"throwOnInvalid",t:4,rt:$n[0].Boolean,sn:"throwOnInvalid",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}}]}},$n);$m("System.Text.UTF7Encoding",function(){return{att:1048577,a:2,m:[{a:2,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].Boolean],pi:[{n:"allowOptionals",pt:$n[0].Boolean,ps:0}],sn:"$ctor1"},{ov:!0,a:3,n:"Decode",t:8,pi:[{n:"bytes",pt:$n[0].Array.type(System.Byte),ps:0},{n:"index",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2},{n:"chars",pt:$n[0].Array.type(System.Char),ps:3},{n:"charIndex",pt:$n[0].Int32,ps:4}],sn:"Decode$2",rt:$n[0].String,p:[$n[0].Array.type(System.Byte),$n[0].Int32,$n[0].Int32,$n[0].Array.type(System.Char),$n[0].Int32]},{ov:!0,a:3,n:"Encode",t:8,pi:[{n:"s",pt:$n[0].String,ps:0},{n:"outputBytes",pt:$n[0].Array.type(System.Byte),ps:1},{n:"outputIndex",pt:$n[0].Int32,ps:2},{n:"writtenBytes",out:!0,pt:$n[0].Int32,ps:3}],sn:"Encode$3",rt:$n[0].Array.type(System.Byte),p:[$n[0].String,$n[0].Array.type(System.Byte),$n[0].Int32,$n[0].Int32]},{a:1,n:"Escape",is:!0,t:8,pi:[{n:"chars",pt:$n[0].String,ps:0}],sn:"Escape",rt:$n[0].String,p:[$n[0].String]},{ov:!0,a:2,n:"GetMaxByteCount",t:8,pi:[{n:"charCount",pt:$n[0].Int32,ps:0}],sn:"GetMaxByteCount",rt:$n[0].Int32,p:[$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{ov:!0,a:2,n:"GetMaxCharCount",t:8,pi:[{n:"byteCount",pt:$n[0].Int32,ps:0}],sn:"GetMaxCharCount",rt:$n[0].Int32,p:[$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{ov:!0,a:2,n:"CodePage",t:16,rt:$n[0].Int32,g:{ov:!0,a:2,n:"get_CodePage",t:8,rt:$n[0].Int32,fg:"CodePage",box:function($v){return H5.box($v,System.Int32)}},fn:"CodePage"},{ov:!0,a:2,n:"EncodingName",t:16,rt:$n[0].String,g:{ov:!0,a:2,n:"get_EncodingName",t:8,rt:$n[0].String,fg:"EncodingName"},fn:"EncodingName"},{a:1,n:"allowOptionals",t:4,rt:$n[0].Boolean,sn:"allowOptionals",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}}]}},$n);$m("System.Text.UTF8Encoding",function(){return{att:1048577,a:2,m:[{a:2,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].Boolean],pi:[{n:"encoderShouldEmitUTF8Identifier",pt:$n[0].Boolean,ps:0}],sn:"$ctor1"},{a:2,n:".ctor",t:1,p:[$n[0].Boolean,$n[0].Boolean],pi:[{n:"encoderShouldEmitUTF8Identifier",pt:$n[0].Boolean,ps:0},{n:"throwOnInvalidBytes",pt:$n[0].Boolean,ps:1}],sn:"$ctor2"},{ov:!0,a:3,n:"Decode",t:8,pi:[{n:"bytes",pt:$n[0].Array.type(System.Byte),ps:0},{n:"index",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2},{n:"chars",pt:$n[0].Array.type(System.Char),ps:3},{n:"charIndex",pt:$n[0].Int32,ps:4}],sn:"Decode$2",rt:$n[0].String,p:[$n[0].Array.type(System.Byte),$n[0].Int32,$n[0].Int32,$n[0].Array.type(System.Char),$n[0].Int32]},{ov:!0,a:3,n:"Encode",t:8,pi:[{n:"s",pt:$n[0].String,ps:0},{n:"outputBytes",pt:$n[0].Array.type(System.Byte),ps:1},{n:"outputIndex",pt:$n[0].Int32,ps:2},{n:"writtenBytes",out:!0,pt:$n[0].Int32,ps:3}],sn:"Encode$3",rt:$n[0].Array.type(System.Byte),p:[$n[0].String,$n[0].Array.type(System.Byte),$n[0].Int32,$n[0].Int32]},{ov:!0,a:2,n:"GetMaxByteCount",t:8,pi:[{n:"charCount",pt:$n[0].Int32,ps:0}],sn:"GetMaxByteCount",rt:$n[0].Int32,p:[$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{ov:!0,a:2,n:"GetMaxCharCount",t:8,pi:[{n:"byteCount",pt:$n[0].Int32,ps:0}],sn:"GetMaxCharCount",rt:$n[0].Int32,p:[$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{ov:!0,a:2,n:"CodePage",t:16,rt:$n[0].Int32,g:{ov:!0,a:2,n:"get_CodePage",t:8,rt:$n[0].Int32,fg:"CodePage",box:function($v){return H5.box($v,System.Int32)}},fn:"CodePage"},{ov:!0,a:2,n:"EncodingName",t:16,rt:$n[0].String,g:{ov:!0,a:2,n:"get_EncodingName",t:8,rt:$n[0].String,fg:"EncodingName"},fn:"EncodingName"},{a:1,n:"encoderShouldEmitUTF8Identifier",t:4,rt:$n[0].Boolean,sn:"encoderShouldEmitUTF8Identifier",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"throwOnInvalid",t:4,rt:$n[0].Boolean,sn:"throwOnInvalid",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}}]}},$n);$m("System.Text.RegularExpressions.Capture",function(){return{att:1048577,a:2,m:[{a:4,n:".ctor",t:1,p:[$n[0].String,$n[0].Int32,$n[0].Int32],pi:[{n:"text",pt:$n[0].String,ps:0},{n:"i",pt:$n[0].Int32,ps:1},{n:"l",pt:$n[0].Int32,ps:2}],sn:"ctor"},{ov:!0,a:2,n:"ToString",t:8,sn:"toString",rt:$n[0].String},{a:2,n:"Index",t:16,rt:$n[0].Int32,g:{a:2,n:"get_Index",t:8,tpc:0,def:function(){return this.getIndex()},rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}}},{a:2,n:"Length",t:16,rt:$n[0].Int32,g:{a:2,n:"get_Length",t:8,tpc:0,def:function(){return this.getLength()},rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}}},{a:2,n:"Value",t:16,rt:$n[0].String,g:{a:2,n:"get_Value",t:8,tpc:0,def:function(){return this.getValue()},rt:$n[0].String}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Int32,sn:"Index",box:function($v){return H5.box($v,System.Int32)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Int32,sn:"Length",box:function($v){return H5.box($v,System.Int32)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"Value"}]}},$n);$m("System.Text.RegularExpressions.CaptureCollection",function(){return{att:1048577,a:2,m:[{a:4,n:".ctor",t:1,sn:"ctor"},{a:2,n:"CopyTo",t:8,pi:[{n:"array",pt:Array,ps:0},{n:"arrayIndex",pt:$n[0].Int32,ps:1}],sn:"copyTo",rt:$n[0].Void,p:[Array,$n[0].Int32]},{a:2,n:"GetEnumerator",t:8,sn:"GetEnumerator",rt:$n[6].IEnumerator},{a:2,n:"Count",t:16,rt:$n[0].Int32,g:{a:2,n:"get_Count",t:8,tpc:0,def:function(){return this.getCount()},rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}}},{a:2,n:"IsReadOnly",t:16,rt:$n[0].Boolean,g:{a:2,n:"get_IsReadOnly",t:8,tpc:0,def:function(){return this.getIsReadOnly()},rt:$n[0].Boolean,box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}}},{a:2,n:"IsSynchronized",t:16,rt:$n[0].Boolean,g:{a:2,n:"get_IsSynchronized",t:8,tpc:0,def:function(){return this.getIsSynchronized()},rt:$n[0].Boolean,box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}}},{a:2,n:"Item",t:16,rt:$n[11].Capture,p:[$n[0].Int32],i:!0,ipi:[{n:"i",pt:$n[0].Int32,ps:0}],g:{a:2,n:"get_Item",t:8,pi:[{n:"i",pt:$n[0].Int32,ps:0}],tpc:0,def:function(i){return this.get(i)},rt:$n[11].Capture,p:[$n[0].Int32]}},{a:2,n:"SyncRoot",t:16,rt:$n[0].Object,g:{a:2,n:"get_SyncRoot",t:8,tpc:0,def:function(){return this.getSyncRoot()},rt:$n[0].Object}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Int32,sn:"Count",box:function($v){return H5.box($v,System.Int32)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Boolean,sn:"IsReadOnly",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Boolean,sn:"IsSynchronized",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[11].Capture,sn:"Item"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Object,sn:"SyncRoot"}]}},$n);$m("System.Text.RegularExpressions.Group",function(){return{att:1048577,a:2,m:[{a:4,n:".ctor",t:1,p:[$n[0].String,$n[0].Array.type(System.Int32),$n[0].Int32],pi:[{n:"text",pt:$n[0].String,ps:0},{n:"caps",pt:$n[0].Array.type(System.Int32),ps:1},{n:"capcount",pt:$n[0].Int32,ps:2}],sn:"ctor"},{a:2,n:"Synchronized",is:!0,t:8,pi:[{n:"inner",pt:$n[11].Group,ps:0}],sn:"synchronized",rt:$n[11].Group,p:[$n[11].Group]},{a:2,n:"Captures",t:16,rt:$n[11].CaptureCollection,g:{a:2,n:"get_Captures",t:8,tpc:0,def:function(){return this.getCaptures()},rt:$n[11].CaptureCollection}},{a:2,n:"Success",t:16,rt:$n[0].Boolean,g:{a:2,n:"get_Success",t:8,tpc:0,def:function(){return this.getSuccess()},rt:$n[0].Boolean,box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[11].CaptureCollection,sn:"Captures"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Boolean,sn:"Success",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}}]}},$n);$m("System.Text.RegularExpressions.GroupCollection",function(){return{att:1048577,a:2,m:[{a:4,n:".ctor",t:1,sn:"ctor"},{a:2,n:"CopyTo",t:8,pi:[{n:"array",pt:Array,ps:0},{n:"arrayIndex",pt:$n[0].Int32,ps:1}],sn:"copyTo",rt:$n[0].Void,p:[Array,$n[0].Int32]},{a:2,n:"GetEnumerator",t:8,sn:"GetEnumerator",rt:$n[6].IEnumerator},{a:2,n:"Count",t:16,rt:$n[0].Int32,g:{a:2,n:"get_Count",t:8,tpc:0,def:function(){return this.getCount()},rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}}},{a:2,n:"IsReadOnly",t:16,rt:$n[0].Boolean,g:{a:2,n:"get_IsReadOnly",t:8,tpc:0,def:function(){return this.getIsReadOnly()},rt:$n[0].Boolean,box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}}},{a:2,n:"IsSynchronized",t:16,rt:$n[0].Boolean,g:{a:2,n:"get_IsSynchronized",t:8,tpc:0,def:function(){return this.getIsSynchronized()},rt:$n[0].Boolean,box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}}},{a:2,n:"Item",t:16,rt:$n[11].Group,p:[$n[0].Int32],i:!0,ipi:[{n:"groupnum",pt:$n[0].Int32,ps:0}],g:{a:2,n:"get_Item",t:8,pi:[{n:"groupnum",pt:$n[0].Int32,ps:0}],tpc:0,def:function(groupnum){return this.get(groupnum)},rt:$n[11].Group,p:[$n[0].Int32]}},{a:2,n:"Item",t:16,rt:$n[11].Group,p:[$n[0].String],i:!0,ipi:[{n:"groupname",pt:$n[0].String,ps:0}],g:{a:2,n:"get_Item",t:8,pi:[{n:"groupname",pt:$n[0].String,ps:0}],tpc:0,def:function(groupname){return this.getByName(groupname)},rt:$n[11].Group,p:[$n[0].String]}},{a:2,n:"SyncRoot",t:16,rt:$n[0].Object,g:{a:2,n:"get_SyncRoot",t:8,tpc:0,def:function(){return this.getSyncRoot()},rt:$n[0].Object}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Int32,sn:"Count",box:function($v){return H5.box($v,System.Int32)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Boolean,sn:"IsReadOnly",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Boolean,sn:"IsSynchronized",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[11].Group,sn:"Item"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[11].Group,sn:"Item"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Object,sn:"SyncRoot"}]}},$n);$m("System.Text.RegularExpressions.Match",function(){return{att:1048577,a:2,m:[{a:4,n:".ctor",t:1,p:[$n[11].Regex,$n[0].Int32,$n[0].String,$n[0].Int32,$n[0].Int32,$n[0].Int32],pi:[{n:"regex",pt:$n[11].Regex,ps:0},{n:"capcount",pt:$n[0].Int32,ps:1},{n:"text",pt:$n[0].String,ps:2},{n:"begpos",pt:$n[0].Int32,ps:3},{n:"len",pt:$n[0].Int32,ps:4},{n:"startpos",pt:$n[0].Int32,ps:5}],sn:"ctor"},{a:2,n:"NextMatch",t:8,sn:"nextMatch",rt:$n[11].Match},{v:!0,a:2,n:"Result",t:8,pi:[{n:"replacement",pt:$n[0].String,ps:0}],sn:"result",rt:$n[0].String,p:[$n[0].String]},{a:2,n:"Synchronized",is:!0,t:8,pi:[{n:"inner",pt:$n[11].Match,ps:0}],sn:"synchronized",rt:$n[11].Match,p:[$n[11].Match]},{a:2,n:"Empty",is:!0,t:16,rt:$n[11].Match,g:{a:2,n:"get_Empty",is:!0,t:8,tpc:0,def:function(){return this.getEmpty()},rt:$n[11].Match}},{v:!0,a:2,n:"Groups",t:16,rt:$n[11].GroupCollection,g:{v:!0,a:2,n:"get_Groups",t:8,tpc:0,def:function(){return this.getGroups()},rt:$n[11].GroupCollection}},{a:1,backing:!0,n:"k__BackingField",is:!0,t:4,rt:$n[11].Match,sn:"Empty"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[11].GroupCollection,sn:"Groups"}]}},$n);$m("System.Text.RegularExpressions.MatchCollection",function(){return{att:1048577,a:2,m:[{a:4,n:".ctor",t:1,p:[$n[11].Regex,$n[0].String,$n[0].Int32,$n[0].Int32,$n[0].Int32],pi:[{n:"regex",pt:$n[11].Regex,ps:0},{n:"input",pt:$n[0].String,ps:1},{n:"beginning",pt:$n[0].Int32,ps:2},{n:"length",pt:$n[0].Int32,ps:3},{n:"startat",pt:$n[0].Int32,ps:4}],sn:"ctor"},{a:2,n:"CopyTo",t:8,pi:[{n:"array",pt:Array,ps:0},{n:"arrayIndex",pt:$n[0].Int32,ps:1}],sn:"copyTo",rt:$n[0].Void,p:[Array,$n[0].Int32]},{a:2,n:"GetEnumerator",t:8,sn:"GetEnumerator",rt:$n[6].IEnumerator},{a:2,n:"Count",t:16,rt:$n[0].Int32,g:{a:2,n:"get_Count",t:8,tpc:0,def:function(){return this.getCount()},rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}}},{a:2,n:"IsReadOnly",t:16,rt:$n[0].Boolean,g:{a:2,n:"get_IsReadOnly",t:8,tpc:0,def:function(){return this.getIsReadOnly()},rt:$n[0].Boolean,box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}}},{a:2,n:"IsSynchronized",t:16,rt:$n[0].Boolean,g:{a:2,n:"get_IsSynchronized",t:8,tpc:0,def:function(){return this.getIsSynchronized()},rt:$n[0].Boolean,box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}}},{v:!0,a:2,n:"Item",t:16,rt:$n[11].Match,p:[$n[0].Int32],i:!0,ipi:[{n:"i",pt:$n[0].Int32,ps:0}],g:{v:!0,a:2,n:"get_Item",t:8,pi:[{n:"i",pt:$n[0].Int32,ps:0}],tpc:0,def:function(i){return this.get(i)},rt:$n[11].Match,p:[$n[0].Int32]}},{a:2,n:"SyncRoot",t:16,rt:$n[0].Object,g:{a:2,n:"get_SyncRoot",t:8,tpc:0,def:function(){return this.getSyncRoot()},rt:$n[0].Object}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Int32,sn:"Count",box:function($v){return H5.box($v,System.Int32)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Boolean,sn:"IsReadOnly",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Boolean,sn:"IsSynchronized",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[11].Match,sn:"Item"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Object,sn:"SyncRoot"}]}},$n);$m("System.Text.RegularExpressions.Regex",function(){return{att:1048833,a:2,m:[{a:2,n:".ctor",t:1,p:[$n[0].String],pi:[{n:"pattern",pt:$n[0].String,ps:0}],sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[11].RegexOptions],pi:[{n:"pattern",pt:$n[0].String,ps:0},{n:"options",pt:$n[11].RegexOptions,ps:1}],sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[11].RegexOptions,$n[0].TimeSpan],pi:[{n:"pattern",pt:$n[0].String,ps:0},{n:"options",pt:$n[11].RegexOptions,ps:1},{n:"matchTimeout",pt:$n[0].TimeSpan,ps:2}],sn:"ctor"},{a:2,n:"Escape",is:!0,t:8,pi:[{n:"str",pt:$n[0].String,ps:0}],sn:"escape",rt:$n[0].String,p:[$n[0].String]},{a:2,n:"GetGroupNames",t:8,sn:"getGroupNames",rt:$n[0].Array.type(System.String)},{a:2,n:"GetGroupNumbers",t:8,sn:"getGroupNumbers",rt:$n[0].Array.type(System.Int32)},{a:2,n:"GroupNameFromNumber",t:8,pi:[{n:"i",pt:$n[0].Int32,ps:0}],sn:"groupNameFromNumber",rt:$n[0].String,p:[$n[0].Int32]},{a:2,n:"GroupNumberFromName",t:8,pi:[{n:"name",pt:$n[0].String,ps:0}],sn:"groupNumberFromName",rt:$n[0].Int32,p:[$n[0].String],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"IsMatch",t:8,pi:[{n:"input",pt:$n[0].String,ps:0}],sn:"isMatch",rt:$n[0].Boolean,p:[$n[0].String],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"IsMatch",t:8,pi:[{n:"input",pt:$n[0].String,ps:0},{n:"startat",pt:$n[0].Int32,ps:1}],sn:"isMatch",rt:$n[0].Boolean,p:[$n[0].String,$n[0].Int32],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"IsMatch",is:!0,t:8,pi:[{n:"input",pt:$n[0].String,ps:0},{n:"pattern",pt:$n[0].String,ps:1}],sn:"isMatch",rt:$n[0].Boolean,p:[$n[0].String,$n[0].String],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"IsMatch",is:!0,t:8,pi:[{n:"input",pt:$n[0].String,ps:0},{n:"pattern",pt:$n[0].String,ps:1},{n:"options",pt:$n[11].RegexOptions,ps:2}],sn:"isMatch",rt:$n[0].Boolean,p:[$n[0].String,$n[0].String,$n[11].RegexOptions],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"IsMatch",is:!0,t:8,pi:[{n:"input",pt:$n[0].String,ps:0},{n:"pattern",pt:$n[0].String,ps:1},{n:"options",pt:$n[11].RegexOptions,ps:2},{n:"matchTimeout",pt:$n[0].TimeSpan,ps:3}],sn:"isMatch",rt:$n[0].Boolean,p:[$n[0].String,$n[0].String,$n[11].RegexOptions,$n[0].TimeSpan],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Match",t:8,pi:[{n:"input",pt:$n[0].String,ps:0}],sn:"match",rt:$n[11].Match,p:[$n[0].String]},{a:2,n:"Match",t:8,pi:[{n:"input",pt:$n[0].String,ps:0},{n:"startat",pt:$n[0].Int32,ps:1}],sn:"match",rt:$n[11].Match,p:[$n[0].String,$n[0].Int32]},{a:2,n:"Match",is:!0,t:8,pi:[{n:"input",pt:$n[0].String,ps:0},{n:"pattern",pt:$n[0].String,ps:1}],sn:"match",rt:$n[11].Match,p:[$n[0].String,$n[0].String]},{a:2,n:"Match",t:8,pi:[{n:"input",pt:$n[0].String,ps:0},{n:"beginning",pt:$n[0].Int32,ps:1},{n:"length",pt:$n[0].Int32,ps:2}],sn:"match",rt:$n[11].Match,p:[$n[0].String,$n[0].Int32,$n[0].Int32]},{a:2,n:"Match",is:!0,t:8,pi:[{n:"input",pt:$n[0].String,ps:0},{n:"pattern",pt:$n[0].String,ps:1},{n:"options",pt:$n[11].RegexOptions,ps:2}],sn:"match",rt:$n[11].Match,p:[$n[0].String,$n[0].String,$n[11].RegexOptions]},{a:2,n:"Match",is:!0,t:8,pi:[{n:"input",pt:$n[0].String,ps:0},{n:"pattern",pt:$n[0].String,ps:1},{n:"options",pt:$n[11].RegexOptions,ps:2},{n:"matchTimeout",pt:$n[0].TimeSpan,ps:3}],sn:"match",rt:$n[11].Match,p:[$n[0].String,$n[0].String,$n[11].RegexOptions,$n[0].TimeSpan]},{a:2,n:"Matches",t:8,pi:[{n:"input",pt:$n[0].String,ps:0}],sn:"matches",rt:$n[11].MatchCollection,p:[$n[0].String]},{a:2,n:"Matches",t:8,pi:[{n:"input",pt:$n[0].String,ps:0},{n:"startat",pt:$n[0].Int32,ps:1}],sn:"matches",rt:$n[11].MatchCollection,p:[$n[0].String,$n[0].Int32]},{a:2,n:"Matches",is:!0,t:8,pi:[{n:"input",pt:$n[0].String,ps:0},{n:"pattern",pt:$n[0].String,ps:1}],sn:"matches",rt:$n[11].MatchCollection,p:[$n[0].String,$n[0].String]},{a:2,n:"Matches",is:!0,t:8,pi:[{n:"input",pt:$n[0].String,ps:0},{n:"pattern",pt:$n[0].String,ps:1},{n:"options",pt:$n[11].RegexOptions,ps:2}],sn:"matches",rt:$n[11].MatchCollection,p:[$n[0].String,$n[0].String,$n[11].RegexOptions]},{a:2,n:"Matches",is:!0,t:8,pi:[{n:"input",pt:$n[0].String,ps:0},{n:"pattern",pt:$n[0].String,ps:1},{n:"options",pt:$n[11].RegexOptions,ps:2},{n:"matchTimeout",pt:$n[0].TimeSpan,ps:3}],sn:"matches",rt:$n[11].MatchCollection,p:[$n[0].String,$n[0].String,$n[11].RegexOptions,$n[0].TimeSpan]},{a:2,n:"Replace",t:8,pi:[{n:"input",pt:$n[0].String,ps:0},{n:"replacement",pt:$n[0].String,ps:1}],sn:"replace",rt:$n[0].String,p:[$n[0].String,$n[0].String]},{a:2,n:"Replace",t:8,pi:[{n:"input",pt:$n[0].String,ps:0},{n:"evaluator",pt:Function,ps:1}],sn:"replace",rt:$n[0].String,p:[$n[0].String,Function]},{a:2,n:"Replace",t:8,pi:[{n:"input",pt:$n[0].String,ps:0},{n:"replacement",pt:$n[0].String,ps:1},{n:"count",pt:$n[0].Int32,ps:2}],sn:"replace",rt:$n[0].String,p:[$n[0].String,$n[0].String,$n[0].Int32]},{a:2,n:"Replace",is:!0,t:8,pi:[{n:"input",pt:$n[0].String,ps:0},{n:"pattern",pt:$n[0].String,ps:1},{n:"replacement",pt:$n[0].String,ps:2}],sn:"replace",rt:$n[0].String,p:[$n[0].String,$n[0].String,$n[0].String]},{a:2,n:"Replace",is:!0,t:8,pi:[{n:"input",pt:$n[0].String,ps:0},{n:"pattern",pt:$n[0].String,ps:1},{n:"evaluator",pt:Function,ps:2}],sn:"replace",rt:$n[0].String,p:[$n[0].String,$n[0].String,Function]},{a:2,n:"Replace",t:8,pi:[{n:"input",pt:$n[0].String,ps:0},{n:"evaluator",pt:Function,ps:1},{n:"count",pt:$n[0].Int32,ps:2}],sn:"replace",rt:$n[0].String,p:[$n[0].String,Function,$n[0].Int32]},{a:2,n:"Replace",t:8,pi:[{n:"input",pt:$n[0].String,ps:0},{n:"replacement",pt:$n[0].String,ps:1},{n:"count",pt:$n[0].Int32,ps:2},{n:"startat",pt:$n[0].Int32,ps:3}],sn:"replace",rt:$n[0].String,p:[$n[0].String,$n[0].String,$n[0].Int32,$n[0].Int32]},{a:2,n:"Replace",is:!0,t:8,pi:[{n:"input",pt:$n[0].String,ps:0},{n:"pattern",pt:$n[0].String,ps:1},{n:"replacement",pt:$n[0].String,ps:2},{n:"options",pt:$n[11].RegexOptions,ps:3}],sn:"replace",rt:$n[0].String,p:[$n[0].String,$n[0].String,$n[0].String,$n[11].RegexOptions]},{a:2,n:"Replace",is:!0,t:8,pi:[{n:"input",pt:$n[0].String,ps:0},{n:"pattern",pt:$n[0].String,ps:1},{n:"evaluator",pt:Function,ps:2},{n:"options",pt:$n[11].RegexOptions,ps:3}],sn:"replace",rt:$n[0].String,p:[$n[0].String,$n[0].String,Function,$n[11].RegexOptions]},{a:2,n:"Replace",t:8,pi:[{n:"input",pt:$n[0].String,ps:0},{n:"evaluator",pt:Function,ps:1},{n:"count",pt:$n[0].Int32,ps:2},{n:"startat",pt:$n[0].Int32,ps:3}],sn:"replace",rt:$n[0].String,p:[$n[0].String,Function,$n[0].Int32,$n[0].Int32]},{a:2,n:"Replace",is:!0,t:8,pi:[{n:"input",pt:$n[0].String,ps:0},{n:"pattern",pt:$n[0].String,ps:1},{n:"replacement",pt:$n[0].String,ps:2},{n:"options",pt:$n[11].RegexOptions,ps:3},{n:"matchTimeout",pt:$n[0].TimeSpan,ps:4}],sn:"replace",rt:$n[0].String,p:[$n[0].String,$n[0].String,$n[0].String,$n[11].RegexOptions,$n[0].TimeSpan]},{a:2,n:"Replace",is:!0,t:8,pi:[{n:"input",pt:$n[0].String,ps:0},{n:"pattern",pt:$n[0].String,ps:1},{n:"evaluator",pt:Function,ps:2},{n:"options",pt:$n[11].RegexOptions,ps:3},{n:"matchTimeout",pt:$n[0].TimeSpan,ps:4}],sn:"replace",rt:$n[0].String,p:[$n[0].String,$n[0].String,Function,$n[11].RegexOptions,$n[0].TimeSpan]},{a:2,n:"Split",t:8,pi:[{n:"input",pt:$n[0].String,ps:0}],sn:"split",rt:$n[0].Array.type(System.String),p:[$n[0].String]},{a:2,n:"Split",t:8,pi:[{n:"input",pt:$n[0].String,ps:0},{n:"count",pt:$n[0].Int32,ps:1}],sn:"split",rt:$n[0].Array.type(System.String),p:[$n[0].String,$n[0].Int32]},{a:2,n:"Split",is:!0,t:8,pi:[{n:"input",pt:$n[0].String,ps:0},{n:"pattern",pt:$n[0].String,ps:1}],sn:"split",rt:$n[0].Array.type(System.String),p:[$n[0].String,$n[0].String]},{a:2,n:"Split",t:8,pi:[{n:"input",pt:$n[0].String,ps:0},{n:"count",pt:$n[0].Int32,ps:1},{n:"startat",pt:$n[0].Int32,ps:2}],sn:"split",rt:$n[0].Array.type(System.String),p:[$n[0].String,$n[0].Int32,$n[0].Int32]},{a:2,n:"Split",is:!0,t:8,pi:[{n:"input",pt:$n[0].String,ps:0},{n:"pattern",pt:$n[0].String,ps:1},{n:"options",pt:$n[11].RegexOptions,ps:2}],sn:"split",rt:$n[0].Array.type(System.String),p:[$n[0].String,$n[0].String,$n[11].RegexOptions]},{a:2,n:"Split",is:!0,t:8,pi:[{n:"input",pt:$n[0].String,ps:0},{n:"pattern",pt:$n[0].String,ps:1},{n:"options",pt:$n[11].RegexOptions,ps:2},{n:"matchTimeout",pt:$n[0].TimeSpan,ps:3}],sn:"split",rt:$n[0].Array.type(System.String),p:[$n[0].String,$n[0].String,$n[11].RegexOptions,$n[0].TimeSpan]},{a:2,n:"Unescape",is:!0,t:8,pi:[{n:"str",pt:$n[0].String,ps:0}],sn:"unescape",rt:$n[0].String,p:[$n[0].String]},{a:2,n:"MatchTimeout",t:16,rt:$n[0].TimeSpan,g:{a:2,n:"get_MatchTimeout",t:8,tpc:0,def:function(){return this.getMatchTimeout()},rt:$n[0].TimeSpan}},{a:2,n:"Options",t:16,rt:$n[11].RegexOptions,g:{a:2,n:"get_Options",t:8,tpc:0,def:function(){return this.getOptions()},rt:$n[11].RegexOptions}},{a:2,n:"RightToLeft",t:16,rt:$n[0].Boolean,g:{a:2,n:"get_RightToLeft",t:8,tpc:0,def:function(){return this.getRightToLeft()},rt:$n[0].Boolean,box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].TimeSpan,sn:"MatchTimeout"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[11].RegexOptions,sn:"Options"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Boolean,sn:"RightToLeft",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}}]}},$n);$m("System.Security.SecurityException",function(){return{att:1056769,a:2,at:[new System.SerializableAttribute],m:[{a:2,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].String],pi:[{n:"message",pt:$n[0].String,ps:0}],sn:"$ctor1"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[0].Exception],pi:[{n:"message",pt:$n[0].String,ps:0},{n:"inner",pt:$n[0].Exception,ps:1}],sn:"$ctor2"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[0].Type],pi:[{n:"message",pt:$n[0].String,ps:0},{n:"type",pt:$n[0].Type,ps:1}],sn:"$ctor3"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[0].Type,$n[0].String],pi:[{n:"message",pt:$n[0].String,ps:0},{n:"type",pt:$n[0].Type,ps:1},{n:"state",pt:$n[0].String,ps:2}],sn:"$ctor4"},{ov:!0,a:2,n:"ToString",t:8,sn:"toString",rt:$n[0].String},{a:2,n:"Demanded",t:16,rt:$n[0].Object,g:{a:2,n:"get_Demanded",t:8,rt:$n[0].Object,fg:"Demanded"},s:{a:2,n:"set_Demanded",t:8,p:[$n[0].Object],rt:$n[0].Void,fs:"Demanded"},fn:"Demanded"},{a:2,n:"DenySetInstance",t:16,rt:$n[0].Object,g:{a:2,n:"get_DenySetInstance",t:8,rt:$n[0].Object,fg:"DenySetInstance"},s:{a:2,n:"set_DenySetInstance",t:8,p:[$n[0].Object],rt:$n[0].Void,fs:"DenySetInstance"},fn:"DenySetInstance"},{a:2,n:"GrantedSet",t:16,rt:$n[0].String,g:{a:2,n:"get_GrantedSet",t:8,rt:$n[0].String,fg:"GrantedSet"},s:{a:2,n:"set_GrantedSet",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"GrantedSet"},fn:"GrantedSet"},{a:2,n:"Method",t:16,rt:$n[12].MethodInfo,g:{a:2,n:"get_Method",t:8,rt:$n[12].MethodInfo,fg:"Method"},s:{a:2,n:"set_Method",t:8,p:[$n[12].MethodInfo],rt:$n[0].Void,fs:"Method"},fn:"Method"},{a:2,n:"PermissionState",t:16,rt:$n[0].String,g:{a:2,n:"get_PermissionState",t:8,rt:$n[0].String,fg:"PermissionState"},s:{a:2,n:"set_PermissionState",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"PermissionState"},fn:"PermissionState"},{a:2,n:"PermissionType",t:16,rt:$n[0].Type,g:{a:2,n:"get_PermissionType",t:8,rt:$n[0].Type,fg:"PermissionType"},s:{a:2,n:"set_PermissionType",t:8,p:[$n[0].Type],rt:$n[0].Void,fs:"PermissionType"},fn:"PermissionType"},{a:2,n:"PermitOnlySetInstance",t:16,rt:$n[0].Object,g:{a:2,n:"get_PermitOnlySetInstance",t:8,rt:$n[0].Object,fg:"PermitOnlySetInstance"},s:{a:2,n:"set_PermitOnlySetInstance",t:8,p:[$n[0].Object],rt:$n[0].Void,fs:"PermitOnlySetInstance"},fn:"PermitOnlySetInstance"},{a:2,n:"RefusedSet",t:16,rt:$n[0].String,g:{a:2,n:"get_RefusedSet",t:8,rt:$n[0].String,fg:"RefusedSet"},s:{a:2,n:"set_RefusedSet",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"RefusedSet"},fn:"RefusedSet"},{a:2,n:"Url",t:16,rt:$n[0].String,g:{a:2,n:"get_Url",t:8,rt:$n[0].String,fg:"Url"},s:{a:2,n:"set_Url",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"Url"},fn:"Url"},{a:1,n:"DemandedName",is:!0,t:4,rt:$n[0].String,sn:"DemandedName"},{a:1,n:"DeniedName",is:!0,t:4,rt:$n[0].String,sn:"DeniedName"},{a:1,n:"GrantedSetName",is:!0,t:4,rt:$n[0].String,sn:"GrantedSetName"},{a:1,n:"PermitOnlyName",is:!0,t:4,rt:$n[0].String,sn:"PermitOnlyName"},{a:1,n:"RefusedSetName",is:!0,t:4,rt:$n[0].String,sn:"RefusedSetName"},{a:1,n:"UrlName",is:!0,t:4,rt:$n[0].String,sn:"UrlName"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Object,sn:"Demanded"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Object,sn:"DenySetInstance"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"GrantedSet"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[12].MethodInfo,sn:"Method"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"PermissionState"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Type,sn:"PermissionType"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Object,sn:"PermitOnlySetInstance"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"RefusedSet"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"Url"}]}},$n);$m("System.Runtime.Serialization.CollectionDataContractAttribute",function(){return{att:1048833,a:2,m:[{a:2,n:".ctor",t:1,sn:"ctor"},{a:2,n:"IsItemNameSetExplicitly",t:16,rt:$n[0].Boolean,g:{a:2,n:"get_IsItemNameSetExplicitly",t:8,rt:$n[0].Boolean,fg:"IsItemNameSetExplicitly",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},fn:"IsItemNameSetExplicitly"},{a:2,n:"IsKeyNameSetExplicitly",t:16,rt:$n[0].Boolean,g:{a:2,n:"get_IsKeyNameSetExplicitly",t:8,rt:$n[0].Boolean,fg:"IsKeyNameSetExplicitly",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},fn:"IsKeyNameSetExplicitly"},{a:2,n:"IsNameSetExplicitly",t:16,rt:$n[0].Boolean,g:{a:2,n:"get_IsNameSetExplicitly",t:8,rt:$n[0].Boolean,fg:"IsNameSetExplicitly",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},fn:"IsNameSetExplicitly"},{a:2,n:"IsNamespaceSetExplicitly",t:16,rt:$n[0].Boolean,g:{a:2,n:"get_IsNamespaceSetExplicitly",t:8,rt:$n[0].Boolean,fg:"IsNamespaceSetExplicitly",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},fn:"IsNamespaceSetExplicitly"},{a:2,n:"IsReference",t:16,rt:$n[0].Boolean,g:{a:2,n:"get_IsReference",t:8,rt:$n[0].Boolean,fg:"IsReference",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},s:{a:2,n:"set_IsReference",t:8,p:[$n[0].Boolean],rt:$n[0].Void,fs:"IsReference"},fn:"IsReference"},{a:2,n:"IsReferenceSetExplicitly",t:16,rt:$n[0].Boolean,g:{a:2,n:"get_IsReferenceSetExplicitly",t:8,rt:$n[0].Boolean,fg:"IsReferenceSetExplicitly",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},fn:"IsReferenceSetExplicitly"},{a:2,n:"IsValueNameSetExplicitly",t:16,rt:$n[0].Boolean,g:{a:2,n:"get_IsValueNameSetExplicitly",t:8,rt:$n[0].Boolean,fg:"IsValueNameSetExplicitly",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},fn:"IsValueNameSetExplicitly"},{a:2,n:"ItemName",t:16,rt:$n[0].String,g:{a:2,n:"get_ItemName",t:8,rt:$n[0].String,fg:"ItemName"},s:{a:2,n:"set_ItemName",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"ItemName"},fn:"ItemName"},{a:2,n:"KeyName",t:16,rt:$n[0].String,g:{a:2,n:"get_KeyName",t:8,rt:$n[0].String,fg:"KeyName"},s:{a:2,n:"set_KeyName",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"KeyName"},fn:"KeyName"},{a:2,n:"Name",t:16,rt:$n[0].String,g:{a:2,n:"get_Name",t:8,rt:$n[0].String,fg:"Name"},s:{a:2,n:"set_Name",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"Name"},fn:"Name"},{a:2,n:"Namespace",t:16,rt:$n[0].String,g:{a:2,n:"get_Namespace",t:8,rt:$n[0].String,fg:"Namespace"},s:{a:2,n:"set_Namespace",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"Namespace"},fn:"Namespace"},{a:2,n:"ValueName",t:16,rt:$n[0].String,g:{a:2,n:"get_ValueName",t:8,rt:$n[0].String,fg:"ValueName"},s:{a:2,n:"set_ValueName",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"ValueName"},fn:"ValueName"},{a:1,n:"_isItemNameSetExplicitly",t:4,rt:$n[0].Boolean,sn:"_isItemNameSetExplicitly",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"_isKeyNameSetExplicitly",t:4,rt:$n[0].Boolean,sn:"_isKeyNameSetExplicitly",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"_isNameSetExplicitly",t:4,rt:$n[0].Boolean,sn:"_isNameSetExplicitly",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"_isNamespaceSetExplicitly",t:4,rt:$n[0].Boolean,sn:"_isNamespaceSetExplicitly",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"_isReference",t:4,rt:$n[0].Boolean,sn:"_isReference",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"_isReferenceSetExplicitly",t:4,rt:$n[0].Boolean,sn:"_isReferenceSetExplicitly",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"_isValueNameSetExplicitly",t:4,rt:$n[0].Boolean,sn:"_isValueNameSetExplicitly",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"_itemName",t:4,rt:$n[0].String,sn:"_itemName"},{a:1,n:"_keyName",t:4,rt:$n[0].String,sn:"_keyName"},{a:1,n:"_name",t:4,rt:$n[0].String,sn:"_name"},{a:1,n:"_ns",t:4,rt:$n[0].String,sn:"_ns"},{a:1,n:"_valueName",t:4,rt:$n[0].String,sn:"_valueName"}],ni:!0}},$n);$m("System.Runtime.Serialization.ContractNamespaceAttribute",function(){return{att:1048833,a:2,m:[{a:2,n:".ctor",t:1,p:[$n[0].String],pi:[{n:"contractNamespace",pt:$n[0].String,ps:0}],sn:"ctor"},{a:2,n:"ClrNamespace",t:16,rt:$n[0].String,g:{a:2,n:"get_ClrNamespace",t:8,rt:$n[0].String,fg:"ClrNamespace"},s:{a:2,n:"set_ClrNamespace",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"ClrNamespace"},fn:"ClrNamespace"},{a:2,n:"ContractNamespace",t:16,rt:$n[0].String,g:{a:2,n:"get_ContractNamespace",t:8,rt:$n[0].String,fg:"ContractNamespace"},fn:"ContractNamespace"},{a:1,n:"_clrNamespace",t:4,rt:$n[0].String,sn:"_clrNamespace"},{a:1,n:"_contractNamespace",t:4,rt:$n[0].String,sn:"_contractNamespace"}],ni:!0,am:!0}},$n);$m("System.Runtime.Serialization.DataContractAttribute",function(){return{att:1048833,a:2,m:[{a:2,n:".ctor",t:1,sn:"ctor"},{a:2,n:"IsNameSetExplicitly",t:16,rt:$n[0].Boolean,g:{a:2,n:"get_IsNameSetExplicitly",t:8,rt:$n[0].Boolean,fg:"IsNameSetExplicitly",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},fn:"IsNameSetExplicitly"},{a:2,n:"IsNamespaceSetExplicitly",t:16,rt:$n[0].Boolean,g:{a:2,n:"get_IsNamespaceSetExplicitly",t:8,rt:$n[0].Boolean,fg:"IsNamespaceSetExplicitly",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},fn:"IsNamespaceSetExplicitly"},{a:2,n:"IsReference",t:16,rt:$n[0].Boolean,g:{a:2,n:"get_IsReference",t:8,rt:$n[0].Boolean,fg:"IsReference",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},s:{a:2,n:"set_IsReference",t:8,p:[$n[0].Boolean],rt:$n[0].Void,fs:"IsReference"},fn:"IsReference"},{a:2,n:"IsReferenceSetExplicitly",t:16,rt:$n[0].Boolean,g:{a:2,n:"get_IsReferenceSetExplicitly",t:8,rt:$n[0].Boolean,fg:"IsReferenceSetExplicitly",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},fn:"IsReferenceSetExplicitly"},{a:2,n:"Name",t:16,rt:$n[0].String,g:{a:2,n:"get_Name",t:8,rt:$n[0].String,fg:"Name"},s:{a:2,n:"set_Name",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"Name"},fn:"Name"},{a:2,n:"Namespace",t:16,rt:$n[0].String,g:{a:2,n:"get_Namespace",t:8,rt:$n[0].String,fg:"Namespace"},s:{a:2,n:"set_Namespace",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"Namespace"},fn:"Namespace"},{a:1,n:"_isNameSetExplicitly",t:4,rt:$n[0].Boolean,sn:"_isNameSetExplicitly",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"_isNamespaceSetExplicitly",t:4,rt:$n[0].Boolean,sn:"_isNamespaceSetExplicitly",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"_isReference",t:4,rt:$n[0].Boolean,sn:"_isReference",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"_isReferenceSetExplicitly",t:4,rt:$n[0].Boolean,sn:"_isReferenceSetExplicitly",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"_name",t:4,rt:$n[0].String,sn:"_name"},{a:1,n:"_ns",t:4,rt:$n[0].String,sn:"_ns"}],ni:!0}},$n);$m("System.Runtime.Serialization.DataMemberAttribute",function(){return{att:1048833,a:2,m:[{a:2,n:".ctor",t:1,sn:"ctor"},{a:2,n:"EmitDefaultValue",t:16,rt:$n[0].Boolean,g:{a:2,n:"get_EmitDefaultValue",t:8,rt:$n[0].Boolean,fg:"EmitDefaultValue",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},s:{a:2,n:"set_EmitDefaultValue",t:8,p:[$n[0].Boolean],rt:$n[0].Void,fs:"EmitDefaultValue"},fn:"EmitDefaultValue"},{a:2,n:"IsNameSetExplicitly",t:16,rt:$n[0].Boolean,g:{a:2,n:"get_IsNameSetExplicitly",t:8,rt:$n[0].Boolean,fg:"IsNameSetExplicitly",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},fn:"IsNameSetExplicitly"},{a:2,n:"IsRequired",t:16,rt:$n[0].Boolean,g:{a:2,n:"get_IsRequired",t:8,rt:$n[0].Boolean,fg:"IsRequired",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},s:{a:2,n:"set_IsRequired",t:8,p:[$n[0].Boolean],rt:$n[0].Void,fs:"IsRequired"},fn:"IsRequired"},{a:2,n:"Name",t:16,rt:$n[0].String,g:{a:2,n:"get_Name",t:8,rt:$n[0].String,fg:"Name"},s:{a:2,n:"set_Name",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"Name"},fn:"Name"},{a:2,n:"Order",t:16,rt:$n[0].Int32,g:{a:2,n:"get_Order",t:8,rt:$n[0].Int32,fg:"Order",box:function($v){return H5.box($v,System.Int32)}},s:{a:2,n:"set_Order",t:8,p:[$n[0].Int32],rt:$n[0].Void,fs:"Order"},fn:"Order"},{a:1,n:"_emitDefaultValue",t:4,rt:$n[0].Boolean,sn:"_emitDefaultValue",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"_isNameSetExplicitly",t:4,rt:$n[0].Boolean,sn:"_isNameSetExplicitly",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"_isRequired",t:4,rt:$n[0].Boolean,sn:"_isRequired",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"_name",t:4,rt:$n[0].String,sn:"_name"},{a:1,n:"_order",t:4,rt:$n[0].Int32,sn:"_order",box:function($v){return H5.box($v,System.Int32)}}],ni:!0}},$n);$m("System.Runtime.Serialization.EnumMemberAttribute",function(){return{att:1048833,a:2,m:[{a:2,n:".ctor",t:1,sn:"ctor"},{a:2,n:"IsValueSetExplicitly",t:16,rt:$n[0].Boolean,g:{a:2,n:"get_IsValueSetExplicitly",t:8,rt:$n[0].Boolean,fg:"IsValueSetExplicitly",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},fn:"IsValueSetExplicitly"},{a:2,n:"Value",t:16,rt:$n[0].String,g:{a:2,n:"get_Value",t:8,rt:$n[0].String,fg:"Value"},s:{a:2,n:"set_Value",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"Value"},fn:"Value"},{a:1,n:"_isValueSetExplicitly",t:4,rt:$n[0].Boolean,sn:"_isValueSetExplicitly",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"_value",t:4,rt:$n[0].String,sn:"_value"}],ni:!0}},$n);$m("System.Runtime.Serialization.IDeserializationCallback",function(){return{att:1048737,a:2,m:[{ab:!0,a:2,n:"OnDeserialization",t:8,pi:[{n:"sender",pt:$n[0].Object,ps:0}],sn:"System$Runtime$Serialization$IDeserializationCallback$OnDeserialization",rt:$n[0].Void,p:[$n[0].Object]}]}},$n);$m("System.Runtime.Serialization.IFormatterConverter",function(){return{att:1048737,a:2,m:[{ab:!0,a:2,n:"Convert",t:8,pi:[{n:"value",pt:$n[0].Object,ps:0},{n:"type",pt:$n[0].Type,ps:1}],sn:"System$Runtime$Serialization$IFormatterConverter$Convert",rt:$n[0].Object,p:[$n[0].Object,$n[0].Type]},{ab:!0,a:2,n:"Convert",t:8,pi:[{n:"value",pt:$n[0].Object,ps:0},{n:"typeCode",pt:$n[0].TypeCode,ps:1}],sn:"System$Runtime$Serialization$IFormatterConverter$Convert$1",rt:$n[0].Object,p:[$n[0].Object,$n[0].TypeCode]},{ab:!0,a:2,n:"ToBoolean",t:8,pi:[{n:"value",pt:$n[0].Object,ps:0}],sn:"System$Runtime$Serialization$IFormatterConverter$ToBoolean",rt:$n[0].Boolean,p:[$n[0].Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ab:!0,a:2,n:"ToByte",t:8,pi:[{n:"value",pt:$n[0].Object,ps:0}],sn:"System$Runtime$Serialization$IFormatterConverter$ToByte",rt:$n[0].Byte,p:[$n[0].Object],box:function($v){return H5.box($v,System.Byte)}},{ab:!0,a:2,n:"ToChar",t:8,pi:[{n:"value",pt:$n[0].Object,ps:0}],sn:"System$Runtime$Serialization$IFormatterConverter$ToChar",rt:$n[0].Char,p:[$n[0].Object],box:function($v){return H5.box($v,System.Char,String.fromCharCode,System.Char.getHashCode)}},{ab:!0,a:2,n:"ToDateTime",t:8,pi:[{n:"value",pt:$n[0].Object,ps:0}],sn:"System$Runtime$Serialization$IFormatterConverter$ToDateTime",rt:$n[0].DateTime,p:[$n[0].Object],box:function($v){return H5.box($v,System.DateTime,System.DateTime.format)}},{ab:!0,a:2,n:"ToDecimal",t:8,pi:[{n:"value",pt:$n[0].Object,ps:0}],sn:"System$Runtime$Serialization$IFormatterConverter$ToDecimal",rt:$n[0].Decimal,p:[$n[0].Object]},{ab:!0,a:2,n:"ToDouble",t:8,pi:[{n:"value",pt:$n[0].Object,ps:0}],sn:"System$Runtime$Serialization$IFormatterConverter$ToDouble",rt:$n[0].Double,p:[$n[0].Object],box:function($v){return H5.box($v,System.Double,System.Double.format,System.Double.getHashCode)}},{ab:!0,a:2,n:"ToInt16",t:8,pi:[{n:"value",pt:$n[0].Object,ps:0}],sn:"System$Runtime$Serialization$IFormatterConverter$ToInt16",rt:$n[0].Int16,p:[$n[0].Object],box:function($v){return H5.box($v,System.Int16)}},{ab:!0,a:2,n:"ToInt32",t:8,pi:[{n:"value",pt:$n[0].Object,ps:0}],sn:"System$Runtime$Serialization$IFormatterConverter$ToInt32",rt:$n[0].Int32,p:[$n[0].Object],box:function($v){return H5.box($v,System.Int32)}},{ab:!0,a:2,n:"ToInt64",t:8,pi:[{n:"value",pt:$n[0].Object,ps:0}],sn:"System$Runtime$Serialization$IFormatterConverter$ToInt64",rt:$n[0].Int64,p:[$n[0].Object]},{ab:!0,a:2,n:"ToSByte",t:8,pi:[{n:"value",pt:$n[0].Object,ps:0}],sn:"System$Runtime$Serialization$IFormatterConverter$ToSByte",rt:$n[0].SByte,p:[$n[0].Object],box:function($v){return H5.box($v,System.SByte)}},{ab:!0,a:2,n:"ToSingle",t:8,pi:[{n:"value",pt:$n[0].Object,ps:0}],sn:"System$Runtime$Serialization$IFormatterConverter$ToSingle",rt:$n[0].Single,p:[$n[0].Object],box:function($v){return H5.box($v,System.Single,System.Single.format,System.Single.getHashCode)}},{ab:!0,a:2,n:"ToString",t:8,pi:[{n:"value",pt:$n[0].Object,ps:0}],sn:"System$Runtime$Serialization$IFormatterConverter$ToString",rt:$n[0].String,p:[$n[0].Object]},{ab:!0,a:2,n:"ToUInt16",t:8,pi:[{n:"value",pt:$n[0].Object,ps:0}],sn:"System$Runtime$Serialization$IFormatterConverter$ToUInt16",rt:$n[0].UInt16,p:[$n[0].Object],box:function($v){return H5.box($v,System.UInt16)}},{ab:!0,a:2,n:"ToUInt32",t:8,pi:[{n:"value",pt:$n[0].Object,ps:0}],sn:"System$Runtime$Serialization$IFormatterConverter$ToUInt32",rt:$n[0].UInt32,p:[$n[0].Object],box:function($v){return H5.box($v,System.UInt32)}},{ab:!0,a:2,n:"ToUInt64",t:8,pi:[{n:"value",pt:$n[0].Object,ps:0}],sn:"System$Runtime$Serialization$IFormatterConverter$ToUInt64",rt:$n[0].UInt64,p:[$n[0].Object]}]}},$n);$m("System.Runtime.Serialization.IgnoreDataMemberAttribute",function(){return{att:1048833,a:2,m:[{a:2,n:".ctor",t:1,sn:"ctor"}],ni:!0}},$n);$m("System.Runtime.Serialization.InvalidDataContractException",function(){return{att:1056769,a:2,at:[new System.SerializableAttribute],m:[{a:2,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].String],pi:[{n:"message",pt:$n[0].String,ps:0}],sn:"$ctor1"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[0].Exception],pi:[{n:"message",pt:$n[0].String,ps:0},{n:"innerException",pt:$n[0].Exception,ps:1}],sn:"$ctor2"}]}},$n);$m("System.Runtime.Serialization.IObjectReference",function(){return{att:1048737,a:2,m:[{ab:!0,a:2,n:"GetRealObject",t:8,pi:[{n:"context",pt:$n[4].StreamingContext,ps:0}],sn:"System$Runtime$Serialization$IObjectReference$GetRealObject",rt:$n[0].Object,p:[$n[4].StreamingContext]}]}},$n);$m("System.Runtime.Serialization.ISafeSerializationData",function(){return{att:1048737,a:2,m:[{ab:!0,a:2,n:"CompleteDeserialization",t:8,pi:[{n:"deserialized",pt:$n[0].Object,ps:0}],sn:"System$Runtime$Serialization$ISafeSerializationData$CompleteDeserialization",rt:$n[0].Void,p:[$n[0].Object]}]}},$n);$m("System.Runtime.Serialization.ISerializable",function(){return{att:1048737,a:2}},$n);$m("System.Runtime.Serialization.ISerializationSurrogateProvider",function(){return{att:1048737,a:2,m:[{ab:!0,a:2,n:"GetDeserializedObject",t:8,pi:[{n:"obj",pt:$n[0].Object,ps:0},{n:"targetType",pt:$n[0].Type,ps:1}],sn:"System$Runtime$Serialization$ISerializationSurrogateProvider$GetDeserializedObject",rt:$n[0].Object,p:[$n[0].Object,$n[0].Type]},{ab:!0,a:2,n:"GetObjectToSerialize",t:8,pi:[{n:"obj",pt:$n[0].Object,ps:0},{n:"targetType",pt:$n[0].Type,ps:1}],sn:"System$Runtime$Serialization$ISerializationSurrogateProvider$GetObjectToSerialize",rt:$n[0].Object,p:[$n[0].Object,$n[0].Type]},{ab:!0,a:2,n:"GetSurrogateType",t:8,pi:[{n:"type",pt:$n[0].Type,ps:0}],sn:"System$Runtime$Serialization$ISerializationSurrogateProvider$GetSurrogateType",rt:$n[0].Type,p:[$n[0].Type]}]}},$n);$m("System.Runtime.Serialization.KnownTypeAttribute",function(){return{att:1048833,a:2,m:[{a:1,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].String],pi:[{n:"methodName",pt:$n[0].String,ps:0}],sn:"$ctor1"},{a:2,n:".ctor",t:1,p:[$n[0].Type],pi:[{n:"type",pt:$n[0].Type,ps:0}],sn:"$ctor2"},{a:2,n:"MethodName",t:16,rt:$n[0].String,g:{a:2,n:"get_MethodName",t:8,rt:$n[0].String,fg:"MethodName"},fn:"MethodName"},{a:2,n:"Type",t:16,rt:$n[0].Type,g:{a:2,n:"get_Type",t:8,rt:$n[0].Type,fg:"Type"},fn:"Type"},{a:1,n:"_methodName",t:4,rt:$n[0].String,sn:"_methodName"},{a:1,n:"_type",t:4,rt:$n[0].Type,sn:"_type"}],am:!0}},$n);$m("System.Runtime.Serialization.SerializationException",function(){return{att:1056769,a:2,at:[new System.SerializableAttribute],m:[{a:2,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].String],pi:[{n:"message",pt:$n[0].String,ps:0}],sn:"$ctor1"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[0].Exception],pi:[{n:"message",pt:$n[0].String,ps:0},{n:"innerException",pt:$n[0].Exception,ps:1}],sn:"$ctor2"},{a:1,n:"s_nullMessage",is:!0,t:4,rt:$n[0].String,sn:"s_nullMessage"}]}},$n);$m("System.Runtime.Serialization.SerializationEntry",function(){return{att:1048841,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:4,n:".ctor",t:1,p:[$n[0].String,$n[0].Object,$n[0].Type],pi:[{n:"entryName",pt:$n[0].String,ps:0},{n:"entryValue",pt:$n[0].Object,ps:1},{n:"entryType",pt:$n[0].Type,ps:2}],sn:"$ctor1"},{a:2,n:"Name",t:16,rt:$n[0].String,g:{a:2,n:"get_Name",t:8,rt:$n[0].String,fg:"Name"},fn:"Name"},{a:2,n:"ObjectType",t:16,rt:$n[0].Type,g:{a:2,n:"get_ObjectType",t:8,rt:$n[0].Type,fg:"ObjectType"},fn:"ObjectType"},{a:2,n:"Value",t:16,rt:$n[0].Object,g:{a:2,n:"get_Value",t:8,rt:$n[0].Object,fg:"Value"},fn:"Value"},{a:1,n:"_name",t:4,rt:$n[0].String,sn:"_name"},{a:1,n:"_type",t:4,rt:$n[0].Type,sn:"_type"},{a:1,n:"_value",t:4,rt:$n[0].Object,sn:"_value"}]}},$n);$m("System.Runtime.Serialization.SerializationInfoEnumerator",function(){return{att:1048833,a:2,m:[{a:4,n:".ctor",t:1,p:[$n[0].Array.type(System.String),$n[0].Array.type(System.Object),$n[0].Array.type(System.Type),$n[0].Int32],pi:[{n:"members",pt:$n[0].Array.type(System.String),ps:0},{n:"info",pt:$n[0].Array.type(System.Object),ps:1},{n:"types",pt:$n[0].Array.type(System.Type),ps:2},{n:"numItems",pt:$n[0].Int32,ps:3}],sn:"ctor"},{a:2,n:"MoveNext",t:8,sn:"moveNext",rt:$n[0].Boolean,box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Reset",t:8,sn:"reset",rt:$n[0].Void},{a:2,n:"Current",t:16,rt:$n[4].SerializationEntry,g:{a:2,n:"get_Current",t:8,rt:$n[4].SerializationEntry,fg:"Current"},fn:"Current"},{a:2,n:"Name",t:16,rt:$n[0].String,g:{a:2,n:"get_Name",t:8,rt:$n[0].String,fg:"Name"},fn:"Name"},{a:2,n:"ObjectType",t:16,rt:$n[0].Type,g:{a:2,n:"get_ObjectType",t:8,rt:$n[0].Type,fg:"ObjectType"},fn:"ObjectType"},{a:2,n:"Value",t:16,rt:$n[0].Object,g:{a:2,n:"get_Value",t:8,rt:$n[0].Object,fg:"Value"},fn:"Value"},{a:1,n:"_currItem",t:4,rt:$n[0].Int32,sn:"_currItem",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"_current",t:4,rt:$n[0].Boolean,sn:"_current",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"_data",t:4,rt:$n[0].Array.type(System.Object),sn:"_data",ro:!0},{a:1,n:"_members",t:4,rt:$n[0].Array.type(System.String),sn:"_members",ro:!0},{a:1,n:"_numItems",t:4,rt:$n[0].Int32,sn:"_numItems",ro:!0,box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"_types",t:4,rt:$n[0].Array.type(System.Type),sn:"_types",ro:!0}]}},$n);$m("System.Runtime.Serialization.StreamingContext",function(){return{att:1048841,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[4].StreamingContextStates],pi:[{n:"state",pt:$n[4].StreamingContextStates,ps:0}],sn:"$ctor1"},{a:2,n:".ctor",t:1,p:[$n[4].StreamingContextStates,$n[0].Object],pi:[{n:"state",pt:$n[4].StreamingContextStates,ps:0},{n:"additional",pt:$n[0].Object,ps:1}],sn:"$ctor2"},{ov:!0,a:2,n:"Equals",t:8,pi:[{n:"obj",pt:$n[0].Object,ps:0}],sn:"equals",rt:$n[0].Boolean,p:[$n[0].Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ov:!0,a:2,n:"GetHashCode",t:8,sn:"getHashCode",rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"Context",t:16,rt:$n[0].Object,g:{a:2,n:"get_Context",t:8,rt:$n[0].Object,fg:"Context"},fn:"Context"},{a:2,n:"State",t:16,rt:$n[4].StreamingContextStates,g:{a:2,n:"get_State",t:8,rt:$n[4].StreamingContextStates,fg:"State",box:function($v){return H5.box($v,System.Runtime.Serialization.StreamingContextStates,System.Enum.toStringFn(System.Runtime.Serialization.StreamingContextStates))}},fn:"State"},{a:1,n:"_additionalContext",t:4,rt:$n[0].Object,sn:"_additionalContext",ro:!0},{a:1,n:"_state",t:4,rt:$n[4].StreamingContextStates,sn:"_state",ro:!0,box:function($v){return H5.box($v,System.Runtime.Serialization.StreamingContextStates,System.Enum.toStringFn(System.Runtime.Serialization.StreamingContextStates))}}]}},$n);$m("System.Runtime.Serialization.StreamingContextStates",function(){return{att:257,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:"All",is:!0,t:4,rt:$n[4].StreamingContextStates,sn:"All",box:function($v){return H5.box($v,System.Runtime.Serialization.StreamingContextStates,System.Enum.toStringFn(System.Runtime.Serialization.StreamingContextStates))}},{a:2,n:"Clone",is:!0,t:4,rt:$n[4].StreamingContextStates,sn:"Clone",box:function($v){return H5.box($v,System.Runtime.Serialization.StreamingContextStates,System.Enum.toStringFn(System.Runtime.Serialization.StreamingContextStates))}},{a:2,n:"CrossAppDomain",is:!0,t:4,rt:$n[4].StreamingContextStates,sn:"CrossAppDomain",box:function($v){return H5.box($v,System.Runtime.Serialization.StreamingContextStates,System.Enum.toStringFn(System.Runtime.Serialization.StreamingContextStates))}},{a:2,n:"CrossMachine",is:!0,t:4,rt:$n[4].StreamingContextStates,sn:"CrossMachine",box:function($v){return H5.box($v,System.Runtime.Serialization.StreamingContextStates,System.Enum.toStringFn(System.Runtime.Serialization.StreamingContextStates))}},{a:2,n:"CrossProcess",is:!0,t:4,rt:$n[4].StreamingContextStates,sn:"CrossProcess",box:function($v){return H5.box($v,System.Runtime.Serialization.StreamingContextStates,System.Enum.toStringFn(System.Runtime.Serialization.StreamingContextStates))}},{a:2,n:"File",is:!0,t:4,rt:$n[4].StreamingContextStates,sn:"File",box:function($v){return H5.box($v,System.Runtime.Serialization.StreamingContextStates,System.Enum.toStringFn(System.Runtime.Serialization.StreamingContextStates))}},{a:2,n:"Other",is:!0,t:4,rt:$n[4].StreamingContextStates,sn:"Other",box:function($v){return H5.box($v,System.Runtime.Serialization.StreamingContextStates,System.Enum.toStringFn(System.Runtime.Serialization.StreamingContextStates))}},{a:2,n:"Persistence",is:!0,t:4,rt:$n[4].StreamingContextStates,sn:"Persistence",box:function($v){return H5.box($v,System.Runtime.Serialization.StreamingContextStates,System.Enum.toStringFn(System.Runtime.Serialization.StreamingContextStates))}},{a:2,n:"Remoting",is:!0,t:4,rt:$n[4].StreamingContextStates,sn:"Remoting",box:function($v){return H5.box($v,System.Runtime.Serialization.StreamingContextStates,System.Enum.toStringFn(System.Runtime.Serialization.StreamingContextStates))}}]}},$n);$m("System.Runtime.Serialization.OnDeserializedAttribute",function(){return{att:1048833,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"}],ni:!0}},$n);$m("System.Runtime.Serialization.OnDeserializingAttribute",function(){return{att:1048833,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"}],ni:!0}},$n);$m("System.Runtime.Serialization.OnSerializedAttribute",function(){return{att:1048833,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"}],ni:!0}},$n);$m("System.Runtime.Serialization.OnSerializingAttribute",function(){return{att:1048833,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"}],ni:!0}},$n);$m("System.Runtime.CompilerServices.FormattableStringFactory",function(){return{nested:[$n[13].FormattableStringFactory.ConcreteFormattableString],att:1048961,a:2,s:!0,m:[{a:2,n:"Create",is:!0,t:8,pi:[{n:"format",pt:$n[0].String,ps:0},{n:"arguments",ip:!0,pt:$n[0].Array.type(System.Object),ps:1}],sn:"Create",rt:$n[0].FormattableString,p:[$n[0].String,$n[0].Array.type(System.Object)]}]}},$n);$m("System.Runtime.CompilerServices.FormattableStringFactory.ConcreteFormattableString",function(){return{td:$n[13].FormattableStringFactory,att:1048835,a:1,m:[{a:4,n:".ctor",t:1,p:[$n[0].String,$n[0].Array.type(System.Object)],pi:[{n:"format",pt:$n[0].String,ps:0},{n:"arguments",pt:$n[0].Array.type(System.Object),ps:1}],sn:"ctor"},{ov:!0,a:2,n:"GetArgument",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0}],sn:"GetArgument",rt:$n[0].Object,p:[$n[0].Int32]},{ov:!0,a:2,n:"GetArguments",t:8,sn:"GetArguments",rt:$n[0].Array.type(System.Object)},{ov:!0,a:2,n:"ToString",t:8,pi:[{n:"formatProvider",pt:$n[0].IFormatProvider,ps:0}],sn:"ToString",rt:$n[0].String,p:[$n[0].IFormatProvider]},{ov:!0,a:2,n:"ArgumentCount",t:16,rt:$n[0].Int32,g:{ov:!0,a:2,n:"get_ArgumentCount",t:8,rt:$n[0].Int32,fg:"ArgumentCount",box:function($v){return H5.box($v,System.Int32)}},fn:"ArgumentCount"},{ov:!0,a:2,n:"Format",t:16,rt:$n[0].String,g:{ov:!0,a:2,n:"get_Format",t:8,rt:$n[0].String,fg:"Format"},fn:"Format"},{a:1,n:"_arguments",t:4,rt:$n[0].Array.type(System.Object),sn:"_arguments",ro:!0},{a:1,n:"_format",t:4,rt:$n[0].String,sn:"_format",ro:!0}]}},$n);$m("System.Runtime.CompilerServices.InlineArrayAttribute",function(){return{att:1048832,a:4,m:[{a:2,n:".ctor",t:1,p:[$n[0].Int32],pi:[{n:"length",pt:$n[0].Int32,ps:0}],sn:"ctor"},{a:2,n:"Length",t:16,rt:$n[0].Int32,g:{a:2,n:"get_Length",t:8,rt:$n[0].Int32,fg:"Length",box:function($v){return H5.box($v,System.Int32)}},fn:"Length"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Int32,sn:"Length",box:function($v){return H5.box($v,System.Int32)}}]}},$n);$m("System.Runtime.CompilerServices.CallerArgumentExpressionAttribute",function(){return{att:1048833,a:2,m:[{a:2,n:".ctor",t:1,p:[$n[0].String],pi:[{n:"parameterName",pt:$n[0].String,ps:0}],sn:"ctor"},{a:2,n:"ParameterName",t:16,rt:$n[0].String,g:{a:2,n:"get_ParameterName",t:8,rt:$n[0].String,fg:"ParameterName"},fn:"ParameterName"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"ParameterName"}],ni:!0}},$n);$m("System.Runtime.CompilerServices.ModuleInitializerAttribute",function(){return{att:1048833,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"}],ni:!0}},$n);$m("System.Resources.MissingManifestResourceException",function(){return{att:1056769,a:2,at:[new System.SerializableAttribute],m:[{a:2,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].String],pi:[{n:"message",pt:$n[0].String,ps:0}],sn:"$ctor1"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[0].Exception],pi:[{n:"message",pt:$n[0].String,ps:0},{n:"inner",pt:$n[0].Exception,ps:1}],sn:"$ctor2"}]}},$n);$m("System.Reflection.AmbiguousMatchException",function(){return{att:1057025,a:2,at:[new System.SerializableAttribute],m:[{a:2,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].String],pi:[{n:"message",pt:$n[0].String,ps:0}],sn:"$ctor1"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[0].Exception],pi:[{n:"message",pt:$n[0].String,ps:0},{n:"inner",pt:$n[0].Exception,ps:1}],sn:"$ctor2"}]}},$n);$m("System.Reflection.Binder",function(){return{att:1048705,a:2,m:[{a:3,n:".ctor",t:1,sn:"ctor"},{ab:!0,a:2,n:"BindToField",t:8,pi:[{n:"bindingAttr",pt:$n[12].BindingFlags,ps:0},{n:"match",pt:System.Array.type(System.Reflection.FieldInfo),ps:1},{n:"value",pt:$n[0].Object,ps:2},{n:"culture",pt:$n[1].CultureInfo,ps:3}],sn:"BindToField",rt:$n[12].FieldInfo,p:[$n[12].BindingFlags,System.Array.type(System.Reflection.FieldInfo),$n[0].Object,$n[1].CultureInfo]},{ab:!0,a:2,n:"BindToMethod",t:8,pi:[{n:"bindingAttr",pt:$n[12].BindingFlags,ps:0},{n:"match",pt:System.Array.type(System.Object),ps:1},{n:"args",ref:!0,pt:$n[0].Array.type(System.Object),ps:2},{n:"modifiers",pt:System.Array.type(System.Reflection.ParameterModifier),ps:3},{n:"culture",pt:$n[1].CultureInfo,ps:4},{n:"names",pt:$n[0].Array.type(System.String),ps:5},{n:"state",out:!0,pt:$n[0].Object,ps:6}],sn:"BindToMethod",rt:System.Object,p:[$n[12].BindingFlags,System.Array.type(System.Object),$n[0].Array.type(System.Object),System.Array.type(System.Reflection.ParameterModifier),$n[1].CultureInfo,$n[0].Array.type(System.String),$n[0].Object]},{ab:!0,a:2,n:"ChangeType",t:8,pi:[{n:"value",pt:$n[0].Object,ps:0},{n:"type",pt:$n[0].Type,ps:1},{n:"culture",pt:$n[1].CultureInfo,ps:2}],sn:"ChangeType",rt:$n[0].Object,p:[$n[0].Object,$n[0].Type,$n[1].CultureInfo]},{ab:!0,a:2,n:"ReorderArgumentArray",t:8,pi:[{n:"args",ref:!0,pt:$n[0].Array.type(System.Object),ps:0},{n:"state",pt:$n[0].Object,ps:1}],sn:"ReorderArgumentArray",rt:$n[0].Void,p:[$n[0].Array.type(System.Object),$n[0].Object]},{ab:!0,a:2,n:"SelectMethod",t:8,pi:[{n:"bindingAttr",pt:$n[12].BindingFlags,ps:0},{n:"match",pt:System.Array.type(System.Object),ps:1},{n:"types",pt:$n[0].Array.type(System.Type),ps:2},{n:"modifiers",pt:System.Array.type(System.Reflection.ParameterModifier),ps:3}],sn:"SelectMethod",rt:System.Object,p:[$n[12].BindingFlags,System.Array.type(System.Object),$n[0].Array.type(System.Type),System.Array.type(System.Reflection.ParameterModifier)]},{ab:!0,a:2,n:"SelectProperty",t:8,pi:[{n:"bindingAttr",pt:$n[12].BindingFlags,ps:0},{n:"match",pt:System.Array.type(System.Reflection.PropertyInfo),ps:1},{n:"returnType",pt:$n[0].Type,ps:2},{n:"indexes",pt:$n[0].Array.type(System.Type),ps:3},{n:"modifiers",pt:System.Array.type(System.Reflection.ParameterModifier),ps:4}],sn:"SelectProperty",rt:$n[12].PropertyInfo,p:[$n[12].BindingFlags,System.Array.type(System.Reflection.PropertyInfo),$n[0].Type,$n[0].Array.type(System.Type),System.Array.type(System.Reflection.ParameterModifier)]}]}},$n);$m("System.Reflection.BindingFlags",function(){return{att:257,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:"CreateInstance",is:!0,t:4,rt:$n[12].BindingFlags,sn:"CreateInstance",box:function($v){return H5.box($v,System.Reflection.BindingFlags,System.Enum.toStringFn(System.Reflection.BindingFlags))}},{a:2,n:"DeclaredOnly",is:!0,t:4,rt:$n[12].BindingFlags,sn:"DeclaredOnly",box:function($v){return H5.box($v,System.Reflection.BindingFlags,System.Enum.toStringFn(System.Reflection.BindingFlags))}},{a:2,n:"Default",is:!0,t:4,rt:$n[12].BindingFlags,sn:"Default",box:function($v){return H5.box($v,System.Reflection.BindingFlags,System.Enum.toStringFn(System.Reflection.BindingFlags))}},{a:2,n:"DoNotWrapExceptions",is:!0,t:4,rt:$n[12].BindingFlags,sn:"DoNotWrapExceptions",box:function($v){return H5.box($v,System.Reflection.BindingFlags,System.Enum.toStringFn(System.Reflection.BindingFlags))}},{a:2,n:"ExactBinding",is:!0,t:4,rt:$n[12].BindingFlags,sn:"ExactBinding",box:function($v){return H5.box($v,System.Reflection.BindingFlags,System.Enum.toStringFn(System.Reflection.BindingFlags))}},{a:2,n:"FlattenHierarchy",is:!0,t:4,rt:$n[12].BindingFlags,sn:"FlattenHierarchy",box:function($v){return H5.box($v,System.Reflection.BindingFlags,System.Enum.toStringFn(System.Reflection.BindingFlags))}},{a:2,n:"GetField",is:!0,t:4,rt:$n[12].BindingFlags,sn:"GetField",box:function($v){return H5.box($v,System.Reflection.BindingFlags,System.Enum.toStringFn(System.Reflection.BindingFlags))}},{a:2,n:"GetProperty",is:!0,t:4,rt:$n[12].BindingFlags,sn:"GetProperty",box:function($v){return H5.box($v,System.Reflection.BindingFlags,System.Enum.toStringFn(System.Reflection.BindingFlags))}},{a:2,n:"IgnoreCase",is:!0,t:4,rt:$n[12].BindingFlags,sn:"IgnoreCase",box:function($v){return H5.box($v,System.Reflection.BindingFlags,System.Enum.toStringFn(System.Reflection.BindingFlags))}},{a:2,n:"IgnoreReturn",is:!0,t:4,rt:$n[12].BindingFlags,sn:"IgnoreReturn",box:function($v){return H5.box($v,System.Reflection.BindingFlags,System.Enum.toStringFn(System.Reflection.BindingFlags))}},{a:2,n:"Instance",is:!0,t:4,rt:$n[12].BindingFlags,sn:"Instance",box:function($v){return H5.box($v,System.Reflection.BindingFlags,System.Enum.toStringFn(System.Reflection.BindingFlags))}},{a:2,n:"InvokeMethod",is:!0,t:4,rt:$n[12].BindingFlags,sn:"InvokeMethod",box:function($v){return H5.box($v,System.Reflection.BindingFlags,System.Enum.toStringFn(System.Reflection.BindingFlags))}},{a:2,n:"NonPublic",is:!0,t:4,rt:$n[12].BindingFlags,sn:"NonPublic",box:function($v){return H5.box($v,System.Reflection.BindingFlags,System.Enum.toStringFn(System.Reflection.BindingFlags))}},{a:2,n:"OptionalParamBinding",is:!0,t:4,rt:$n[12].BindingFlags,sn:"OptionalParamBinding",box:function($v){return H5.box($v,System.Reflection.BindingFlags,System.Enum.toStringFn(System.Reflection.BindingFlags))}},{a:2,n:"Public",is:!0,t:4,rt:$n[12].BindingFlags,sn:"Public",box:function($v){return H5.box($v,System.Reflection.BindingFlags,System.Enum.toStringFn(System.Reflection.BindingFlags))}},{a:2,n:"PutDispProperty",is:!0,t:4,rt:$n[12].BindingFlags,sn:"PutDispProperty",box:function($v){return H5.box($v,System.Reflection.BindingFlags,System.Enum.toStringFn(System.Reflection.BindingFlags))}},{a:2,n:"PutRefDispProperty",is:!0,t:4,rt:$n[12].BindingFlags,sn:"PutRefDispProperty",box:function($v){return H5.box($v,System.Reflection.BindingFlags,System.Enum.toStringFn(System.Reflection.BindingFlags))}},{a:2,n:"SetField",is:!0,t:4,rt:$n[12].BindingFlags,sn:"SetField",box:function($v){return H5.box($v,System.Reflection.BindingFlags,System.Enum.toStringFn(System.Reflection.BindingFlags))}},{a:2,n:"SetProperty",is:!0,t:4,rt:$n[12].BindingFlags,sn:"SetProperty",box:function($v){return H5.box($v,System.Reflection.BindingFlags,System.Enum.toStringFn(System.Reflection.BindingFlags))}},{a:2,n:"Static",is:!0,t:4,rt:$n[12].BindingFlags,sn:"Static",box:function($v){return H5.box($v,System.Reflection.BindingFlags,System.Enum.toStringFn(System.Reflection.BindingFlags))}},{a:2,n:"SuppressChangeType",is:!0,t:4,rt:$n[12].BindingFlags,sn:"SuppressChangeType",box:function($v){return H5.box($v,System.Reflection.BindingFlags,System.Enum.toStringFn(System.Reflection.BindingFlags))}}]}},$n);$m("System.Reflection.CallingConventions",function(){return{att:257,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:"Any",is:!0,t:4,rt:$n[12].CallingConventions,sn:"Any",box:function($v){return H5.box($v,System.Reflection.CallingConventions,System.Enum.toStringFn(System.Reflection.CallingConventions))}},{a:2,n:"ExplicitThis",is:!0,t:4,rt:$n[12].CallingConventions,sn:"ExplicitThis",box:function($v){return H5.box($v,System.Reflection.CallingConventions,System.Enum.toStringFn(System.Reflection.CallingConventions))}},{a:2,n:"HasThis",is:!0,t:4,rt:$n[12].CallingConventions,sn:"HasThis",box:function($v){return H5.box($v,System.Reflection.CallingConventions,System.Enum.toStringFn(System.Reflection.CallingConventions))}},{a:2,n:"Standard",is:!0,t:4,rt:$n[12].CallingConventions,sn:"Standard",box:function($v){return H5.box($v,System.Reflection.CallingConventions,System.Enum.toStringFn(System.Reflection.CallingConventions))}},{a:2,n:"VarArgs",is:!0,t:4,rt:$n[12].CallingConventions,sn:"VarArgs",box:function($v){return H5.box($v,System.Reflection.CallingConventions,System.Enum.toStringFn(System.Reflection.CallingConventions))}}]}},$n);$m("System.Reflection.ICustomAttributeProvider",function(){return{att:1048737,a:2,m:[{ab:!0,a:2,n:"GetCustomAttributes",t:8,pi:[{n:"inherit",pt:$n[0].Boolean,ps:0}],sn:"System$Reflection$ICustomAttributeProvider$GetCustomAttributes",rt:$n[0].Array.type(System.Object),p:[$n[0].Boolean]},{ab:!0,a:2,n:"GetCustomAttributes",t:8,pi:[{n:"attributeType",pt:$n[0].Type,ps:0},{n:"inherit",pt:$n[0].Boolean,ps:1}],sn:"System$Reflection$ICustomAttributeProvider$GetCustomAttributes$1",rt:$n[0].Array.type(System.Object),p:[$n[0].Type,$n[0].Boolean]},{ab:!0,a:2,n:"IsDefined",t:8,pi:[{n:"attributeType",pt:$n[0].Type,ps:0},{n:"inherit",pt:$n[0].Boolean,ps:1}],sn:"System$Reflection$ICustomAttributeProvider$IsDefined",rt:$n[0].Boolean,p:[$n[0].Type,$n[0].Boolean],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}}]}},$n);$m("System.Reflection.InvalidFilterCriteriaException",function(){return{att:1056769,a:2,at:[new System.SerializableAttribute],m:[{a:2,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].String],pi:[{n:"message",pt:$n[0].String,ps:0}],sn:"$ctor1"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[0].Exception],pi:[{n:"message",pt:$n[0].String,ps:0},{n:"inner",pt:$n[0].Exception,ps:1}],sn:"$ctor2"}]}},$n);$m("System.Reflection.IReflect",function(){return{att:1048737,a:2,m:[{ab:!0,a:2,n:"GetField",t:8,pi:[{n:"name",pt:$n[0].String,ps:0},{n:"bindingAttr",pt:$n[12].BindingFlags,ps:1}],sn:"System$Reflection$IReflect$GetField",rt:$n[12].FieldInfo,p:[$n[0].String,$n[12].BindingFlags]},{ab:!0,a:2,n:"GetFields",t:8,pi:[{n:"bindingAttr",pt:$n[12].BindingFlags,ps:0}],sn:"System$Reflection$IReflect$GetFields",rt:System.Array.type(System.Reflection.FieldInfo),p:[$n[12].BindingFlags]},{ab:!0,a:2,n:"GetMember",t:8,pi:[{n:"name",pt:$n[0].String,ps:0},{n:"bindingAttr",pt:$n[12].BindingFlags,ps:1}],sn:"System$Reflection$IReflect$GetMember",rt:System.Array.type(System.Object),p:[$n[0].String,$n[12].BindingFlags]},{ab:!0,a:2,n:"GetMembers",t:8,pi:[{n:"bindingAttr",pt:$n[12].BindingFlags,ps:0}],sn:"System$Reflection$IReflect$GetMembers",rt:System.Array.type(System.Object),p:[$n[12].BindingFlags]},{ab:!0,a:2,n:"GetMethod",t:8,pi:[{n:"name",pt:$n[0].String,ps:0},{n:"bindingAttr",pt:$n[12].BindingFlags,ps:1}],sn:"System$Reflection$IReflect$GetMethod",rt:$n[12].MethodInfo,p:[$n[0].String,$n[12].BindingFlags]},{ab:!0,a:2,n:"GetMethod",t:8,pi:[{n:"name",pt:$n[0].String,ps:0},{n:"bindingAttr",pt:$n[12].BindingFlags,ps:1},{n:"binder",pt:$n[12].Binder,ps:2},{n:"types",pt:$n[0].Array.type(System.Type),ps:3},{n:"modifiers",pt:System.Array.type(System.Reflection.ParameterModifier),ps:4}],sn:"System$Reflection$IReflect$GetMethod$1",rt:$n[12].MethodInfo,p:[$n[0].String,$n[12].BindingFlags,$n[12].Binder,$n[0].Array.type(System.Type),System.Array.type(System.Reflection.ParameterModifier)]},{ab:!0,a:2,n:"GetMethods",t:8,pi:[{n:"bindingAttr",pt:$n[12].BindingFlags,ps:0}],sn:"System$Reflection$IReflect$GetMethods",rt:System.Array.type(System.Reflection.MethodInfo),p:[$n[12].BindingFlags]},{ab:!0,a:2,n:"GetProperties",t:8,pi:[{n:"bindingAttr",pt:$n[12].BindingFlags,ps:0}],sn:"System$Reflection$IReflect$GetProperties",rt:System.Array.type(System.Reflection.PropertyInfo),p:[$n[12].BindingFlags]},{ab:!0,a:2,n:"GetProperty",t:8,pi:[{n:"name",pt:$n[0].String,ps:0},{n:"bindingAttr",pt:$n[12].BindingFlags,ps:1}],sn:"System$Reflection$IReflect$GetProperty",rt:$n[12].PropertyInfo,p:[$n[0].String,$n[12].BindingFlags]},{ab:!0,a:2,n:"GetProperty",t:8,pi:[{n:"name",pt:$n[0].String,ps:0},{n:"bindingAttr",pt:$n[12].BindingFlags,ps:1},{n:"binder",pt:$n[12].Binder,ps:2},{n:"returnType",pt:$n[0].Type,ps:3},{n:"types",pt:$n[0].Array.type(System.Type),ps:4},{n:"modifiers",pt:System.Array.type(System.Reflection.ParameterModifier),ps:5}],sn:"System$Reflection$IReflect$GetProperty$1",rt:$n[12].PropertyInfo,p:[$n[0].String,$n[12].BindingFlags,$n[12].Binder,$n[0].Type,$n[0].Array.type(System.Type),System.Array.type(System.Reflection.ParameterModifier)]},{ab:!0,a:2,n:"InvokeMember",t:8,pi:[{n:"name",pt:$n[0].String,ps:0},{n:"invokeAttr",pt:$n[12].BindingFlags,ps:1},{n:"binder",pt:$n[12].Binder,ps:2},{n:"target",pt:$n[0].Object,ps:3},{n:"args",pt:$n[0].Array.type(System.Object),ps:4},{n:"modifiers",pt:System.Array.type(System.Reflection.ParameterModifier),ps:5},{n:"culture",pt:$n[1].CultureInfo,ps:6},{n:"namedParameters",pt:$n[0].Array.type(System.String),ps:7}],sn:"System$Reflection$IReflect$InvokeMember",rt:$n[0].Object,p:[$n[0].String,$n[12].BindingFlags,$n[12].Binder,$n[0].Object,$n[0].Array.type(System.Object),System.Array.type(System.Reflection.ParameterModifier),$n[1].CultureInfo,$n[0].Array.type(System.String)]},{ab:!0,a:2,n:"UnderlyingSystemType",t:16,rt:$n[0].Type,g:{ab:!0,a:2,n:"get_UnderlyingSystemType",t:8,rt:$n[0].Type,fg:"System$Reflection$IReflect$UnderlyingSystemType"},fn:"System$Reflection$IReflect$UnderlyingSystemType"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Type,sn:"System$Reflection$IReflect$UnderlyingSystemType"}]}},$n);$m("System.Reflection.MemberTypes",function(){return{att:257,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:"All",is:!0,t:4,rt:$n[12].MemberTypes,sn:"All",box:function($v){return H5.box($v,System.Reflection.MemberTypes,System.Enum.toStringFn(System.Reflection.MemberTypes))}},{a:2,n:"Constructor",is:!0,t:4,rt:$n[12].MemberTypes,sn:"Constructor",box:function($v){return H5.box($v,System.Reflection.MemberTypes,System.Enum.toStringFn(System.Reflection.MemberTypes))}},{a:2,n:"Custom",is:!0,t:4,rt:$n[12].MemberTypes,sn:"Custom",box:function($v){return H5.box($v,System.Reflection.MemberTypes,System.Enum.toStringFn(System.Reflection.MemberTypes))}},{a:2,n:"Event",is:!0,t:4,rt:$n[12].MemberTypes,sn:"Event",box:function($v){return H5.box($v,System.Reflection.MemberTypes,System.Enum.toStringFn(System.Reflection.MemberTypes))}},{a:2,n:"Field",is:!0,t:4,rt:$n[12].MemberTypes,sn:"Field",box:function($v){return H5.box($v,System.Reflection.MemberTypes,System.Enum.toStringFn(System.Reflection.MemberTypes))}},{a:2,n:"Method",is:!0,t:4,rt:$n[12].MemberTypes,sn:"Method",box:function($v){return H5.box($v,System.Reflection.MemberTypes,System.Enum.toStringFn(System.Reflection.MemberTypes))}},{a:2,n:"NestedType",is:!0,t:4,rt:$n[12].MemberTypes,sn:"NestedType",box:function($v){return H5.box($v,System.Reflection.MemberTypes,System.Enum.toStringFn(System.Reflection.MemberTypes))}},{a:2,n:"Property",is:!0,t:4,rt:$n[12].MemberTypes,sn:"Property",box:function($v){return H5.box($v,System.Reflection.MemberTypes,System.Enum.toStringFn(System.Reflection.MemberTypes))}},{a:2,n:"TypeInfo",is:!0,t:4,rt:$n[12].MemberTypes,sn:"TypeInfo",box:function($v){return H5.box($v,System.Reflection.MemberTypes,System.Enum.toStringFn(System.Reflection.MemberTypes))}}]}},$n);$m("System.Reflection.Module",function(){return{att:1048705,a:2,m:[{a:3,n:".ctor",t:1,sn:"ctor"},{ov:!0,a:2,n:"Equals",t:8,pi:[{n:"o",pt:$n[0].Object,ps:0}],sn:"equals",rt:$n[0].Boolean,p:[$n[0].Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"FilterTypeNameIgnoreCaseImpl",is:!0,t:8,pi:[{n:"cls",pt:$n[0].Type,ps:0},{n:"filterCriteria",pt:$n[0].Object,ps:1}],sn:"FilterTypeNameIgnoreCaseImpl",rt:$n[0].Boolean,p:[$n[0].Type,$n[0].Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"FilterTypeNameImpl",is:!0,t:8,pi:[{n:"cls",pt:$n[0].Type,ps:0},{n:"filterCriteria",pt:$n[0].Object,ps:1}],sn:"FilterTypeNameImpl",rt:$n[0].Boolean,p:[$n[0].Type,$n[0].Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{v:!0,a:2,n:"FindTypes",t:8,pi:[{n:"filter",pt:Function,ps:0},{n:"filterCriteria",pt:$n[0].Object,ps:1}],sn:"FindTypes",rt:$n[0].Array.type(System.Type),p:[Function,$n[0].Object]},{v:!0,a:2,n:"GetCustomAttributes",t:8,pi:[{n:"inherit",pt:$n[0].Boolean,ps:0}],sn:"GetCustomAttributes",rt:$n[0].Array.type(System.Object),p:[$n[0].Boolean]},{v:!0,a:2,n:"GetCustomAttributes",t:8,pi:[{n:"attributeType",pt:$n[0].Type,ps:0},{n:"inherit",pt:$n[0].Boolean,ps:1}],sn:"GetCustomAttributes$1",rt:$n[0].Array.type(System.Object),p:[$n[0].Type,$n[0].Boolean]},{a:2,n:"GetField",t:8,pi:[{n:"name",pt:$n[0].String,ps:0}],sn:"GetField",rt:$n[12].FieldInfo,p:[$n[0].String]},{v:!0,a:2,n:"GetField",t:8,pi:[{n:"name",pt:$n[0].String,ps:0},{n:"bindingAttr",pt:$n[12].BindingFlags,ps:1}],sn:"GetField$1",rt:$n[12].FieldInfo,p:[$n[0].String,$n[12].BindingFlags]},{a:2,n:"GetFields",t:8,sn:"GetFields",rt:System.Array.type(System.Reflection.FieldInfo)},{v:!0,a:2,n:"GetFields",t:8,pi:[{n:"bindingFlags",pt:$n[12].BindingFlags,ps:0}],sn:"GetFields$1",rt:System.Array.type(System.Reflection.FieldInfo),p:[$n[12].BindingFlags]},{ov:!0,a:2,n:"GetHashCode",t:8,sn:"getHashCode",rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"GetMethod",t:8,pi:[{n:"name",pt:$n[0].String,ps:0}],sn:"GetMethod",rt:$n[12].MethodInfo,p:[$n[0].String]},{a:2,n:"GetMethod",t:8,pi:[{n:"name",pt:$n[0].String,ps:0},{n:"types",pt:$n[0].Array.type(System.Type),ps:1}],sn:"GetMethod$2",rt:$n[12].MethodInfo,p:[$n[0].String,$n[0].Array.type(System.Type)]},{a:2,n:"GetMethod",t:8,pi:[{n:"name",pt:$n[0].String,ps:0},{n:"bindingAttr",pt:$n[12].BindingFlags,ps:1},{n:"binder",pt:$n[12].Binder,ps:2},{n:"callConvention",pt:$n[12].CallingConventions,ps:3},{n:"types",pt:$n[0].Array.type(System.Type),ps:4},{n:"modifiers",pt:System.Array.type(System.Reflection.ParameterModifier),ps:5}],sn:"GetMethod$1",rt:$n[12].MethodInfo,p:[$n[0].String,$n[12].BindingFlags,$n[12].Binder,$n[12].CallingConventions,$n[0].Array.type(System.Type),System.Array.type(System.Reflection.ParameterModifier)]},{v:!0,a:3,n:"GetMethodImpl",t:8,pi:[{n:"name",pt:$n[0].String,ps:0},{n:"bindingAttr",pt:$n[12].BindingFlags,ps:1},{n:"binder",pt:$n[12].Binder,ps:2},{n:"callConvention",pt:$n[12].CallingConventions,ps:3},{n:"types",pt:$n[0].Array.type(System.Type),ps:4},{n:"modifiers",pt:System.Array.type(System.Reflection.ParameterModifier),ps:5}],sn:"GetMethodImpl",rt:$n[12].MethodInfo,p:[$n[0].String,$n[12].BindingFlags,$n[12].Binder,$n[12].CallingConventions,$n[0].Array.type(System.Type),System.Array.type(System.Reflection.ParameterModifier)]},{a:2,n:"GetMethods",t:8,sn:"GetMethods",rt:System.Array.type(System.Reflection.MethodInfo)},{v:!0,a:2,n:"GetMethods",t:8,pi:[{n:"bindingFlags",pt:$n[12].BindingFlags,ps:0}],sn:"GetMethods$1",rt:System.Array.type(System.Reflection.MethodInfo),p:[$n[12].BindingFlags]},{v:!0,a:2,n:"GetType",t:8,pi:[{n:"className",pt:$n[0].String,ps:0}],sn:"GetType",rt:$n[0].Type,p:[$n[0].String]},{v:!0,a:2,n:"GetType",t:8,pi:[{n:"className",pt:$n[0].String,ps:0},{n:"ignoreCase",pt:$n[0].Boolean,ps:1}],sn:"GetType$1",rt:$n[0].Type,p:[$n[0].String,$n[0].Boolean]},{v:!0,a:2,n:"GetType",t:8,pi:[{n:"className",pt:$n[0].String,ps:0},{n:"throwOnError",pt:$n[0].Boolean,ps:1},{n:"ignoreCase",pt:$n[0].Boolean,ps:2}],sn:"GetType$2",rt:$n[0].Type,p:[$n[0].String,$n[0].Boolean,$n[0].Boolean]},{v:!0,a:2,n:"GetTypes",t:8,sn:"GetTypes",rt:$n[0].Array.type(System.Type)},{v:!0,a:2,n:"IsDefined",t:8,pi:[{n:"attributeType",pt:$n[0].Type,ps:0},{n:"inherit",pt:$n[0].Boolean,ps:1}],sn:"IsDefined",rt:$n[0].Boolean,p:[$n[0].Type,$n[0].Boolean],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{v:!0,a:2,n:"IsResource",t:8,sn:"IsResource",rt:$n[0].Boolean,box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"ResolveField",t:8,pi:[{n:"metadataToken",pt:$n[0].Int32,ps:0}],sn:"ResolveField",rt:$n[12].FieldInfo,p:[$n[0].Int32]},{v:!0,a:2,n:"ResolveField",t:8,pi:[{n:"metadataToken",pt:$n[0].Int32,ps:0},{n:"genericTypeArguments",pt:$n[0].Array.type(System.Type),ps:1},{n:"genericMethodArguments",pt:$n[0].Array.type(System.Type),ps:2}],sn:"ResolveField$1",rt:$n[12].FieldInfo,p:[$n[0].Int32,$n[0].Array.type(System.Type),$n[0].Array.type(System.Type)]},{a:2,n:"ResolveMember",t:8,pi:[{n:"metadataToken",pt:$n[0].Int32,ps:0}],sn:"ResolveMember",rt:System.Object,p:[$n[0].Int32]},{v:!0,a:2,n:"ResolveMember",t:8,pi:[{n:"metadataToken",pt:$n[0].Int32,ps:0},{n:"genericTypeArguments",pt:$n[0].Array.type(System.Type),ps:1},{n:"genericMethodArguments",pt:$n[0].Array.type(System.Type),ps:2}],sn:"ResolveMember$1",rt:System.Object,p:[$n[0].Int32,$n[0].Array.type(System.Type),$n[0].Array.type(System.Type)]},{a:2,n:"ResolveMethod",t:8,pi:[{n:"metadataToken",pt:$n[0].Int32,ps:0}],sn:"ResolveMethod",rt:System.Object,p:[$n[0].Int32]},{v:!0,a:2,n:"ResolveMethod",t:8,pi:[{n:"metadataToken",pt:$n[0].Int32,ps:0},{n:"genericTypeArguments",pt:$n[0].Array.type(System.Type),ps:1},{n:"genericMethodArguments",pt:$n[0].Array.type(System.Type),ps:2}],sn:"ResolveMethod$1",rt:System.Object,p:[$n[0].Int32,$n[0].Array.type(System.Type),$n[0].Array.type(System.Type)]},{v:!0,a:2,n:"ResolveSignature",t:8,pi:[{n:"metadataToken",pt:$n[0].Int32,ps:0}],sn:"ResolveSignature",rt:$n[0].Array.type(System.Byte),p:[$n[0].Int32]},{v:!0,a:2,n:"ResolveString",t:8,pi:[{n:"metadataToken",pt:$n[0].Int32,ps:0}],sn:"ResolveString",rt:$n[0].String,p:[$n[0].Int32]},{a:2,n:"ResolveType",t:8,pi:[{n:"metadataToken",pt:$n[0].Int32,ps:0}],sn:"ResolveType",rt:$n[0].Type,p:[$n[0].Int32]},{v:!0,a:2,n:"ResolveType",t:8,pi:[{n:"metadataToken",pt:$n[0].Int32,ps:0},{n:"genericTypeArguments",pt:$n[0].Array.type(System.Type),ps:1},{n:"genericMethodArguments",pt:$n[0].Array.type(System.Type),ps:2}],sn:"ResolveType$1",rt:$n[0].Type,p:[$n[0].Int32,$n[0].Array.type(System.Type),$n[0].Array.type(System.Type)]},{ov:!0,a:2,n:"ToString",t:8,sn:"toString",rt:$n[0].String},{a:2,n:"op_Equality",is:!0,t:8,pi:[{n:"left",pt:$n[12].Module,ps:0},{n:"right",pt:$n[12].Module,ps:1}],sn:"op_Equality",rt:$n[0].Boolean,p:[$n[12].Module,$n[12].Module],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"op_Inequality",is:!0,t:8,pi:[{n:"left",pt:$n[12].Module,ps:0},{n:"right",pt:$n[12].Module,ps:1}],sn:"op_Inequality",rt:$n[0].Boolean,p:[$n[12].Module,$n[12].Module],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{v:!0,a:2,n:"Assembly",t:16,rt:$n[12].Assembly,g:{v:!0,a:2,n:"get_Assembly",t:8,rt:$n[12].Assembly,fg:"Assembly"},fn:"Assembly"},{v:!0,a:2,n:"FullyQualifiedName",t:16,rt:$n[0].String,g:{v:!0,a:2,n:"get_FullyQualifiedName",t:8,rt:$n[0].String,fg:"FullyQualifiedName"},fn:"FullyQualifiedName"},{v:!0,a:2,n:"MDStreamVersion",t:16,rt:$n[0].Int32,g:{v:!0,a:2,n:"get_MDStreamVersion",t:8,rt:$n[0].Int32,fg:"MDStreamVersion",box:function($v){return H5.box($v,System.Int32)}},fn:"MDStreamVersion"},{v:!0,a:2,n:"MetadataToken",t:16,rt:$n[0].Int32,g:{v:!0,a:2,n:"get_MetadataToken",t:8,rt:$n[0].Int32,fg:"MetadataToken",box:function($v){return H5.box($v,System.Int32)}},fn:"MetadataToken"},{v:!0,a:2,n:"ModuleVersionId",t:16,rt:$n[0].Guid,g:{v:!0,a:2,n:"get_ModuleVersionId",t:8,rt:$n[0].Guid,fg:"ModuleVersionId"},fn:"ModuleVersionId"},{v:!0,a:2,n:"Name",t:16,rt:$n[0].String,g:{v:!0,a:2,n:"get_Name",t:8,rt:$n[0].String,fg:"Name"},fn:"Name"},{v:!0,a:2,n:"ScopeName",t:16,rt:$n[0].String,g:{v:!0,a:2,n:"get_ScopeName",t:8,rt:$n[0].String,fg:"ScopeName"},fn:"ScopeName"},{a:1,n:"DefaultLookup",is:!0,t:4,rt:$n[12].BindingFlags,sn:"DefaultLookup",box:function($v){return H5.box($v,System.Reflection.BindingFlags,System.Enum.toStringFn(System.Reflection.BindingFlags))}},{a:2,n:"FilterTypeName",is:!0,t:4,rt:Function,sn:"FilterTypeName",ro:!0},{a:2,n:"FilterTypeNameIgnoreCase",is:!0,t:4,rt:Function,sn:"FilterTypeNameIgnoreCase",ro:!0}]}},$n);$m("System.Reflection.ParameterModifier",function(){return{att:1048841,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].Int32],pi:[{n:"parameterCount",pt:$n[0].Int32,ps:0}],sn:"$ctor1"},{a:2,n:"Item",t:16,rt:$n[0].Boolean,p:[$n[0].Int32],i:!0,ipi:[{n:"index",pt:$n[0].Int32,ps:0}],g:{a:2,n:"get_Item",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0}],sn:"getItem",rt:$n[0].Boolean,p:[$n[0].Int32],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},s:{a:2,n:"set_Item",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0},{n:"value",pt:$n[0].Boolean,ps:1}],sn:"setItem",rt:$n[0].Void,p:[$n[0].Int32,$n[0].Boolean]}},{a:1,n:"_byRef",t:4,rt:$n[0].Array.type(System.Boolean),sn:"_byRef",ro:!0}]}},$n);$m("System.Reflection.TypeAttributes",function(){return{att:257,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:"Abstract",is:!0,t:4,rt:$n[12].TypeAttributes,sn:"Abstract",box:function($v){return H5.box($v,System.Reflection.TypeAttributes,System.Enum.toStringFn(System.Reflection.TypeAttributes))}},{a:2,n:"AnsiClass",is:!0,t:4,rt:$n[12].TypeAttributes,sn:"AnsiClass",box:function($v){return H5.box($v,System.Reflection.TypeAttributes,System.Enum.toStringFn(System.Reflection.TypeAttributes))}},{a:2,n:"AutoClass",is:!0,t:4,rt:$n[12].TypeAttributes,sn:"AutoClass",box:function($v){return H5.box($v,System.Reflection.TypeAttributes,System.Enum.toStringFn(System.Reflection.TypeAttributes))}},{a:2,n:"AutoLayout",is:!0,t:4,rt:$n[12].TypeAttributes,sn:"AutoLayout",box:function($v){return H5.box($v,System.Reflection.TypeAttributes,System.Enum.toStringFn(System.Reflection.TypeAttributes))}},{a:2,n:"BeforeFieldInit",is:!0,t:4,rt:$n[12].TypeAttributes,sn:"BeforeFieldInit",box:function($v){return H5.box($v,System.Reflection.TypeAttributes,System.Enum.toStringFn(System.Reflection.TypeAttributes))}},{a:2,n:"Class",is:!0,t:4,rt:$n[12].TypeAttributes,sn:"Class",box:function($v){return H5.box($v,System.Reflection.TypeAttributes,System.Enum.toStringFn(System.Reflection.TypeAttributes))}},{a:2,n:"ClassSemanticsMask",is:!0,t:4,rt:$n[12].TypeAttributes,sn:"ClassSemanticsMask",box:function($v){return H5.box($v,System.Reflection.TypeAttributes,System.Enum.toStringFn(System.Reflection.TypeAttributes))}},{a:2,n:"CustomFormatClass",is:!0,t:4,rt:$n[12].TypeAttributes,sn:"CustomFormatClass",box:function($v){return H5.box($v,System.Reflection.TypeAttributes,System.Enum.toStringFn(System.Reflection.TypeAttributes))}},{a:2,n:"CustomFormatMask",is:!0,t:4,rt:$n[12].TypeAttributes,sn:"CustomFormatMask",box:function($v){return H5.box($v,System.Reflection.TypeAttributes,System.Enum.toStringFn(System.Reflection.TypeAttributes))}},{a:2,n:"ExplicitLayout",is:!0,t:4,rt:$n[12].TypeAttributes,sn:"ExplicitLayout",box:function($v){return H5.box($v,System.Reflection.TypeAttributes,System.Enum.toStringFn(System.Reflection.TypeAttributes))}},{a:2,n:"HasSecurity",is:!0,t:4,rt:$n[12].TypeAttributes,sn:"HasSecurity",box:function($v){return H5.box($v,System.Reflection.TypeAttributes,System.Enum.toStringFn(System.Reflection.TypeAttributes))}},{a:2,n:"Import",is:!0,t:4,rt:$n[12].TypeAttributes,sn:"Import",box:function($v){return H5.box($v,System.Reflection.TypeAttributes,System.Enum.toStringFn(System.Reflection.TypeAttributes))}},{a:2,n:"Interface",is:!0,t:4,rt:$n[12].TypeAttributes,sn:"Interface",box:function($v){return H5.box($v,System.Reflection.TypeAttributes,System.Enum.toStringFn(System.Reflection.TypeAttributes))}},{a:2,n:"LayoutMask",is:!0,t:4,rt:$n[12].TypeAttributes,sn:"LayoutMask",box:function($v){return H5.box($v,System.Reflection.TypeAttributes,System.Enum.toStringFn(System.Reflection.TypeAttributes))}},{a:2,n:"NestedAssembly",is:!0,t:4,rt:$n[12].TypeAttributes,sn:"NestedAssembly",box:function($v){return H5.box($v,System.Reflection.TypeAttributes,System.Enum.toStringFn(System.Reflection.TypeAttributes))}},{a:2,n:"NestedFamANDAssem",is:!0,t:4,rt:$n[12].TypeAttributes,sn:"NestedFamANDAssem",box:function($v){return H5.box($v,System.Reflection.TypeAttributes,System.Enum.toStringFn(System.Reflection.TypeAttributes))}},{a:2,n:"NestedFamORAssem",is:!0,t:4,rt:$n[12].TypeAttributes,sn:"NestedFamORAssem",box:function($v){return H5.box($v,System.Reflection.TypeAttributes,System.Enum.toStringFn(System.Reflection.TypeAttributes))}},{a:2,n:"NestedFamily",is:!0,t:4,rt:$n[12].TypeAttributes,sn:"NestedFamily",box:function($v){return H5.box($v,System.Reflection.TypeAttributes,System.Enum.toStringFn(System.Reflection.TypeAttributes))}},{a:2,n:"NestedPrivate",is:!0,t:4,rt:$n[12].TypeAttributes,sn:"NestedPrivate",box:function($v){return H5.box($v,System.Reflection.TypeAttributes,System.Enum.toStringFn(System.Reflection.TypeAttributes))}},{a:2,n:"NestedPublic",is:!0,t:4,rt:$n[12].TypeAttributes,sn:"NestedPublic",box:function($v){return H5.box($v,System.Reflection.TypeAttributes,System.Enum.toStringFn(System.Reflection.TypeAttributes))}},{a:2,n:"NotPublic",is:!0,t:4,rt:$n[12].TypeAttributes,sn:"NotPublic",box:function($v){return H5.box($v,System.Reflection.TypeAttributes,System.Enum.toStringFn(System.Reflection.TypeAttributes))}},{a:2,n:"Public",is:!0,t:4,rt:$n[12].TypeAttributes,sn:"Public",box:function($v){return H5.box($v,System.Reflection.TypeAttributes,System.Enum.toStringFn(System.Reflection.TypeAttributes))}},{a:2,n:"RTSpecialName",is:!0,t:4,rt:$n[12].TypeAttributes,sn:"RTSpecialName",box:function($v){return H5.box($v,System.Reflection.TypeAttributes,System.Enum.toStringFn(System.Reflection.TypeAttributes))}},{a:2,n:"ReservedMask",is:!0,t:4,rt:$n[12].TypeAttributes,sn:"ReservedMask",box:function($v){return H5.box($v,System.Reflection.TypeAttributes,System.Enum.toStringFn(System.Reflection.TypeAttributes))}},{a:2,n:"Sealed",is:!0,t:4,rt:$n[12].TypeAttributes,sn:"Sealed",box:function($v){return H5.box($v,System.Reflection.TypeAttributes,System.Enum.toStringFn(System.Reflection.TypeAttributes))}},{a:2,n:"SequentialLayout",is:!0,t:4,rt:$n[12].TypeAttributes,sn:"SequentialLayout",box:function($v){return H5.box($v,System.Reflection.TypeAttributes,System.Enum.toStringFn(System.Reflection.TypeAttributes))}},{a:2,n:"Serializable",is:!0,t:4,rt:$n[12].TypeAttributes,sn:"Serializable",box:function($v){return H5.box($v,System.Reflection.TypeAttributes,System.Enum.toStringFn(System.Reflection.TypeAttributes))}},{a:2,n:"SpecialName",is:!0,t:4,rt:$n[12].TypeAttributes,sn:"SpecialName",box:function($v){return H5.box($v,System.Reflection.TypeAttributes,System.Enum.toStringFn(System.Reflection.TypeAttributes))}},{a:2,n:"StringFormatMask",is:!0,t:4,rt:$n[12].TypeAttributes,sn:"StringFormatMask",box:function($v){return H5.box($v,System.Reflection.TypeAttributes,System.Enum.toStringFn(System.Reflection.TypeAttributes))}},{a:2,n:"UnicodeClass",is:!0,t:4,rt:$n[12].TypeAttributes,sn:"UnicodeClass",box:function($v){return H5.box($v,System.Reflection.TypeAttributes,System.Enum.toStringFn(System.Reflection.TypeAttributes))}},{a:2,n:"VisibilityMask",is:!0,t:4,rt:$n[12].TypeAttributes,sn:"VisibilityMask",box:function($v){return H5.box($v,System.Reflection.TypeAttributes,System.Enum.toStringFn(System.Reflection.TypeAttributes))}},{a:2,n:"WindowsRuntime",is:!0,t:4,rt:$n[12].TypeAttributes,sn:"WindowsRuntime",box:function($v){return H5.box($v,System.Reflection.TypeAttributes,System.Enum.toStringFn(System.Reflection.TypeAttributes))}}]}},$n);$m("System.IO.BinaryReader",function(){return{att:1048577,a:2,m:[{a:2,n:".ctor",t:1,p:[$n[14].Stream],pi:[{n:"input",pt:$n[14].Stream,ps:0}],sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[14].Stream,$n[8].Encoding],pi:[{n:"input",pt:$n[14].Stream,ps:0},{n:"encoding",pt:$n[8].Encoding,ps:1}],sn:"$ctor1"},{a:2,n:".ctor",t:1,p:[$n[14].Stream,$n[8].Encoding,$n[0].Boolean],pi:[{n:"input",pt:$n[14].Stream,ps:0},{n:"encoding",pt:$n[8].Encoding,ps:1},{n:"leaveOpen",pt:$n[0].Boolean,ps:2}],sn:"$ctor2"},{v:!0,a:2,n:"Close",t:8,sn:"Close",rt:$n[0].Void},{a:2,n:"Dispose",t:8,sn:"Dispose",rt:$n[0].Void},{v:!0,a:3,n:"Dispose",t:8,pi:[{n:"disposing",pt:$n[0].Boolean,ps:0}],sn:"Dispose$1",rt:$n[0].Void,p:[$n[0].Boolean]},{v:!0,a:3,n:"FillBuffer",t:8,pi:[{n:"numBytes",pt:$n[0].Int32,ps:0}],sn:"FillBuffer",rt:$n[0].Void,p:[$n[0].Int32]},{a:1,n:"InternalReadChars",t:8,pi:[{n:"buffer",pt:$n[0].Array.type(System.Char),ps:0},{n:"index",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2}],sn:"InternalReadChars",rt:$n[0].Int32,p:[$n[0].Array.type(System.Char),$n[0].Int32,$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"InternalReadOneChar",t:8,pi:[{n:"allowSurrogate",dv:!1,o:!0,pt:$n[0].Boolean,ps:0}],sn:"InternalReadOneChar",rt:$n[0].Int32,p:[$n[0].Boolean],box:function($v){return H5.box($v,System.Int32)}},{v:!0,a:2,n:"PeekChar",t:8,sn:"PeekChar",rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}},{v:!0,a:2,n:"Read",t:8,sn:"Read",rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}},{v:!0,a:2,n:"Read",t:8,pi:[{n:"buffer",pt:$n[0].Array.type(System.Byte),ps:0},{n:"index",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2}],sn:"Read$1",rt:$n[0].Int32,p:[$n[0].Array.type(System.Byte),$n[0].Int32,$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{v:!0,a:2,n:"Read",t:8,pi:[{n:"buffer",pt:$n[0].Array.type(System.Char),ps:0},{n:"index",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2}],sn:"Read$2",rt:$n[0].Int32,p:[$n[0].Array.type(System.Char),$n[0].Int32,$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{a:5,n:"Read7BitEncodedInt",t:8,sn:"Read7BitEncodedInt",rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}},{v:!0,a:2,n:"ReadBoolean",t:8,sn:"ReadBoolean",rt:$n[0].Boolean,box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{v:!0,a:2,n:"ReadByte",t:8,sn:"ReadByte",rt:$n[0].Byte,box:function($v){return H5.box($v,System.Byte)}},{v:!0,a:2,n:"ReadBytes",t:8,pi:[{n:"count",pt:$n[0].Int32,ps:0}],sn:"ReadBytes",rt:$n[0].Array.type(System.Byte),p:[$n[0].Int32]},{v:!0,a:2,n:"ReadChar",t:8,sn:"ReadChar",rt:$n[0].Char,box:function($v){return H5.box($v,System.Char,String.fromCharCode,System.Char.getHashCode)}},{v:!0,a:2,n:"ReadChars",t:8,pi:[{n:"count",pt:$n[0].Int32,ps:0}],sn:"ReadChars",rt:$n[0].Array.type(System.Char),p:[$n[0].Int32]},{v:!0,a:2,n:"ReadDecimal",t:8,sn:"ReadDecimal",rt:$n[0].Decimal},{v:!0,a:2,n:"ReadDouble",t:8,sn:"ReadDouble",rt:$n[0].Double,box:function($v){return H5.box($v,System.Double,System.Double.format,System.Double.getHashCode)}},{v:!0,a:2,n:"ReadInt16",t:8,sn:"ReadInt16",rt:$n[0].Int16,box:function($v){return H5.box($v,System.Int16)}},{v:!0,a:2,n:"ReadInt32",t:8,sn:"ReadInt32",rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}},{v:!0,a:2,n:"ReadInt64",t:8,sn:"ReadInt64",rt:$n[0].Int64},{v:!0,a:2,n:"ReadSByte",t:8,sn:"ReadSByte",rt:$n[0].SByte,box:function($v){return H5.box($v,System.SByte)}},{v:!0,a:2,n:"ReadSingle",t:8,sn:"ReadSingle",rt:$n[0].Single,box:function($v){return H5.box($v,System.Single,System.Single.format,System.Single.getHashCode)}},{v:!0,a:2,n:"ReadString",t:8,sn:"ReadString",rt:$n[0].String},{v:!0,a:2,n:"ReadUInt16",t:8,sn:"ReadUInt16",rt:$n[0].UInt16,box:function($v){return H5.box($v,System.UInt16)}},{v:!0,a:2,n:"ReadUInt32",t:8,sn:"ReadUInt32",rt:$n[0].UInt32,box:function($v){return H5.box($v,System.UInt32)}},{v:!0,a:2,n:"ReadUInt64",t:8,sn:"ReadUInt64",rt:$n[0].UInt64},{v:!0,a:2,n:"BaseStream",t:16,rt:$n[14].Stream,g:{v:!0,a:2,n:"get_BaseStream",t:8,rt:$n[14].Stream,fg:"BaseStream"},fn:"BaseStream"},{a:1,n:"MaxCharBytesSize",is:!0,t:4,rt:$n[0].Int32,sn:"MaxCharBytesSize",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"lastCharsRead",t:4,rt:$n[0].Int32,sn:"lastCharsRead",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"m_2BytesPerChar",t:4,rt:$n[0].Boolean,sn:"m_2BytesPerChar",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"m_buffer",t:4,rt:$n[0].Array.type(System.Byte),sn:"m_buffer"},{a:1,n:"m_charBuffer",t:4,rt:$n[0].Array.type(System.Char),sn:"m_charBuffer"},{a:1,n:"m_charBytes",t:4,rt:$n[0].Array.type(System.Byte),sn:"m_charBytes"},{a:1,n:"m_encoding",t:4,rt:$n[8].Encoding,sn:"m_encoding"},{a:1,n:"m_isMemoryStream",t:4,rt:$n[0].Boolean,sn:"m_isMemoryStream",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"m_leaveOpen",t:4,rt:$n[0].Boolean,sn:"m_leaveOpen",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"m_maxCharsSize",t:4,rt:$n[0].Int32,sn:"m_maxCharsSize",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"m_singleChar",t:4,rt:$n[0].Array.type(System.Char),sn:"m_singleChar"},{a:1,n:"m_stream",t:4,rt:$n[14].Stream,sn:"m_stream"}]}},$n);$m("System.IO.BinaryWriter",function(){return{att:1048577,a:2,m:[{a:3,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[14].Stream],pi:[{n:"output",pt:$n[14].Stream,ps:0}],sn:"$ctor1"},{a:2,n:".ctor",t:1,p:[$n[14].Stream,$n[8].Encoding],pi:[{n:"output",pt:$n[14].Stream,ps:0},{n:"encoding",pt:$n[8].Encoding,ps:1}],sn:"$ctor2"},{a:2,n:".ctor",t:1,p:[$n[14].Stream,$n[8].Encoding,$n[0].Boolean],pi:[{n:"output",pt:$n[14].Stream,ps:0},{n:"encoding",pt:$n[8].Encoding,ps:1},{n:"leaveOpen",pt:$n[0].Boolean,ps:2}],sn:"$ctor3"},{v:!0,a:2,n:"Close",t:8,sn:"Close",rt:$n[0].Void},{a:2,n:"Dispose",t:8,sn:"Dispose",rt:$n[0].Void},{v:!0,a:3,n:"Dispose",t:8,pi:[{n:"disposing",pt:$n[0].Boolean,ps:0}],sn:"Dispose$1",rt:$n[0].Void,p:[$n[0].Boolean]},{v:!0,a:2,n:"Flush",t:8,sn:"Flush",rt:$n[0].Void},{v:!0,a:2,n:"Seek",t:8,pi:[{n:"offset",pt:$n[0].Int32,ps:0},{n:"origin",pt:$n[14].SeekOrigin,ps:1}],sn:"Seek",rt:$n[0].Int64,p:[$n[0].Int32,$n[14].SeekOrigin]},{v:!0,a:2,n:"Write",t:8,pi:[{n:"value",pt:$n[0].Boolean,ps:0}],sn:"Write",rt:$n[0].Void,p:[$n[0].Boolean]},{v:!0,a:2,n:"Write",t:8,pi:[{n:"value",pt:$n[0].Byte,ps:0}],sn:"Write$1",rt:$n[0].Void,p:[$n[0].Byte]},{v:!0,a:2,n:"Write",t:8,pi:[{n:"buffer",pt:$n[0].Array.type(System.Byte),ps:0}],sn:"Write$2",rt:$n[0].Void,p:[$n[0].Array.type(System.Byte)]},{v:!0,a:2,n:"Write",t:8,pi:[{n:"ch",pt:$n[0].Char,ps:0}],sn:"Write$4",rt:$n[0].Void,p:[$n[0].Char]},{v:!0,a:2,n:"Write",t:8,pi:[{n:"chars",pt:$n[0].Array.type(System.Char),ps:0}],sn:"Write$5",rt:$n[0].Void,p:[$n[0].Array.type(System.Char)]},{v:!0,a:2,n:"Write",t:8,pi:[{n:"value",pt:$n[0].Decimal,ps:0}],sn:"Write$7",rt:$n[0].Void,p:[$n[0].Decimal]},{v:!0,a:2,n:"Write",t:8,pi:[{n:"value",pt:$n[0].Double,ps:0}],sn:"Write$8",rt:$n[0].Void,p:[$n[0].Double]},{v:!0,a:2,n:"Write",t:8,pi:[{n:"value",pt:$n[0].Int16,ps:0}],sn:"Write$9",rt:$n[0].Void,p:[$n[0].Int16]},{v:!0,a:2,n:"Write",t:8,pi:[{n:"value",pt:$n[0].Int32,ps:0}],sn:"Write$10",rt:$n[0].Void,p:[$n[0].Int32]},{v:!0,a:2,n:"Write",t:8,pi:[{n:"value",pt:$n[0].Int64,ps:0}],sn:"Write$11",rt:$n[0].Void,p:[$n[0].Int64]},{v:!0,a:2,n:"Write",t:8,pi:[{n:"value",pt:$n[0].SByte,ps:0}],sn:"Write$12",rt:$n[0].Void,p:[$n[0].SByte]},{v:!0,a:2,n:"Write",t:8,pi:[{n:"value",pt:$n[0].Single,ps:0}],sn:"Write$13",rt:$n[0].Void,p:[$n[0].Single]},{v:!0,a:2,n:"Write",t:8,pi:[{n:"value",pt:$n[0].String,ps:0}],sn:"Write$14",rt:$n[0].Void,p:[$n[0].String]},{v:!0,a:2,n:"Write",t:8,pi:[{n:"value",pt:$n[0].UInt16,ps:0}],sn:"Write$15",rt:$n[0].Void,p:[$n[0].UInt16]},{v:!0,a:2,n:"Write",t:8,pi:[{n:"value",pt:$n[0].UInt32,ps:0}],sn:"Write$16",rt:$n[0].Void,p:[$n[0].UInt32]},{v:!0,a:2,n:"Write",t:8,pi:[{n:"value",pt:$n[0].UInt64,ps:0}],sn:"Write$17",rt:$n[0].Void,p:[$n[0].UInt64]},{v:!0,a:2,n:"Write",t:8,pi:[{n:"buffer",pt:$n[0].Array.type(System.Byte),ps:0},{n:"index",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2}],sn:"Write$3",rt:$n[0].Void,p:[$n[0].Array.type(System.Byte),$n[0].Int32,$n[0].Int32]},{v:!0,a:2,n:"Write",t:8,pi:[{n:"chars",pt:$n[0].Array.type(System.Char),ps:0},{n:"index",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2}],sn:"Write$6",rt:$n[0].Void,p:[$n[0].Array.type(System.Char),$n[0].Int32,$n[0].Int32]},{a:3,n:"Write7BitEncodedInt",t:8,pi:[{n:"value",pt:$n[0].Int32,ps:0}],sn:"Write7BitEncodedInt",rt:$n[0].Void,p:[$n[0].Int32]},{v:!0,a:2,n:"BaseStream",t:16,rt:$n[14].Stream,g:{v:!0,a:2,n:"get_BaseStream",t:8,rt:$n[14].Stream,fg:"BaseStream"},fn:"BaseStream"},{a:1,n:"LargeByteBufferSize",is:!0,t:4,rt:$n[0].Int32,sn:"LargeByteBufferSize",box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"Null",is:!0,t:4,rt:$n[14].BinaryWriter,sn:"Null",ro:!0},{a:3,n:"OutStream",t:4,rt:$n[14].Stream,sn:"OutStream"},{a:1,n:"_buffer",t:4,rt:$n[0].Array.type(System.Byte),sn:"_buffer"},{a:1,n:"_encoding",t:4,rt:$n[8].Encoding,sn:"_encoding"},{a:1,n:"_leaveOpen",t:4,rt:$n[0].Boolean,sn:"_leaveOpen",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"_tmpOneCharBuffer",t:4,rt:$n[0].Array.type(System.Char),sn:"_tmpOneCharBuffer"}]}},$n);$m("System.IO.BufferedStream",function(){return{att:1048833,a:2,m:[{a:1,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[14].Stream],pi:[{n:"stream",pt:$n[14].Stream,ps:0}],sn:"$ctor1"},{a:2,n:".ctor",t:1,p:[$n[14].Stream,$n[0].Int32],pi:[{n:"stream",pt:$n[14].Stream,ps:0},{n:"bufferSize",pt:$n[0].Int32,ps:1}],sn:"$ctor2"},{a:1,n:"ClearReadBufferBeforeWrite",t:8,sn:"ClearReadBufferBeforeWrite",rt:$n[0].Void},{ov:!0,a:3,n:"Dispose",t:8,pi:[{n:"disposing",pt:$n[0].Boolean,ps:0}],sn:"Dispose$1",rt:$n[0].Void,p:[$n[0].Boolean]},{a:1,n:"EnsureBufferAllocated",t:8,sn:"EnsureBufferAllocated",rt:$n[0].Void},{a:1,n:"EnsureCanRead",t:8,sn:"EnsureCanRead",rt:$n[0].Void},{a:1,n:"EnsureCanSeek",t:8,sn:"EnsureCanSeek",rt:$n[0].Void},{a:1,n:"EnsureCanWrite",t:8,sn:"EnsureCanWrite",rt:$n[0].Void},{a:1,n:"EnsureNotClosed",t:8,sn:"EnsureNotClosed",rt:$n[0].Void},{a:1,n:"EnsureShadowBufferAllocated",t:8,sn:"EnsureShadowBufferAllocated",rt:$n[0].Void},{ov:!0,a:2,n:"Flush",t:8,sn:"Flush",rt:$n[0].Void},{a:1,n:"FlushRead",t:8,sn:"FlushRead",rt:$n[0].Void},{a:1,n:"FlushWrite",t:8,sn:"FlushWrite",rt:$n[0].Void},{ov:!0,a:2,n:"Read",t:8,pi:[{n:"array",pt:$n[0].Array.type(System.Byte),ps:0},{n:"offset",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2}],sn:"Read",rt:$n[0].Int32,p:[$n[0].Array.type(System.Byte),$n[0].Int32,$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{ov:!0,a:2,n:"ReadByte",t:8,sn:"ReadByte",rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"ReadFromBuffer",t:8,pi:[{n:"array",pt:$n[0].Array.type(System.Byte),ps:0},{n:"offset",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2}],sn:"ReadFromBuffer",rt:$n[0].Int32,p:[$n[0].Array.type(System.Byte),$n[0].Int32,$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"ReadFromBuffer",t:8,pi:[{n:"array",pt:$n[0].Array.type(System.Byte),ps:0},{n:"offset",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2},{n:"error",out:!0,pt:$n[0].Exception,ps:3}],sn:"ReadFromBuffer$1",rt:$n[0].Int32,p:[$n[0].Array.type(System.Byte),$n[0].Int32,$n[0].Int32,$n[0].Exception],box:function($v){return H5.box($v,System.Int32)}},{ov:!0,a:2,n:"Seek",t:8,pi:[{n:"offset",pt:$n[0].Int64,ps:0},{n:"origin",pt:$n[14].SeekOrigin,ps:1}],sn:"Seek",rt:$n[0].Int64,p:[$n[0].Int64,$n[14].SeekOrigin]},{ov:!0,a:2,n:"SetLength",t:8,pi:[{n:"value",pt:$n[0].Int64,ps:0}],sn:"SetLength",rt:$n[0].Void,p:[$n[0].Int64]},{ov:!0,a:2,n:"Write",t:8,pi:[{n:"array",pt:$n[0].Array.type(System.Byte),ps:0},{n:"offset",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2}],sn:"Write",rt:$n[0].Void,p:[$n[0].Array.type(System.Byte),$n[0].Int32,$n[0].Int32]},{ov:!0,a:2,n:"WriteByte",t:8,pi:[{n:"value",pt:$n[0].Byte,ps:0}],sn:"WriteByte",rt:$n[0].Void,p:[$n[0].Byte]},{a:1,n:"WriteToBuffer",t:8,pi:[{n:"array",pt:$n[0].Array.type(System.Byte),ps:0},{n:"offset",ref:!0,pt:$n[0].Int32,ps:1},{n:"count",ref:!0,pt:$n[0].Int32,ps:2}],sn:"WriteToBuffer",rt:$n[0].Void,p:[$n[0].Array.type(System.Byte),$n[0].Int32,$n[0].Int32]},{a:1,n:"WriteToBuffer",t:8,pi:[{n:"array",pt:$n[0].Array.type(System.Byte),ps:0},{n:"offset",ref:!0,pt:$n[0].Int32,ps:1},{n:"count",ref:!0,pt:$n[0].Int32,ps:2},{n:"error",out:!0,pt:$n[0].Exception,ps:3}],sn:"WriteToBuffer$1",rt:$n[0].Void,p:[$n[0].Array.type(System.Byte),$n[0].Int32,$n[0].Int32,$n[0].Exception]},{a:4,n:"BufferSize",t:16,rt:$n[0].Int32,g:{a:4,n:"get_BufferSize",t:8,rt:$n[0].Int32,fg:"BufferSize",box:function($v){return H5.box($v,System.Int32)}},fn:"BufferSize"},{ov:!0,a:2,n:"CanRead",t:16,rt:$n[0].Boolean,g:{ov:!0,a:2,n:"get_CanRead",t:8,rt:$n[0].Boolean,fg:"CanRead",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},fn:"CanRead"},{ov:!0,a:2,n:"CanSeek",t:16,rt:$n[0].Boolean,g:{ov:!0,a:2,n:"get_CanSeek",t:8,rt:$n[0].Boolean,fg:"CanSeek",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},fn:"CanSeek"},{ov:!0,a:2,n:"CanWrite",t:16,rt:$n[0].Boolean,g:{ov:!0,a:2,n:"get_CanWrite",t:8,rt:$n[0].Boolean,fg:"CanWrite",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},fn:"CanWrite"},{ov:!0,a:2,n:"Length",t:16,rt:$n[0].Int64,g:{ov:!0,a:2,n:"get_Length",t:8,rt:$n[0].Int64,fg:"Length"},fn:"Length"},{ov:!0,a:2,n:"Position",t:16,rt:$n[0].Int64,g:{ov:!0,a:2,n:"get_Position",t:8,rt:$n[0].Int64,fg:"Position"},s:{ov:!0,a:2,n:"set_Position",t:8,p:[$n[0].Int64],rt:$n[0].Void,fs:"Position"},fn:"Position"},{a:4,n:"UnderlyingStream",t:16,rt:$n[14].Stream,g:{a:4,n:"get_UnderlyingStream",t:8,rt:$n[14].Stream,fg:"UnderlyingStream"},fn:"UnderlyingStream"},{a:1,n:"MaxShadowBufferSize",is:!0,t:4,rt:$n[0].Int32,sn:"MaxShadowBufferSize",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"_DefaultBufferSize",is:!0,t:4,rt:$n[0].Int32,sn:"_DefaultBufferSize",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"_buffer",t:4,rt:$n[0].Array.type(System.Byte),sn:"_buffer"},{a:1,n:"_bufferSize",t:4,rt:$n[0].Int32,sn:"_bufferSize",ro:!0,box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"_readLen",t:4,rt:$n[0].Int32,sn:"_readLen",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"_readPos",t:4,rt:$n[0].Int32,sn:"_readPos",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"_stream",t:4,rt:$n[14].Stream,sn:"_stream"},{a:1,n:"_writePos",t:4,rt:$n[0].Int32,sn:"_writePos",box:function($v){return H5.box($v,System.Int32)}}]}},$n);$m("System.IO.EndOfStreamException",function(){return{att:1048577,a:2,m:[{a:2,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].String],pi:[{n:"message",pt:$n[0].String,ps:0}],sn:"$ctor1"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[0].Exception],pi:[{n:"message",pt:$n[0].String,ps:0},{n:"innerException",pt:$n[0].Exception,ps:1}],sn:"$ctor2"}]}},$n);$m("System.IO.File",function(){return{att:1048961,a:2,s:!0,m:[{a:1,n:"InternalReadAllBytes",is:!0,t:8,pi:[{n:"path",pt:$n[0].String,ps:0},{n:"checkHost",pt:$n[0].Boolean,ps:1}],sn:"InternalReadAllBytes",rt:$n[0].Array.type(System.Byte),p:[$n[0].String,$n[0].Boolean]},{a:1,n:"InternalReadAllLines",is:!0,t:8,pi:[{n:"path",pt:$n[0].String,ps:0},{n:"encoding",pt:$n[8].Encoding,ps:1}],sn:"InternalReadAllLines",rt:$n[0].Array.type(System.String),p:[$n[0].String,$n[8].Encoding]},{a:1,n:"InternalReadAllText",is:!0,t:8,pi:[{n:"path",pt:$n[0].String,ps:0},{n:"encoding",pt:$n[8].Encoding,ps:1},{n:"checkHost",pt:$n[0].Boolean,ps:2}],sn:"InternalReadAllText",rt:$n[0].String,p:[$n[0].String,$n[8].Encoding,$n[0].Boolean]},{a:2,n:"OpenRead",is:!0,t:8,pi:[{n:"path",pt:$n[0].String,ps:0}],sn:"OpenRead",rt:$n[14].FileStream,p:[$n[0].String]},{a:2,n:"OpenText",is:!0,t:8,pi:[{n:"path",pt:$n[0].String,ps:0}],sn:"OpenText",rt:$n[14].StreamReader,p:[$n[0].String]},{a:2,n:"ReadAllBytes",is:!0,t:8,pi:[{n:"path",pt:$n[0].String,ps:0}],sn:"ReadAllBytes",rt:$n[0].Array.type(System.Byte),p:[$n[0].String]},{a:2,n:"ReadAllLines",is:!0,t:8,pi:[{n:"path",pt:$n[0].String,ps:0}],sn:"ReadAllLines",rt:$n[0].Array.type(System.String),p:[$n[0].String]},{a:2,n:"ReadAllLines",is:!0,t:8,pi:[{n:"path",pt:$n[0].String,ps:0},{n:"encoding",pt:$n[8].Encoding,ps:1}],sn:"ReadAllLines$1",rt:$n[0].Array.type(System.String),p:[$n[0].String,$n[8].Encoding]},{a:2,n:"ReadAllText",is:!0,t:8,pi:[{n:"path",pt:$n[0].String,ps:0}],sn:"ReadAllText",rt:$n[0].String,p:[$n[0].String]},{a:2,n:"ReadAllText",is:!0,t:8,pi:[{n:"path",pt:$n[0].String,ps:0},{n:"encoding",pt:$n[8].Encoding,ps:1}],sn:"ReadAllText$1",rt:$n[0].String,p:[$n[0].String,$n[8].Encoding]},{a:2,n:"ReadLines",is:!0,t:8,pi:[{n:"path",pt:$n[0].String,ps:0}],sn:"ReadLines",rt:$n[3].IEnumerable$1(System.String),p:[$n[0].String]},{a:2,n:"ReadLines",is:!0,t:8,pi:[{n:"path",pt:$n[0].String,ps:0},{n:"encoding",pt:$n[8].Encoding,ps:1}],sn:"ReadLines$1",rt:$n[3].IEnumerable$1(System.String),p:[$n[0].String,$n[8].Encoding]}]}},$n);$m("System.IO.FileMode",function(){return{att:257,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:"Append",is:!0,t:4,rt:$n[14].FileMode,sn:"Append",box:function($v){return H5.box($v,System.IO.FileMode,System.Enum.toStringFn(System.IO.FileMode))}},{a:2,n:"Create",is:!0,t:4,rt:$n[14].FileMode,sn:"Create",box:function($v){return H5.box($v,System.IO.FileMode,System.Enum.toStringFn(System.IO.FileMode))}},{a:2,n:"CreateNew",is:!0,t:4,rt:$n[14].FileMode,sn:"CreateNew",box:function($v){return H5.box($v,System.IO.FileMode,System.Enum.toStringFn(System.IO.FileMode))}},{a:2,n:"Open",is:!0,t:4,rt:$n[14].FileMode,sn:"Open",box:function($v){return H5.box($v,System.IO.FileMode,System.Enum.toStringFn(System.IO.FileMode))}},{a:2,n:"OpenOrCreate",is:!0,t:4,rt:$n[14].FileMode,sn:"OpenOrCreate",box:function($v){return H5.box($v,System.IO.FileMode,System.Enum.toStringFn(System.IO.FileMode))}},{a:2,n:"Truncate",is:!0,t:4,rt:$n[14].FileMode,sn:"Truncate",box:function($v){return H5.box($v,System.IO.FileMode,System.Enum.toStringFn(System.IO.FileMode))}}]}},$n);$m("System.IO.FileOptions",function(){return{att:257,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:"Asynchronous",is:!0,t:4,rt:$n[14].FileOptions,sn:"Asynchronous",box:function($v){return H5.box($v,System.IO.FileOptions,System.Enum.toStringFn(System.IO.FileOptions))}},{a:2,n:"DeleteOnClose",is:!0,t:4,rt:$n[14].FileOptions,sn:"DeleteOnClose",box:function($v){return H5.box($v,System.IO.FileOptions,System.Enum.toStringFn(System.IO.FileOptions))}},{a:2,n:"Encrypted",is:!0,t:4,rt:$n[14].FileOptions,sn:"Encrypted",box:function($v){return H5.box($v,System.IO.FileOptions,System.Enum.toStringFn(System.IO.FileOptions))}},{a:2,n:"None",is:!0,t:4,rt:$n[14].FileOptions,sn:"None",box:function($v){return H5.box($v,System.IO.FileOptions,System.Enum.toStringFn(System.IO.FileOptions))}},{a:2,n:"RandomAccess",is:!0,t:4,rt:$n[14].FileOptions,sn:"RandomAccess",box:function($v){return H5.box($v,System.IO.FileOptions,System.Enum.toStringFn(System.IO.FileOptions))}},{a:2,n:"SequentialScan",is:!0,t:4,rt:$n[14].FileOptions,sn:"SequentialScan",box:function($v){return H5.box($v,System.IO.FileOptions,System.Enum.toStringFn(System.IO.FileOptions))}},{a:2,n:"WriteThrough",is:!0,t:4,rt:$n[14].FileOptions,sn:"WriteThrough",box:function($v){return H5.box($v,System.IO.FileOptions,System.Enum.toStringFn(System.IO.FileOptions))}}]}},$n);$m("System.IO.FileShare",function(){return{att:257,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:"Delete",is:!0,t:4,rt:$n[14].FileShare,sn:"Delete",box:function($v){return H5.box($v,System.IO.FileShare,System.Enum.toStringFn(System.IO.FileShare))}},{a:2,n:"Inheritable",is:!0,t:4,rt:$n[14].FileShare,sn:"Inheritable",box:function($v){return H5.box($v,System.IO.FileShare,System.Enum.toStringFn(System.IO.FileShare))}},{a:2,n:"None",is:!0,t:4,rt:$n[14].FileShare,sn:"None",box:function($v){return H5.box($v,System.IO.FileShare,System.Enum.toStringFn(System.IO.FileShare))}},{a:2,n:"Read",is:!0,t:4,rt:$n[14].FileShare,sn:"Read",box:function($v){return H5.box($v,System.IO.FileShare,System.Enum.toStringFn(System.IO.FileShare))}},{a:2,n:"ReadWrite",is:!0,t:4,rt:$n[14].FileShare,sn:"ReadWrite",box:function($v){return H5.box($v,System.IO.FileShare,System.Enum.toStringFn(System.IO.FileShare))}},{a:2,n:"Write",is:!0,t:4,rt:$n[14].FileShare,sn:"Write",box:function($v){return H5.box($v,System.IO.FileShare,System.Enum.toStringFn(System.IO.FileShare))}}]}},$n);$m("System.IO.IOException",function(){return{att:1056769,a:2,at:[new System.SerializableAttribute],m:[{a:2,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].String],pi:[{n:"message",pt:$n[0].String,ps:0}],sn:"$ctor1"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[0].Exception],pi:[{n:"message",pt:$n[0].String,ps:0},{n:"innerException",pt:$n[0].Exception,ps:1}],sn:"$ctor2"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[0].Int32],pi:[{n:"message",pt:$n[0].String,ps:0},{n:"hresult",pt:$n[0].Int32,ps:1}],sn:"$ctor3"}]}},$n);$m("System.IO.MemoryStream",function(){return{att:1048577,a:2,m:[{a:2,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].Array.type(System.Byte)],pi:[{n:"buffer",pt:$n[0].Array.type(System.Byte),ps:0}],sn:"$ctor1"},{a:2,n:".ctor",t:1,p:[$n[0].Int32],pi:[{n:"capacity",pt:$n[0].Int32,ps:0}],sn:"$ctor6"},{a:2,n:".ctor",t:1,p:[$n[0].Array.type(System.Byte),$n[0].Boolean],pi:[{n:"buffer",pt:$n[0].Array.type(System.Byte),ps:0},{n:"writable",pt:$n[0].Boolean,ps:1}],sn:"$ctor2"},{a:2,n:".ctor",t:1,p:[$n[0].Array.type(System.Byte),$n[0].Int32,$n[0].Int32],pi:[{n:"buffer",pt:$n[0].Array.type(System.Byte),ps:0},{n:"index",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2}],sn:"$ctor3"},{a:2,n:".ctor",t:1,p:[$n[0].Array.type(System.Byte),$n[0].Int32,$n[0].Int32,$n[0].Boolean],pi:[{n:"buffer",pt:$n[0].Array.type(System.Byte),ps:0},{n:"index",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2},{n:"writable",pt:$n[0].Boolean,ps:3}],sn:"$ctor4"},{a:2,n:".ctor",t:1,p:[$n[0].Array.type(System.Byte),$n[0].Int32,$n[0].Int32,$n[0].Boolean,$n[0].Boolean],pi:[{n:"buffer",pt:$n[0].Array.type(System.Byte),ps:0},{n:"index",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2},{n:"writable",pt:$n[0].Boolean,ps:3},{n:"publiclyVisible",pt:$n[0].Boolean,ps:4}],sn:"$ctor5"},{ov:!0,a:3,n:"Dispose",t:8,pi:[{n:"disposing",pt:$n[0].Boolean,ps:0}],sn:"Dispose$1",rt:$n[0].Void,p:[$n[0].Boolean]},{a:1,n:"EnsureCapacity",t:8,pi:[{n:"value",pt:$n[0].Int32,ps:0}],sn:"EnsureCapacity",rt:$n[0].Boolean,p:[$n[0].Int32],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"EnsureWriteable",t:8,sn:"EnsureWriteable",rt:$n[0].Void},{ov:!0,a:2,n:"Flush",t:8,sn:"Flush",rt:$n[0].Void},{v:!0,a:2,n:"GetBuffer",t:8,sn:"GetBuffer",rt:$n[0].Array.type(System.Byte)},{a:4,n:"InternalEmulateRead",t:8,pi:[{n:"count",pt:$n[0].Int32,ps:0}],sn:"InternalEmulateRead",rt:$n[0].Int32,p:[$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"InternalGetBuffer",t:8,sn:"InternalGetBuffer",rt:$n[0].Array.type(System.Byte)},{a:4,n:"InternalGetPosition",t:8,sn:"InternalGetPosition",rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"InternalReadInt32",t:8,sn:"InternalReadInt32",rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}},{ov:!0,a:2,n:"Read",t:8,pi:[{n:"buffer",pt:$n[0].Array.type(System.Byte),ps:0},{n:"offset",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2}],sn:"Read",rt:$n[0].Int32,p:[$n[0].Array.type(System.Byte),$n[0].Int32,$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{ov:!0,a:2,n:"ReadByte",t:8,sn:"ReadByte",rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}},{ov:!0,a:2,n:"Seek",t:8,pi:[{n:"offset",pt:$n[0].Int64,ps:0},{n:"loc",pt:$n[14].SeekOrigin,ps:1}],sn:"Seek",rt:$n[0].Int64,p:[$n[0].Int64,$n[14].SeekOrigin]},{ov:!0,a:2,n:"SetLength",t:8,pi:[{n:"value",pt:$n[0].Int64,ps:0}],sn:"SetLength",rt:$n[0].Void,p:[$n[0].Int64]},{v:!0,a:2,n:"ToArray",t:8,sn:"ToArray",rt:$n[0].Array.type(System.Byte)},{v:!0,a:2,n:"TryGetBuffer",t:8,pi:[{n:"buffer",out:!0,pt:$n[0].ArraySegment,ps:0}],sn:"TryGetBuffer",rt:$n[0].Boolean,p:[$n[0].ArraySegment],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ov:!0,a:2,n:"Write",t:8,pi:[{n:"buffer",pt:$n[0].Array.type(System.Byte),ps:0},{n:"offset",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2}],sn:"Write",rt:$n[0].Void,p:[$n[0].Array.type(System.Byte),$n[0].Int32,$n[0].Int32]},{ov:!0,a:2,n:"WriteByte",t:8,pi:[{n:"value",pt:$n[0].Byte,ps:0}],sn:"WriteByte",rt:$n[0].Void,p:[$n[0].Byte]},{v:!0,a:2,n:"WriteTo",t:8,pi:[{n:"stream",pt:$n[14].Stream,ps:0}],sn:"WriteTo",rt:$n[0].Void,p:[$n[14].Stream]},{ov:!0,a:2,n:"CanRead",t:16,rt:$n[0].Boolean,g:{ov:!0,a:2,n:"get_CanRead",t:8,rt:$n[0].Boolean,fg:"CanRead",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},fn:"CanRead"},{ov:!0,a:2,n:"CanSeek",t:16,rt:$n[0].Boolean,g:{ov:!0,a:2,n:"get_CanSeek",t:8,rt:$n[0].Boolean,fg:"CanSeek",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},fn:"CanSeek"},{ov:!0,a:2,n:"CanWrite",t:16,rt:$n[0].Boolean,g:{ov:!0,a:2,n:"get_CanWrite",t:8,rt:$n[0].Boolean,fg:"CanWrite",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},fn:"CanWrite"},{v:!0,a:2,n:"Capacity",t:16,rt:$n[0].Int32,g:{v:!0,a:2,n:"get_Capacity",t:8,rt:$n[0].Int32,fg:"Capacity",box:function($v){return H5.box($v,System.Int32)}},s:{v:!0,a:2,n:"set_Capacity",t:8,p:[$n[0].Int32],rt:$n[0].Void,fs:"Capacity"},fn:"Capacity"},{ov:!0,a:2,n:"Length",t:16,rt:$n[0].Int64,g:{ov:!0,a:2,n:"get_Length",t:8,rt:$n[0].Int64,fg:"Length"},fn:"Length"},{ov:!0,a:2,n:"Position",t:16,rt:$n[0].Int64,g:{ov:!0,a:2,n:"get_Position",t:8,rt:$n[0].Int64,fg:"Position"},s:{ov:!0,a:2,n:"set_Position",t:8,p:[$n[0].Int64],rt:$n[0].Void,fs:"Position"},fn:"Position"},{a:1,n:"MemStreamMaxLength",is:!0,t:4,rt:$n[0].Int32,sn:"MemStreamMaxLength",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"_buffer",t:4,rt:$n[0].Array.type(System.Byte),sn:"_buffer"},{a:1,n:"_capacity",t:4,rt:$n[0].Int32,sn:"_capacity",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"_expandable",t:4,rt:$n[0].Boolean,sn:"_expandable",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"_exposable",t:4,rt:$n[0].Boolean,sn:"_exposable",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"_isOpen",t:4,rt:$n[0].Boolean,sn:"_isOpen",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"_length",t:4,rt:$n[0].Int32,sn:"_length",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"_origin",t:4,rt:$n[0].Int32,sn:"_origin",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"_position",t:4,rt:$n[0].Int32,sn:"_position",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"_writable",t:4,rt:$n[0].Boolean,sn:"_writable",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}}]}},$n);$m("System.IO.Iterator$1",function(TSource){return{att:1048704,a:4,m:[{a:2,n:".ctor",t:1,sn:"ctor"},{ab:!0,a:3,n:"Clone",t:8,sn:"Clone",rt:$n[14].Iterator$1(TSource)},{a:2,n:"Dispose",t:8,sn:"Dispose",rt:$n[0].Void},{v:!0,a:3,n:"Dispose",t:8,pi:[{n:"disposing",pt:$n[0].Boolean,ps:0}],sn:"Dispose$1",rt:$n[0].Void,p:[$n[0].Boolean]},{a:2,n:"GetEnumerator",t:8,sn:"GetEnumerator",rt:$n[3].IEnumerator$1(TSource)},{ab:!0,a:2,n:"MoveNext",t:8,sn:"moveNext",rt:$n[0].Boolean,box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Current",t:16,rt:TSource,g:{a:2,n:"get_Current",t:8,rt:TSource,fg:"Current"},fn:"Current"},{a:4,n:"current",t:4,rt:TSource,sn:"current"},{a:4,n:"state",t:4,rt:$n[0].Int32,sn:"state",box:function($v){return H5.box($v,System.Int32)}}]}},$n);$m("System.IO.ReadLinesIterator",function(){return{att:1048576,a:4,m:[{a:1,n:".ctor",t:1,p:[$n[0].String,$n[8].Encoding,$n[14].StreamReader],pi:[{n:"path",pt:$n[0].String,ps:0},{n:"encoding",pt:$n[8].Encoding,ps:1},{n:"reader",pt:$n[14].StreamReader,ps:2}],sn:"ctor"},{ov:!0,a:3,n:"Clone",t:8,sn:"Clone",rt:$n[14].Iterator$1(System.String)},{a:4,n:"CreateIterator",is:!0,t:8,pi:[{n:"path",pt:$n[0].String,ps:0},{n:"encoding",pt:$n[8].Encoding,ps:1}],sn:"CreateIterator",rt:$n[14].ReadLinesIterator,p:[$n[0].String,$n[8].Encoding]},{a:1,n:"CreateIterator",is:!0,t:8,pi:[{n:"path",pt:$n[0].String,ps:0},{n:"encoding",pt:$n[8].Encoding,ps:1},{n:"reader",pt:$n[14].StreamReader,ps:2}],sn:"CreateIterator$1",rt:$n[14].ReadLinesIterator,p:[$n[0].String,$n[8].Encoding,$n[14].StreamReader]},{ov:!0,a:3,n:"Dispose",t:8,pi:[{n:"disposing",pt:$n[0].Boolean,ps:0}],sn:"Dispose$1",rt:$n[0].Void,p:[$n[0].Boolean]},{ov:!0,a:2,n:"MoveNext",t:8,sn:"moveNext",rt:$n[0].Boolean,box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"_encoding",t:4,rt:$n[8].Encoding,sn:"_encoding",ro:!0},{a:1,n:"_path",t:4,rt:$n[0].String,sn:"_path",ro:!0},{a:1,n:"_reader",t:4,rt:$n[14].StreamReader,sn:"_reader"}]}},$n);$m("System.IO.SeekOrigin",function(){return{att:257,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:"Begin",is:!0,t:4,rt:$n[14].SeekOrigin,sn:"Begin",box:function($v){return H5.box($v,System.IO.SeekOrigin,System.Enum.toStringFn(System.IO.SeekOrigin))}},{a:2,n:"Current",is:!0,t:4,rt:$n[14].SeekOrigin,sn:"Current",box:function($v){return H5.box($v,System.IO.SeekOrigin,System.Enum.toStringFn(System.IO.SeekOrigin))}},{a:2,n:"End",is:!0,t:4,rt:$n[14].SeekOrigin,sn:"End",box:function($v){return H5.box($v,System.IO.SeekOrigin,System.Enum.toStringFn(System.IO.SeekOrigin))}}]}},$n);$m("System.IO.Stream",function(){return{nested:[$n[14].Stream.NullStream,$n[14].Stream.SynchronousAsyncResult],att:1048705,a:2,m:[{a:3,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{v:!0,a:2,n:"BeginRead",t:8,pi:[{n:"buffer",pt:$n[0].Array.type(System.Byte),ps:0},{n:"offset",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2},{n:"callback",pt:Function,ps:3},{n:"state",pt:$n[0].Object,ps:4}],sn:"BeginRead",rt:$n[0].IAsyncResult,p:[$n[0].Array.type(System.Byte),$n[0].Int32,$n[0].Int32,Function,$n[0].Object]},{a:4,n:"BeginReadInternal",t:8,pi:[{n:"buffer",pt:$n[0].Array.type(System.Byte),ps:0},{n:"offset",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2},{n:"callback",pt:Function,ps:3},{n:"state",pt:$n[0].Object,ps:4},{n:"serializeAsynchronously",pt:$n[0].Boolean,ps:5}],sn:"BeginReadInternal",rt:$n[0].IAsyncResult,p:[$n[0].Array.type(System.Byte),$n[0].Int32,$n[0].Int32,Function,$n[0].Object,$n[0].Boolean]},{v:!0,a:2,n:"BeginWrite",t:8,pi:[{n:"buffer",pt:$n[0].Array.type(System.Byte),ps:0},{n:"offset",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2},{n:"callback",pt:Function,ps:3},{n:"state",pt:$n[0].Object,ps:4}],sn:"BeginWrite",rt:$n[0].IAsyncResult,p:[$n[0].Array.type(System.Byte),$n[0].Int32,$n[0].Int32,Function,$n[0].Object]},{a:4,n:"BeginWriteInternal",t:8,pi:[{n:"buffer",pt:$n[0].Array.type(System.Byte),ps:0},{n:"offset",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2},{n:"callback",pt:Function,ps:3},{n:"state",pt:$n[0].Object,ps:4},{n:"serializeAsynchronously",pt:$n[0].Boolean,ps:5}],sn:"BeginWriteInternal",rt:$n[0].IAsyncResult,p:[$n[0].Array.type(System.Byte),$n[0].Int32,$n[0].Int32,Function,$n[0].Object,$n[0].Boolean]},{a:4,n:"BlockingBeginRead",t:8,pi:[{n:"buffer",pt:$n[0].Array.type(System.Byte),ps:0},{n:"offset",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2},{n:"callback",pt:Function,ps:3},{n:"state",pt:$n[0].Object,ps:4}],sn:"BlockingBeginRead",rt:$n[0].IAsyncResult,p:[$n[0].Array.type(System.Byte),$n[0].Int32,$n[0].Int32,Function,$n[0].Object]},{a:4,n:"BlockingBeginWrite",t:8,pi:[{n:"buffer",pt:$n[0].Array.type(System.Byte),ps:0},{n:"offset",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2},{n:"callback",pt:Function,ps:3},{n:"state",pt:$n[0].Object,ps:4}],sn:"BlockingBeginWrite",rt:$n[0].IAsyncResult,p:[$n[0].Array.type(System.Byte),$n[0].Int32,$n[0].Int32,Function,$n[0].Object]},{a:4,n:"BlockingEndRead",is:!0,t:8,pi:[{n:"asyncResult",pt:$n[0].IAsyncResult,ps:0}],sn:"BlockingEndRead",rt:$n[0].Int32,p:[$n[0].IAsyncResult],box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"BlockingEndWrite",is:!0,t:8,pi:[{n:"asyncResult",pt:$n[0].IAsyncResult,ps:0}],sn:"BlockingEndWrite",rt:$n[0].Void,p:[$n[0].IAsyncResult]},{v:!0,a:2,n:"Close",t:8,sn:"Close",rt:$n[0].Void},{a:2,n:"CopyTo",t:8,pi:[{n:"destination",pt:$n[14].Stream,ps:0}],sn:"CopyTo",rt:$n[0].Void,p:[$n[14].Stream]},{a:2,n:"CopyTo",t:8,pi:[{n:"destination",pt:$n[14].Stream,ps:0},{n:"bufferSize",pt:$n[0].Int32,ps:1}],sn:"CopyTo$1",rt:$n[0].Void,p:[$n[14].Stream,$n[0].Int32]},{a:2,n:"Dispose",t:8,sn:"Dispose",rt:$n[0].Void},{v:!0,a:3,n:"Dispose",t:8,pi:[{n:"disposing",pt:$n[0].Boolean,ps:0}],sn:"Dispose$1",rt:$n[0].Void,p:[$n[0].Boolean]},{v:!0,a:2,n:"EndRead",t:8,pi:[{n:"asyncResult",pt:$n[0].IAsyncResult,ps:0}],sn:"EndRead",rt:$n[0].Int32,p:[$n[0].IAsyncResult],box:function($v){return H5.box($v,System.Int32)}},{v:!0,a:2,n:"EndWrite",t:8,pi:[{n:"asyncResult",pt:$n[0].IAsyncResult,ps:0}],sn:"EndWrite",rt:$n[0].Void,p:[$n[0].IAsyncResult]},{ab:!0,a:2,n:"Flush",t:8,sn:"Flush",rt:$n[0].Void},{a:1,n:"InternalCopyTo",t:8,pi:[{n:"destination",pt:$n[14].Stream,ps:0},{n:"bufferSize",pt:$n[0].Int32,ps:1}],sn:"InternalCopyTo",rt:$n[0].Void,p:[$n[14].Stream,$n[0].Int32]},{ab:!0,a:2,n:"Read",t:8,pi:[{n:"buffer",pt:$n[0].Array.type(System.Byte),ps:0},{n:"offset",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2}],sn:"Read",rt:$n[0].Int32,p:[$n[0].Array.type(System.Byte),$n[0].Int32,$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{v:!0,a:2,n:"ReadByte",t:8,sn:"ReadByte",rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}},{ab:!0,a:2,n:"Seek",t:8,pi:[{n:"offset",pt:$n[0].Int64,ps:0},{n:"origin",pt:$n[14].SeekOrigin,ps:1}],sn:"Seek",rt:$n[0].Int64,p:[$n[0].Int64,$n[14].SeekOrigin]},{ab:!0,a:2,n:"SetLength",t:8,pi:[{n:"value",pt:$n[0].Int64,ps:0}],sn:"SetLength",rt:$n[0].Void,p:[$n[0].Int64]},{a:2,n:"Synchronized",is:!0,t:8,pi:[{n:"stream",pt:$n[14].Stream,ps:0}],sn:"Synchronized",rt:$n[14].Stream,p:[$n[14].Stream]},{ab:!0,a:2,n:"Write",t:8,pi:[{n:"buffer",pt:$n[0].Array.type(System.Byte),ps:0},{n:"offset",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2}],sn:"Write",rt:$n[0].Void,p:[$n[0].Array.type(System.Byte),$n[0].Int32,$n[0].Int32]},{v:!0,a:2,n:"WriteByte",t:8,pi:[{n:"value",pt:$n[0].Byte,ps:0}],sn:"WriteByte",rt:$n[0].Void,p:[$n[0].Byte]},{ab:!0,a:2,n:"CanRead",t:16,rt:$n[0].Boolean,g:{ab:!0,a:2,n:"get_CanRead",t:8,rt:$n[0].Boolean,fg:"CanRead",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},fn:"CanRead"},{ab:!0,a:2,n:"CanSeek",t:16,rt:$n[0].Boolean,g:{ab:!0,a:2,n:"get_CanSeek",t:8,rt:$n[0].Boolean,fg:"CanSeek",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},fn:"CanSeek"},{v:!0,a:2,n:"CanTimeout",t:16,rt:$n[0].Boolean,g:{v:!0,a:2,n:"get_CanTimeout",t:8,rt:$n[0].Boolean,fg:"CanTimeout",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},fn:"CanTimeout"},{ab:!0,a:2,n:"CanWrite",t:16,rt:$n[0].Boolean,g:{ab:!0,a:2,n:"get_CanWrite",t:8,rt:$n[0].Boolean,fg:"CanWrite",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},fn:"CanWrite"},{ab:!0,a:2,n:"Length",t:16,rt:$n[0].Int64,g:{ab:!0,a:2,n:"get_Length",t:8,rt:$n[0].Int64,fg:"Length"},fn:"Length"},{ab:!0,a:2,n:"Position",t:16,rt:$n[0].Int64,g:{ab:!0,a:2,n:"get_Position",t:8,rt:$n[0].Int64,fg:"Position"},s:{ab:!0,a:2,n:"set_Position",t:8,p:[$n[0].Int64],rt:$n[0].Void,fs:"Position"},fn:"Position"},{v:!0,a:2,n:"ReadTimeout",t:16,rt:$n[0].Int32,g:{v:!0,a:2,n:"get_ReadTimeout",t:8,rt:$n[0].Int32,fg:"ReadTimeout",box:function($v){return H5.box($v,System.Int32)}},s:{v:!0,a:2,n:"set_ReadTimeout",t:8,p:[$n[0].Int32],rt:$n[0].Void,fs:"ReadTimeout"},fn:"ReadTimeout"},{v:!0,a:2,n:"WriteTimeout",t:16,rt:$n[0].Int32,g:{v:!0,a:2,n:"get_WriteTimeout",t:8,rt:$n[0].Int32,fg:"WriteTimeout",box:function($v){return H5.box($v,System.Int32)}},s:{v:!0,a:2,n:"set_WriteTimeout",t:8,p:[$n[0].Int32],rt:$n[0].Void,fs:"WriteTimeout"},fn:"WriteTimeout"},{a:2,n:"Null",is:!0,t:4,rt:$n[14].Stream,sn:"Null",ro:!0},{a:1,n:"_DefaultCopyBufferSize",is:!0,t:4,rt:$n[0].Int32,sn:"_DefaultCopyBufferSize",box:function($v){return H5.box($v,System.Int32)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Boolean,sn:"CanRead",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Boolean,sn:"CanSeek",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Boolean,sn:"CanWrite",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Int64,sn:"Length"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Int64,sn:"Position"}]}},$n);$m("System.IO.Stream.NullStream",function(){return{td:$n[14].Stream,att:1057027,a:1,at:[new System.SerializableAttribute],m:[{a:4,n:".ctor",t:1,sn:"ctor"},{ov:!0,a:2,n:"BeginRead",t:8,pi:[{n:"buffer",pt:$n[0].Array.type(System.Byte),ps:0},{n:"offset",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2},{n:"callback",pt:Function,ps:3},{n:"state",pt:$n[0].Object,ps:4}],sn:"BeginRead",rt:$n[0].IAsyncResult,p:[$n[0].Array.type(System.Byte),$n[0].Int32,$n[0].Int32,Function,$n[0].Object]},{ov:!0,a:2,n:"BeginWrite",t:8,pi:[{n:"buffer",pt:$n[0].Array.type(System.Byte),ps:0},{n:"offset",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2},{n:"callback",pt:Function,ps:3},{n:"state",pt:$n[0].Object,ps:4}],sn:"BeginWrite",rt:$n[0].IAsyncResult,p:[$n[0].Array.type(System.Byte),$n[0].Int32,$n[0].Int32,Function,$n[0].Object]},{ov:!0,a:3,n:"Dispose",t:8,pi:[{n:"disposing",pt:$n[0].Boolean,ps:0}],sn:"Dispose$1",rt:$n[0].Void,p:[$n[0].Boolean]},{ov:!0,a:2,n:"EndRead",t:8,pi:[{n:"asyncResult",pt:$n[0].IAsyncResult,ps:0}],sn:"EndRead",rt:$n[0].Int32,p:[$n[0].IAsyncResult],box:function($v){return H5.box($v,System.Int32)}},{ov:!0,a:2,n:"EndWrite",t:8,pi:[{n:"asyncResult",pt:$n[0].IAsyncResult,ps:0}],sn:"EndWrite",rt:$n[0].Void,p:[$n[0].IAsyncResult]},{ov:!0,a:2,n:"Flush",t:8,sn:"Flush",rt:$n[0].Void},{ov:!0,a:2,n:"Read",t:8,pi:[{n:"buffer",pt:$n[0].Array.type(System.Byte),ps:0},{n:"offset",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2}],sn:"Read",rt:$n[0].Int32,p:[$n[0].Array.type(System.Byte),$n[0].Int32,$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{ov:!0,a:2,n:"ReadByte",t:8,sn:"ReadByte",rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}},{ov:!0,a:2,n:"Seek",t:8,pi:[{n:"offset",pt:$n[0].Int64,ps:0},{n:"origin",pt:$n[14].SeekOrigin,ps:1}],sn:"Seek",rt:$n[0].Int64,p:[$n[0].Int64,$n[14].SeekOrigin]},{ov:!0,a:2,n:"SetLength",t:8,pi:[{n:"length",pt:$n[0].Int64,ps:0}],sn:"SetLength",rt:$n[0].Void,p:[$n[0].Int64]},{ov:!0,a:2,n:"Write",t:8,pi:[{n:"buffer",pt:$n[0].Array.type(System.Byte),ps:0},{n:"offset",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2}],sn:"Write",rt:$n[0].Void,p:[$n[0].Array.type(System.Byte),$n[0].Int32,$n[0].Int32]},{ov:!0,a:2,n:"WriteByte",t:8,pi:[{n:"value",pt:$n[0].Byte,ps:0}],sn:"WriteByte",rt:$n[0].Void,p:[$n[0].Byte]},{ov:!0,a:2,n:"CanRead",t:16,rt:$n[0].Boolean,g:{ov:!0,a:2,n:"get_CanRead",t:8,rt:$n[0].Boolean,fg:"CanRead",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},fn:"CanRead"},{ov:!0,a:2,n:"CanSeek",t:16,rt:$n[0].Boolean,g:{ov:!0,a:2,n:"get_CanSeek",t:8,rt:$n[0].Boolean,fg:"CanSeek",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},fn:"CanSeek"},{ov:!0,a:2,n:"CanWrite",t:16,rt:$n[0].Boolean,g:{ov:!0,a:2,n:"get_CanWrite",t:8,rt:$n[0].Boolean,fg:"CanWrite",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},fn:"CanWrite"},{ov:!0,a:2,n:"Length",t:16,rt:$n[0].Int64,g:{ov:!0,a:2,n:"get_Length",t:8,rt:$n[0].Int64,fg:"Length"},fn:"Length"},{ov:!0,a:2,n:"Position",t:16,rt:$n[0].Int64,g:{ov:!0,a:2,n:"get_Position",t:8,rt:$n[0].Int64,fg:"Position"},s:{ov:!0,a:2,n:"set_Position",t:8,p:[$n[0].Int64],rt:$n[0].Void,fs:"Position"},fn:"Position"}]}},$n);$m("System.IO.Stream.SynchronousAsyncResult",function(){return{td:$n[14].Stream,att:1048837,a:4,m:[{a:4,n:".ctor",t:1,p:[$n[0].Object],pi:[{n:"asyncStateObject",pt:$n[0].Object,ps:0}],sn:"$ctor2"},{a:4,n:".ctor",t:1,p:[$n[0].Int32,$n[0].Object],pi:[{n:"bytesRead",pt:$n[0].Int32,ps:0},{n:"asyncStateObject",pt:$n[0].Object,ps:1}],sn:"$ctor1"},{a:4,n:".ctor",t:1,p:[$n[0].Exception,$n[0].Object,$n[0].Boolean],pi:[{n:"ex",pt:$n[0].Exception,ps:0},{n:"asyncStateObject",pt:$n[0].Object,ps:1},{n:"isWrite",pt:$n[0].Boolean,ps:2}],sn:"ctor"},{a:4,n:"EndRead",is:!0,t:8,pi:[{n:"asyncResult",pt:$n[0].IAsyncResult,ps:0}],sn:"EndRead",rt:$n[0].Int32,p:[$n[0].IAsyncResult],box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"EndWrite",is:!0,t:8,pi:[{n:"asyncResult",pt:$n[0].IAsyncResult,ps:0}],sn:"EndWrite",rt:$n[0].Void,p:[$n[0].IAsyncResult]},{a:4,n:"ThrowIfError",t:8,sn:"ThrowIfError",rt:$n[0].Void},{a:2,n:"AsyncState",t:16,rt:$n[0].Object,g:{a:2,n:"get_AsyncState",t:8,rt:$n[0].Object,fg:"AsyncState"},fn:"AsyncState"},{a:2,n:"CompletedSynchronously",t:16,rt:$n[0].Boolean,g:{a:2,n:"get_CompletedSynchronously",t:8,rt:$n[0].Boolean,fg:"CompletedSynchronously",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},fn:"CompletedSynchronously"},{a:2,n:"IsCompleted",t:16,rt:$n[0].Boolean,g:{a:2,n:"get_IsCompleted",t:8,rt:$n[0].Boolean,fg:"IsCompleted",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},fn:"IsCompleted"},{a:1,n:"_bytesRead",t:4,rt:$n[0].Int32,sn:"_bytesRead",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"_endXxxCalled",t:4,rt:$n[0].Boolean,sn:"_endXxxCalled",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"_exceptionInfo",t:4,rt:$n[0].Exception,sn:"_exceptionInfo"},{a:1,n:"_isWrite",t:4,rt:$n[0].Boolean,sn:"_isWrite",ro:!0,box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"_stateObject",t:4,rt:$n[0].Object,sn:"_stateObject",ro:!0}]}},$n);$m("System.IO.StreamReader",function(){return{nested:[$n[14].StreamReader.NullStreamReader],att:1048577,a:2,m:[{a:4,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[14].Stream],pi:[{n:"stream",pt:$n[14].Stream,ps:0}],sn:"$ctor1"},{a:2,n:".ctor",t:1,p:[$n[0].String],pi:[{n:"path",pt:$n[0].String,ps:0}],sn:"$ctor7"},{a:2,n:".ctor",t:1,p:[$n[14].Stream,$n[0].Boolean],pi:[{n:"stream",pt:$n[14].Stream,ps:0},{n:"detectEncodingFromByteOrderMarks",pt:$n[0].Boolean,ps:1}],sn:"$ctor2"},{a:2,n:".ctor",t:1,p:[$n[14].Stream,$n[8].Encoding],pi:[{n:"stream",pt:$n[14].Stream,ps:0},{n:"encoding",pt:$n[8].Encoding,ps:1}],sn:"$ctor3"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[0].Boolean],pi:[{n:"path",pt:$n[0].String,ps:0},{n:"detectEncodingFromByteOrderMarks",pt:$n[0].Boolean,ps:1}],sn:"$ctor8"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[8].Encoding],pi:[{n:"path",pt:$n[0].String,ps:0},{n:"encoding",pt:$n[8].Encoding,ps:1}],sn:"$ctor9"},{a:2,n:".ctor",t:1,p:[$n[14].Stream,$n[8].Encoding,$n[0].Boolean],pi:[{n:"stream",pt:$n[14].Stream,ps:0},{n:"encoding",pt:$n[8].Encoding,ps:1},{n:"detectEncodingFromByteOrderMarks",pt:$n[0].Boolean,ps:2}],sn:"$ctor4"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[8].Encoding,$n[0].Boolean],pi:[{n:"path",pt:$n[0].String,ps:0},{n:"encoding",pt:$n[8].Encoding,ps:1},{n:"detectEncodingFromByteOrderMarks",pt:$n[0].Boolean,ps:2}],sn:"$ctor10"},{a:2,n:".ctor",t:1,p:[$n[14].Stream,$n[8].Encoding,$n[0].Boolean,$n[0].Int32],pi:[{n:"stream",pt:$n[14].Stream,ps:0},{n:"encoding",pt:$n[8].Encoding,ps:1},{n:"detectEncodingFromByteOrderMarks",pt:$n[0].Boolean,ps:2},{n:"bufferSize",pt:$n[0].Int32,ps:3}],sn:"$ctor5"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[8].Encoding,$n[0].Boolean,$n[0].Int32],pi:[{n:"path",pt:$n[0].String,ps:0},{n:"encoding",pt:$n[8].Encoding,ps:1},{n:"detectEncodingFromByteOrderMarks",pt:$n[0].Boolean,ps:2},{n:"bufferSize",pt:$n[0].Int32,ps:3}],sn:"$ctor11"},{a:2,n:".ctor",t:1,p:[$n[14].Stream,$n[8].Encoding,$n[0].Boolean,$n[0].Int32,$n[0].Boolean],pi:[{n:"stream",pt:$n[14].Stream,ps:0},{n:"encoding",pt:$n[8].Encoding,ps:1},{n:"detectEncodingFromByteOrderMarks",pt:$n[0].Boolean,ps:2},{n:"bufferSize",pt:$n[0].Int32,ps:3},{n:"leaveOpen",pt:$n[0].Boolean,ps:4}],sn:"$ctor6"},{a:4,n:".ctor",t:1,p:[$n[0].String,$n[8].Encoding,$n[0].Boolean,$n[0].Int32,$n[0].Boolean],pi:[{n:"path",pt:$n[0].String,ps:0},{n:"encoding",pt:$n[8].Encoding,ps:1},{n:"detectEncodingFromByteOrderMarks",pt:$n[0].Boolean,ps:2},{n:"bufferSize",pt:$n[0].Int32,ps:3},{n:"checkHost",pt:$n[0].Boolean,ps:4}],sn:"$ctor12"},{ov:!0,a:2,n:"Close",t:8,sn:"Close",rt:$n[0].Void},{a:1,n:"CompressBuffer",t:8,pi:[{n:"n",pt:$n[0].Int32,ps:0}],sn:"CompressBuffer",rt:$n[0].Void,p:[$n[0].Int32]},{a:1,n:"DetectEncoding",t:8,sn:"DetectEncoding",rt:$n[0].Void},{a:2,n:"DiscardBufferedData",t:8,sn:"DiscardBufferedData",rt:$n[0].Void},{ov:!0,a:3,n:"Dispose",t:8,pi:[{n:"disposing",pt:$n[0].Boolean,ps:0}],sn:"Dispose$1",rt:$n[0].Void,p:[$n[0].Boolean]},{a:4,n:"Init",t:8,pi:[{n:"stream",pt:$n[14].Stream,ps:0}],sn:"Init",rt:$n[0].Void,p:[$n[14].Stream]},{a:1,n:"Init",t:8,pi:[{n:"stream",pt:$n[14].Stream,ps:0},{n:"encoding",pt:$n[8].Encoding,ps:1},{n:"detectEncodingFromByteOrderMarks",pt:$n[0].Boolean,ps:2},{n:"bufferSize",pt:$n[0].Int32,ps:3},{n:"leaveOpen",pt:$n[0].Boolean,ps:4}],sn:"Init$1",rt:$n[0].Void,p:[$n[14].Stream,$n[8].Encoding,$n[0].Boolean,$n[0].Int32,$n[0].Boolean]},{a:1,n:"IsPreamble",t:8,sn:"IsPreamble",rt:$n[0].Boolean,box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ov:!0,a:2,n:"Peek",t:8,sn:"Peek",rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}},{ov:!0,a:2,n:"Read",t:8,sn:"Read",rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}},{ov:!0,a:2,n:"Read",t:8,pi:[{n:"buffer",pt:$n[0].Array.type(System.Char),ps:0},{n:"index",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2}],sn:"Read$1",rt:$n[0].Int32,p:[$n[0].Array.type(System.Char),$n[0].Int32,$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{ov:!0,a:2,n:"ReadBlock",t:8,pi:[{n:"buffer",pt:$n[0].Array.type(System.Char),ps:0},{n:"index",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2}],sn:"ReadBlock",rt:$n[0].Int32,p:[$n[0].Array.type(System.Char),$n[0].Int32,$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{v:!0,a:4,n:"ReadBuffer",t:8,sn:"ReadBuffer",rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"ReadBuffer",t:8,pi:[{n:"userBuffer",pt:$n[0].Array.type(System.Char),ps:0},{n:"userOffset",pt:$n[0].Int32,ps:1},{n:"desiredChars",pt:$n[0].Int32,ps:2},{n:"readToUserBuffer",out:!0,pt:$n[0].Boolean,ps:3}],sn:"ReadBuffer$1",rt:$n[0].Int32,p:[$n[0].Array.type(System.Char),$n[0].Int32,$n[0].Int32,$n[0].Boolean],box:function($v){return H5.box($v,System.Int32)}},{ov:!0,a:2,n:"ReadLine",t:8,sn:"ReadLine",rt:$n[0].String},{ov:!0,a:2,n:"ReadToEnd",t:8,sn:"ReadToEnd",rt:$n[0].String},{ov:!0,a:2,n:"ReadToEndAsync",t:8,sn:"ReadToEndAsync",rt:$n[10].Task$1(System.String)},{v:!0,a:2,n:"BaseStream",t:16,rt:$n[14].Stream,g:{v:!0,a:2,n:"get_BaseStream",t:8,rt:$n[14].Stream,fg:"BaseStream"},fn:"BaseStream"},{v:!0,a:2,n:"CurrentEncoding",t:16,rt:$n[8].Encoding,g:{v:!0,a:2,n:"get_CurrentEncoding",t:8,rt:$n[8].Encoding,fg:"CurrentEncoding"},fn:"CurrentEncoding"},{a:4,n:"DefaultBufferSize",is:!0,t:16,rt:$n[0].Int32,g:{a:4,n:"get_DefaultBufferSize",t:8,rt:$n[0].Int32,fg:"DefaultBufferSize",is:!0,box:function($v){return H5.box($v,System.Int32)}},fn:"DefaultBufferSize"},{a:2,n:"EndOfStream",t:16,rt:$n[0].Boolean,g:{a:2,n:"get_EndOfStream",t:8,rt:$n[0].Boolean,fg:"EndOfStream",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},fn:"EndOfStream"},{a:4,n:"LeaveOpen",t:16,rt:$n[0].Boolean,g:{a:4,n:"get_LeaveOpen",t:8,rt:$n[0].Boolean,fg:"LeaveOpen",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},fn:"LeaveOpen"},{a:1,n:"DefaultFileStreamBufferSize",is:!0,t:4,rt:$n[0].Int32,sn:"DefaultFileStreamBufferSize",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"MinBufferSize",is:!0,t:4,rt:$n[0].Int32,sn:"MinBufferSize",box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"Null",is:!0,t:4,rt:$n[14].StreamReader,sn:"Null",ro:!0},{a:1,n:"_closable",t:4,rt:$n[0].Boolean,sn:"_closable",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"_detectEncoding",t:4,rt:$n[0].Boolean,sn:"_detectEncoding",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"_isBlocked",t:4,rt:$n[0].Boolean,sn:"_isBlocked",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"_maxCharsPerBuffer",t:4,rt:$n[0].Int32,sn:"_maxCharsPerBuffer",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"byteBuffer",t:4,rt:$n[0].Array.type(System.Byte),sn:"byteBuffer"},{a:1,n:"byteLen",t:4,rt:$n[0].Int32,sn:"byteLen",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"bytePos",t:4,rt:$n[0].Int32,sn:"bytePos",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"charBuffer",t:4,rt:$n[0].Array.type(System.Char),sn:"charBuffer"},{a:1,n:"charLen",t:4,rt:$n[0].Int32,sn:"charLen",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"charPos",t:4,rt:$n[0].Int32,sn:"charPos",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"encoding",t:4,rt:$n[8].Encoding,sn:"encoding"},{a:1,n:"stream",t:4,rt:$n[14].Stream,sn:"stream"}]}},$n);$m("System.IO.StreamReader.NullStreamReader",function(){return{td:$n[14].StreamReader,att:1048579,a:1,m:[{a:4,n:".ctor",t:1,sn:"ctor"},{ov:!0,a:3,n:"Dispose",t:8,pi:[{n:"disposing",pt:$n[0].Boolean,ps:0}],sn:"Dispose$1",rt:$n[0].Void,p:[$n[0].Boolean]},{ov:!0,a:2,n:"Peek",t:8,sn:"Peek",rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}},{ov:!0,a:2,n:"Read",t:8,sn:"Read",rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}},{ov:!0,a:2,n:"Read",t:8,pi:[{n:"buffer",pt:$n[0].Array.type(System.Char),ps:0},{n:"index",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2}],sn:"Read$1",rt:$n[0].Int32,p:[$n[0].Array.type(System.Char),$n[0].Int32,$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{ov:!0,a:4,n:"ReadBuffer",t:8,sn:"ReadBuffer",rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}},{ov:!0,a:2,n:"ReadLine",t:8,sn:"ReadLine",rt:$n[0].String},{ov:!0,a:2,n:"ReadToEnd",t:8,sn:"ReadToEnd",rt:$n[0].String},{ov:!0,a:2,n:"BaseStream",t:16,rt:$n[14].Stream,g:{ov:!0,a:2,n:"get_BaseStream",t:8,rt:$n[14].Stream,fg:"BaseStream"},fn:"BaseStream"},{ov:!0,a:2,n:"CurrentEncoding",t:16,rt:$n[8].Encoding,g:{ov:!0,a:2,n:"get_CurrentEncoding",t:8,rt:$n[8].Encoding,fg:"CurrentEncoding"},fn:"CurrentEncoding"}]}},$n);$m("System.IO.StreamWriter",function(){return{att:1048577,a:2,m:[{a:4,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[14].Stream],pi:[{n:"stream",pt:$n[14].Stream,ps:0}],sn:"$ctor1"},{a:2,n:".ctor",t:1,p:[$n[0].String],pi:[{n:"path",pt:$n[0].String,ps:0}],sn:"$ctor5"},{a:2,n:".ctor",t:1,p:[$n[14].Stream,$n[8].Encoding],pi:[{n:"stream",pt:$n[14].Stream,ps:0},{n:"encoding",pt:$n[8].Encoding,ps:1}],sn:"$ctor2"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[0].Boolean],pi:[{n:"path",pt:$n[0].String,ps:0},{n:"append",pt:$n[0].Boolean,ps:1}],sn:"$ctor6"},{a:2,n:".ctor",t:1,p:[$n[14].Stream,$n[8].Encoding,$n[0].Int32],pi:[{n:"stream",pt:$n[14].Stream,ps:0},{n:"encoding",pt:$n[8].Encoding,ps:1},{n:"bufferSize",pt:$n[0].Int32,ps:2}],sn:"$ctor3"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[0].Boolean,$n[8].Encoding],pi:[{n:"path",pt:$n[0].String,ps:0},{n:"append",pt:$n[0].Boolean,ps:1},{n:"encoding",pt:$n[8].Encoding,ps:2}],sn:"$ctor7"},{a:2,n:".ctor",t:1,p:[$n[14].Stream,$n[8].Encoding,$n[0].Int32,$n[0].Boolean],pi:[{n:"stream",pt:$n[14].Stream,ps:0},{n:"encoding",pt:$n[8].Encoding,ps:1},{n:"bufferSize",pt:$n[0].Int32,ps:2},{n:"leaveOpen",pt:$n[0].Boolean,ps:3}],sn:"$ctor4"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[0].Boolean,$n[8].Encoding,$n[0].Int32],pi:[{n:"path",pt:$n[0].String,ps:0},{n:"append",pt:$n[0].Boolean,ps:1},{n:"encoding",pt:$n[8].Encoding,ps:2},{n:"bufferSize",pt:$n[0].Int32,ps:3}],sn:"$ctor8"},{a:4,n:".ctor",t:1,p:[$n[0].String,$n[0].Boolean,$n[8].Encoding,$n[0].Int32,$n[0].Boolean],pi:[{n:"path",pt:$n[0].String,ps:0},{n:"append",pt:$n[0].Boolean,ps:1},{n:"encoding",pt:$n[8].Encoding,ps:2},{n:"bufferSize",pt:$n[0].Int32,ps:3},{n:"checkHost",pt:$n[0].Boolean,ps:4}],sn:"$ctor9"},{ov:!0,a:2,n:"Close",t:8,sn:"Close",rt:$n[0].Void},{ov:!0,a:3,n:"Dispose",t:8,pi:[{n:"disposing",pt:$n[0].Boolean,ps:0}],sn:"Dispose$1",rt:$n[0].Void,p:[$n[0].Boolean]},{ov:!0,a:2,n:"Flush",t:8,sn:"Flush",rt:$n[0].Void},{a:1,n:"Flush",t:8,pi:[{n:"flushStream",pt:$n[0].Boolean,ps:0},{n:"flushEncoder",pt:$n[0].Boolean,ps:1}],sn:"Flush$1",rt:$n[0].Void,p:[$n[0].Boolean,$n[0].Boolean]},{a:1,n:"Init",t:8,pi:[{n:"streamArg",pt:$n[14].Stream,ps:0},{n:"encodingArg",pt:$n[8].Encoding,ps:1},{n:"bufferSize",pt:$n[0].Int32,ps:2},{n:"shouldLeaveOpen",pt:$n[0].Boolean,ps:3}],sn:"Init",rt:$n[0].Void,p:[$n[14].Stream,$n[8].Encoding,$n[0].Int32,$n[0].Boolean]},{ov:!0,a:2,n:"Write",t:8,pi:[{n:"value",pt:$n[0].Char,ps:0}],sn:"Write$1",rt:$n[0].Void,p:[$n[0].Char]},{ov:!0,a:2,n:"Write",t:8,pi:[{n:"buffer",pt:$n[0].Array.type(System.Char),ps:0}],sn:"Write$2",rt:$n[0].Void,p:[$n[0].Array.type(System.Char)]},{ov:!0,a:2,n:"Write",t:8,pi:[{n:"value",pt:$n[0].String,ps:0}],sn:"Write$10",rt:$n[0].Void,p:[$n[0].String]},{ov:!0,a:2,n:"Write",t:8,pi:[{n:"buffer",pt:$n[0].Array.type(System.Char),ps:0},{n:"index",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2}],sn:"Write$3",rt:$n[0].Void,p:[$n[0].Array.type(System.Char),$n[0].Int32,$n[0].Int32]},{v:!0,a:2,n:"AutoFlush",t:16,rt:$n[0].Boolean,g:{v:!0,a:2,n:"get_AutoFlush",t:8,rt:$n[0].Boolean,fg:"AutoFlush",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},s:{v:!0,a:2,n:"set_AutoFlush",t:8,p:[$n[0].Boolean],rt:$n[0].Void,fs:"AutoFlush"},fn:"AutoFlush"},{v:!0,a:2,n:"BaseStream",t:16,rt:$n[14].Stream,g:{v:!0,a:2,n:"get_BaseStream",t:8,rt:$n[14].Stream,fg:"BaseStream"},fn:"BaseStream"},{ov:!0,a:2,n:"Encoding",t:16,rt:$n[8].Encoding,g:{ov:!0,a:2,n:"get_Encoding",t:8,rt:$n[8].Encoding,fg:"Encoding"},fn:"Encoding"},{a:4,n:"HaveWrittenPreamble",t:16,rt:$n[0].Boolean,s:{a:4,n:"set_HaveWrittenPreamble",t:8,p:[$n[0].Boolean],rt:$n[0].Void,fs:"HaveWrittenPreamble"},fn:"HaveWrittenPreamble"},{a:4,n:"LeaveOpen",t:16,rt:$n[0].Boolean,g:{a:4,n:"get_LeaveOpen",t:8,rt:$n[0].Boolean,fg:"LeaveOpen",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},fn:"LeaveOpen"},{a:4,n:"UTF8NoBOM",is:!0,t:16,rt:$n[8].Encoding,g:{a:4,n:"get_UTF8NoBOM",t:8,rt:$n[8].Encoding,fg:"UTF8NoBOM",is:!0},fn:"UTF8NoBOM"},{a:4,n:"DefaultBufferSize",is:!0,t:4,rt:$n[0].Int32,sn:"DefaultBufferSize",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"DefaultFileStreamBufferSize",is:!0,t:4,rt:$n[0].Int32,sn:"DefaultFileStreamBufferSize",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"MinBufferSize",is:!0,t:4,rt:$n[0].Int32,sn:"MinBufferSize",box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"Null",is:!0,t:4,rt:$n[14].StreamWriter,sn:"Null",ro:!0},{a:1,n:"_UTF8NoBOM",is:!0,t:4,rt:$n[8].Encoding,sn:"_UTF8NoBOM"},{a:1,n:"autoFlush",t:4,rt:$n[0].Boolean,sn:"autoFlush",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"byteBuffer",t:4,rt:$n[0].Array.type(System.Byte),sn:"byteBuffer"},{a:1,n:"charBuffer",t:4,rt:$n[0].Array.type(System.Char),sn:"charBuffer"},{a:1,n:"charLen",t:4,rt:$n[0].Int32,sn:"charLen",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"charPos",t:4,rt:$n[0].Int32,sn:"charPos",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"closable",t:4,rt:$n[0].Boolean,sn:"closable",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"encoding",t:4,rt:$n[8].Encoding,sn:"encoding"},{a:1,n:"haveWrittenPreamble",t:4,rt:$n[0].Boolean,sn:"haveWrittenPreamble",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"stream",t:4,rt:$n[14].Stream,sn:"stream"}]}},$n);$m("System.IO.StringReader",function(){return{att:1048577,a:2,m:[{a:2,n:".ctor",t:1,p:[$n[0].String],pi:[{n:"s",pt:$n[0].String,ps:0}],sn:"ctor"},{ov:!0,a:2,n:"Close",t:8,sn:"Close",rt:$n[0].Void},{ov:!0,a:3,n:"Dispose",t:8,pi:[{n:"disposing",pt:$n[0].Boolean,ps:0}],sn:"Dispose$1",rt:$n[0].Void,p:[$n[0].Boolean]},{ov:!0,a:2,n:"Peek",t:8,sn:"Peek",rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}},{ov:!0,a:2,n:"Read",t:8,sn:"Read",rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}},{ov:!0,a:2,n:"Read",t:8,pi:[{n:"buffer",pt:$n[0].Array.type(System.Char),ps:0},{n:"index",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2}],sn:"Read$1",rt:$n[0].Int32,p:[$n[0].Array.type(System.Char),$n[0].Int32,$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{ov:!0,a:2,n:"ReadLine",t:8,sn:"ReadLine",rt:$n[0].String},{ov:!0,a:2,n:"ReadToEnd",t:8,sn:"ReadToEnd",rt:$n[0].String},{a:1,n:"_length",t:4,rt:$n[0].Int32,sn:"_length",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"_pos",t:4,rt:$n[0].Int32,sn:"_pos",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"_s",t:4,rt:$n[0].String,sn:"_s"}]}},$n);$m("System.IO.StringWriter",function(){return{att:1048577,a:2,m:[{a:2,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].IFormatProvider],pi:[{n:"formatProvider",pt:$n[0].IFormatProvider,ps:0}],sn:"$ctor1"},{a:2,n:".ctor",t:1,p:[$n[8].StringBuilder],pi:[{n:"sb",pt:$n[8].StringBuilder,ps:0}],sn:"$ctor2"},{a:2,n:".ctor",t:1,p:[$n[8].StringBuilder,$n[0].IFormatProvider],pi:[{n:"sb",pt:$n[8].StringBuilder,ps:0},{n:"formatProvider",pt:$n[0].IFormatProvider,ps:1}],sn:"$ctor3"},{ov:!0,a:2,n:"Close",t:8,sn:"Close",rt:$n[0].Void},{ov:!0,a:3,n:"Dispose",t:8,pi:[{n:"disposing",pt:$n[0].Boolean,ps:0}],sn:"Dispose$1",rt:$n[0].Void,p:[$n[0].Boolean]},{v:!0,a:2,n:"GetStringBuilder",t:8,sn:"GetStringBuilder",rt:$n[8].StringBuilder},{ov:!0,a:2,n:"ToString",t:8,sn:"toString",rt:$n[0].String},{ov:!0,a:2,n:"Write",t:8,pi:[{n:"value",pt:$n[0].Char,ps:0}],sn:"Write$1",rt:$n[0].Void,p:[$n[0].Char]},{ov:!0,a:2,n:"Write",t:8,pi:[{n:"value",pt:$n[0].String,ps:0}],sn:"Write$10",rt:$n[0].Void,p:[$n[0].String]},{ov:!0,a:2,n:"Write",t:8,pi:[{n:"buffer",pt:$n[0].Array.type(System.Char),ps:0},{n:"index",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2}],sn:"Write$3",rt:$n[0].Void,p:[$n[0].Array.type(System.Char),$n[0].Int32,$n[0].Int32]},{ov:!0,a:2,n:"Encoding",t:16,rt:$n[8].Encoding,g:{ov:!0,a:2,n:"get_Encoding",t:8,rt:$n[8].Encoding,fg:"Encoding"},fn:"Encoding"},{a:1,n:"_isOpen",t:4,rt:$n[0].Boolean,sn:"_isOpen",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"_sb",t:4,rt:$n[8].StringBuilder,sn:"_sb"},{a:1,n:"m_encoding",is:!0,t:4,rt:$n[8].UnicodeEncoding,sn:"m_encoding"}]}},$n);$m("System.IO.TextReader",function(){return{nested:[$n[14].TextReader.NullTextReader],att:1048705,a:2,m:[{a:3,n:".ctor",t:1,sn:"ctor"},{v:!0,a:2,n:"Close",t:8,sn:"Close",rt:$n[0].Void},{a:2,n:"Dispose",t:8,sn:"Dispose",rt:$n[0].Void},{v:!0,a:3,n:"Dispose",t:8,pi:[{n:"disposing",pt:$n[0].Boolean,ps:0}],sn:"Dispose$1",rt:$n[0].Void,p:[$n[0].Boolean]},{v:!0,a:2,n:"Peek",t:8,sn:"Peek",rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}},{v:!0,a:2,n:"Read",t:8,sn:"Read",rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}},{v:!0,a:2,n:"Read",t:8,pi:[{n:"buffer",pt:$n[0].Array.type(System.Char),ps:0},{n:"index",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2}],sn:"Read$1",rt:$n[0].Int32,p:[$n[0].Array.type(System.Char),$n[0].Int32,$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{v:!0,a:2,n:"ReadBlock",t:8,pi:[{n:"buffer",pt:$n[0].Array.type(System.Char),ps:0},{n:"index",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2}],sn:"ReadBlock",rt:$n[0].Int32,p:[$n[0].Array.type(System.Char),$n[0].Int32,$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{v:!0,a:2,n:"ReadLine",t:8,sn:"ReadLine",rt:$n[0].String},{v:!0,a:2,n:"ReadToEnd",t:8,sn:"ReadToEnd",rt:$n[0].String},{v:!0,a:2,n:"ReadToEndAsync",t:8,sn:"ReadToEndAsync",rt:$n[10].Task$1(System.String)},{a:2,n:"Synchronized",is:!0,t:8,pi:[{n:"reader",pt:$n[14].TextReader,ps:0}],sn:"Synchronized",rt:$n[14].TextReader,p:[$n[14].TextReader]},{a:2,n:"Null",is:!0,t:4,rt:$n[14].TextReader,sn:"Null",ro:!0}]}},$n);$m("System.IO.TextReader.NullTextReader",function(){return{td:$n[14].TextReader,att:1057027,a:1,at:[new System.SerializableAttribute],m:[{a:2,n:".ctor",t:1,sn:"ctor"},{ov:!0,a:2,n:"Read",t:8,pi:[{n:"buffer",pt:$n[0].Array.type(System.Char),ps:0},{n:"index",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2}],sn:"Read$1",rt:$n[0].Int32,p:[$n[0].Array.type(System.Char),$n[0].Int32,$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{ov:!0,a:2,n:"ReadLine",t:8,sn:"ReadLine",rt:$n[0].String}]}},$n);$m("System.IO.TextWriter",function(){return{nested:[$n[14].TextWriter.NullTextWriter],att:1048705,a:2,m:[{a:3,n:".ctor",t:1,sn:"ctor"},{a:3,n:".ctor",t:1,p:[$n[0].IFormatProvider],pi:[{n:"formatProvider",pt:$n[0].IFormatProvider,ps:0}],sn:"$ctor1"},{v:!0,a:2,n:"Close",t:8,sn:"Close",rt:$n[0].Void},{a:2,n:"Dispose",t:8,sn:"Dispose",rt:$n[0].Void},{v:!0,a:3,n:"Dispose",t:8,pi:[{n:"disposing",pt:$n[0].Boolean,ps:0}],sn:"Dispose$1",rt:$n[0].Void,p:[$n[0].Boolean]},{v:!0,a:2,n:"Flush",t:8,sn:"Flush",rt:$n[0].Void},{a:2,n:"Synchronized",is:!0,t:8,pi:[{n:"writer",pt:$n[14].TextWriter,ps:0}],sn:"Synchronized",rt:$n[14].TextWriter,p:[$n[14].TextWriter]},{v:!0,a:2,n:"Write",t:8,pi:[{n:"value",pt:$n[0].Boolean,ps:0}],sn:"Write",rt:$n[0].Void,p:[$n[0].Boolean]},{v:!0,a:2,n:"Write",t:8,pi:[{n:"value",pt:$n[0].Char,ps:0}],sn:"Write$1",rt:$n[0].Void,p:[$n[0].Char]},{v:!0,a:2,n:"Write",t:8,pi:[{n:"buffer",pt:$n[0].Array.type(System.Char),ps:0}],sn:"Write$2",rt:$n[0].Void,p:[$n[0].Array.type(System.Char)]},{v:!0,a:2,n:"Write",t:8,pi:[{n:"value",pt:$n[0].Decimal,ps:0}],sn:"Write$4",rt:$n[0].Void,p:[$n[0].Decimal]},{v:!0,a:2,n:"Write",t:8,pi:[{n:"value",pt:$n[0].Double,ps:0}],sn:"Write$5",rt:$n[0].Void,p:[$n[0].Double]},{v:!0,a:2,n:"Write",t:8,pi:[{n:"value",pt:$n[0].Int32,ps:0}],sn:"Write$6",rt:$n[0].Void,p:[$n[0].Int32]},{v:!0,a:2,n:"Write",t:8,pi:[{n:"value",pt:$n[0].Int64,ps:0}],sn:"Write$7",rt:$n[0].Void,p:[$n[0].Int64]},{v:!0,a:2,n:"Write",t:8,pi:[{n:"value",pt:$n[0].Object,ps:0}],sn:"Write$8",rt:$n[0].Void,p:[$n[0].Object]},{v:!0,a:2,n:"Write",t:8,pi:[{n:"value",pt:$n[0].Single,ps:0}],sn:"Write$9",rt:$n[0].Void,p:[$n[0].Single]},{v:!0,a:2,n:"Write",t:8,pi:[{n:"value",pt:$n[0].String,ps:0}],sn:"Write$10",rt:$n[0].Void,p:[$n[0].String]},{v:!0,a:2,n:"Write",t:8,pi:[{n:"value",pt:$n[0].UInt32,ps:0}],sn:"Write$15",rt:$n[0].Void,p:[$n[0].UInt32]},{v:!0,a:2,n:"Write",t:8,pi:[{n:"value",pt:$n[0].UInt64,ps:0}],sn:"Write$16",rt:$n[0].Void,p:[$n[0].UInt64]},{v:!0,a:2,n:"Write",t:8,pi:[{n:"format",pt:$n[0].String,ps:0},{n:"arg0",pt:$n[0].Object,ps:1}],sn:"Write$11",rt:$n[0].Void,p:[$n[0].String,$n[0].Object]},{v:!0,a:2,n:"Write",t:8,pi:[{n:"format",pt:$n[0].String,ps:0},{n:"arg",ip:!0,pt:$n[0].Array.type(System.Object),ps:1}],sn:"Write$14",rt:$n[0].Void,p:[$n[0].String,$n[0].Array.type(System.Object)]},{v:!0,a:2,n:"Write",t:8,pi:[{n:"buffer",pt:$n[0].Array.type(System.Char),ps:0},{n:"index",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2}],sn:"Write$3",rt:$n[0].Void,p:[$n[0].Array.type(System.Char),$n[0].Int32,$n[0].Int32]},{v:!0,a:2,n:"Write",t:8,pi:[{n:"format",pt:$n[0].String,ps:0},{n:"arg0",pt:$n[0].Object,ps:1},{n:"arg1",pt:$n[0].Object,ps:2}],sn:"Write$12",rt:$n[0].Void,p:[$n[0].String,$n[0].Object,$n[0].Object]},{v:!0,a:2,n:"Write",t:8,pi:[{n:"format",pt:$n[0].String,ps:0},{n:"arg0",pt:$n[0].Object,ps:1},{n:"arg1",pt:$n[0].Object,ps:2},{n:"arg2",pt:$n[0].Object,ps:3}],sn:"Write$13",rt:$n[0].Void,p:[$n[0].String,$n[0].Object,$n[0].Object,$n[0].Object]},{v:!0,a:2,n:"WriteLine",t:8,sn:"WriteLine",rt:$n[0].Void},{v:!0,a:2,n:"WriteLine",t:8,pi:[{n:"value",pt:$n[0].Boolean,ps:0}],sn:"WriteLine$1",rt:$n[0].Void,p:[$n[0].Boolean]},{v:!0,a:2,n:"WriteLine",t:8,pi:[{n:"value",pt:$n[0].Char,ps:0}],sn:"WriteLine$2",rt:$n[0].Void,p:[$n[0].Char]},{v:!0,a:2,n:"WriteLine",t:8,pi:[{n:"buffer",pt:$n[0].Array.type(System.Char),ps:0}],sn:"WriteLine$3",rt:$n[0].Void,p:[$n[0].Array.type(System.Char)]},{v:!0,a:2,n:"WriteLine",t:8,pi:[{n:"value",pt:$n[0].Decimal,ps:0}],sn:"WriteLine$5",rt:$n[0].Void,p:[$n[0].Decimal]},{v:!0,a:2,n:"WriteLine",t:8,pi:[{n:"value",pt:$n[0].Double,ps:0}],sn:"WriteLine$6",rt:$n[0].Void,p:[$n[0].Double]},{v:!0,a:2,n:"WriteLine",t:8,pi:[{n:"value",pt:$n[0].Int32,ps:0}],sn:"WriteLine$7",rt:$n[0].Void,p:[$n[0].Int32]},{v:!0,a:2,n:"WriteLine",t:8,pi:[{n:"value",pt:$n[0].Int64,ps:0}],sn:"WriteLine$8",rt:$n[0].Void,p:[$n[0].Int64]},{v:!0,a:2,n:"WriteLine",t:8,pi:[{n:"value",pt:$n[0].Object,ps:0}],sn:"WriteLine$9",rt:$n[0].Void,p:[$n[0].Object]},{v:!0,a:2,n:"WriteLine",t:8,pi:[{n:"value",pt:$n[0].Single,ps:0}],sn:"WriteLine$10",rt:$n[0].Void,p:[$n[0].Single]},{v:!0,a:2,n:"WriteLine",t:8,pi:[{n:"value",pt:$n[0].String,ps:0}],sn:"WriteLine$11",rt:$n[0].Void,p:[$n[0].String]},{v:!0,a:2,n:"WriteLine",t:8,pi:[{n:"value",pt:$n[0].UInt32,ps:0}],sn:"WriteLine$16",rt:$n[0].Void,p:[$n[0].UInt32]},{v:!0,a:2,n:"WriteLine",t:8,pi:[{n:"value",pt:$n[0].UInt64,ps:0}],sn:"WriteLine$17",rt:$n[0].Void,p:[$n[0].UInt64]},{v:!0,a:2,n:"WriteLine",t:8,pi:[{n:"format",pt:$n[0].String,ps:0},{n:"arg0",pt:$n[0].Object,ps:1}],sn:"WriteLine$12",rt:$n[0].Void,p:[$n[0].String,$n[0].Object]},{v:!0,a:2,n:"WriteLine",t:8,pi:[{n:"format",pt:$n[0].String,ps:0},{n:"arg",ip:!0,pt:$n[0].Array.type(System.Object),ps:1}],sn:"WriteLine$15",rt:$n[0].Void,p:[$n[0].String,$n[0].Array.type(System.Object)]},{v:!0,a:2,n:"WriteLine",t:8,pi:[{n:"buffer",pt:$n[0].Array.type(System.Char),ps:0},{n:"index",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2}],sn:"WriteLine$4",rt:$n[0].Void,p:[$n[0].Array.type(System.Char),$n[0].Int32,$n[0].Int32]},{v:!0,a:2,n:"WriteLine",t:8,pi:[{n:"format",pt:$n[0].String,ps:0},{n:"arg0",pt:$n[0].Object,ps:1},{n:"arg1",pt:$n[0].Object,ps:2}],sn:"WriteLine$13",rt:$n[0].Void,p:[$n[0].String,$n[0].Object,$n[0].Object]},{v:!0,a:2,n:"WriteLine",t:8,pi:[{n:"format",pt:$n[0].String,ps:0},{n:"arg0",pt:$n[0].Object,ps:1},{n:"arg1",pt:$n[0].Object,ps:2},{n:"arg2",pt:$n[0].Object,ps:3}],sn:"WriteLine$14",rt:$n[0].Void,p:[$n[0].String,$n[0].Object,$n[0].Object,$n[0].Object]},{ab:!0,a:2,n:"Encoding",t:16,rt:$n[8].Encoding,g:{ab:!0,a:2,n:"get_Encoding",t:8,rt:$n[8].Encoding,fg:"Encoding"},fn:"Encoding"},{v:!0,a:2,n:"FormatProvider",t:16,rt:$n[0].IFormatProvider,g:{v:!0,a:2,n:"get_FormatProvider",t:8,rt:$n[0].IFormatProvider,fg:"FormatProvider"},fn:"FormatProvider"},{v:!0,a:2,n:"NewLine",t:16,rt:$n[0].String,g:{v:!0,a:2,n:"get_NewLine",t:8,rt:$n[0].String,fg:"NewLine"},s:{v:!0,a:2,n:"set_NewLine",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"NewLine"},fn:"NewLine"},{a:3,n:"CoreNewLine",t:4,rt:$n[0].Array.type(System.Char),sn:"CoreNewLine"},{a:1,n:"InitialNewLine",is:!0,t:4,rt:$n[0].String,sn:"InitialNewLine"},{a:1,n:"InternalFormatProvider",t:4,rt:$n[0].IFormatProvider,sn:"InternalFormatProvider"},{a:2,n:"Null",is:!0,t:4,rt:$n[14].TextWriter,sn:"Null",ro:!0},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[8].Encoding,sn:"Encoding"}]}},$n);$m("System.IO.TextWriter.NullTextWriter",function(){return{td:$n[14].TextWriter,att:1057027,a:1,at:[new System.SerializableAttribute],m:[{a:4,n:".ctor",t:1,sn:"ctor"},{ov:!0,a:2,n:"Write",t:8,pi:[{n:"value",pt:$n[0].String,ps:0}],sn:"Write$10",rt:$n[0].Void,p:[$n[0].String]},{ov:!0,a:2,n:"Write",t:8,pi:[{n:"buffer",pt:$n[0].Array.type(System.Char),ps:0},{n:"index",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2}],sn:"Write$3",rt:$n[0].Void,p:[$n[0].Array.type(System.Char),$n[0].Int32,$n[0].Int32]},{ov:!0,a:2,n:"WriteLine",t:8,sn:"WriteLine",rt:$n[0].Void},{ov:!0,a:2,n:"WriteLine",t:8,pi:[{n:"value",pt:$n[0].Object,ps:0}],sn:"WriteLine$9",rt:$n[0].Void,p:[$n[0].Object]},{ov:!0,a:2,n:"WriteLine",t:8,pi:[{n:"value",pt:$n[0].String,ps:0}],sn:"WriteLine$11",rt:$n[0].Void,p:[$n[0].String]},{ov:!0,a:2,n:"Encoding",t:16,rt:$n[8].Encoding,g:{ov:!0,a:2,n:"get_Encoding",t:8,rt:$n[8].Encoding,fg:"Encoding"},fn:"Encoding"}]}},$n);$m("System.IO.__Error",function(){return{att:1048960,a:4,s:!0,m:[{a:4,n:"EndOfFile",is:!0,t:8,sn:"EndOfFile",rt:$n[0].Void},{a:4,n:"EndReadCalledTwice",is:!0,t:8,sn:"EndReadCalledTwice",rt:$n[0].Void},{a:4,n:"EndWriteCalledTwice",is:!0,t:8,sn:"EndWriteCalledTwice",rt:$n[0].Void},{a:4,n:"FileNotOpen",is:!0,t:8,sn:"FileNotOpen",rt:$n[0].Void},{a:4,n:"MemoryStreamNotExpandable",is:!0,t:8,sn:"MemoryStreamNotExpandable",rt:$n[0].Void},{a:4,n:"ReadNotSupported",is:!0,t:8,sn:"ReadNotSupported",rt:$n[0].Void},{a:4,n:"ReaderClosed",is:!0,t:8,sn:"ReaderClosed",rt:$n[0].Void},{a:4,n:"SeekNotSupported",is:!0,t:8,sn:"SeekNotSupported",rt:$n[0].Void},{a:4,n:"StreamIsClosed",is:!0,t:8,sn:"StreamIsClosed",rt:$n[0].Void},{a:4,n:"WriteNotSupported",is:!0,t:8,sn:"WriteNotSupported",rt:$n[0].Void},{a:4,n:"WriterClosed",is:!0,t:8,sn:"WriterClosed",rt:$n[0].Void},{a:4,n:"WrongAsyncResult",is:!0,t:8,sn:"WrongAsyncResult",rt:$n[0].Void}]}},$n);$m("System.IO.FileStream",function(){return{att:1048577,a:2,m:[{a:4,n:".ctor",t:1,p:[$n[0].Array.type(System.Byte),$n[0].String],pi:[{n:"buffer",pt:$n[0].Array.type(System.Byte),ps:0},{n:"name",pt:$n[0].String,ps:1}],sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[14].FileMode],pi:[{n:"path",pt:$n[0].String,ps:0},{n:"mode",pt:$n[14].FileMode,ps:1}],sn:"$ctor1"},{a:4,n:"EnsureBufferAsync",t:8,sn:"EnsureBufferAsync",rt:$n[10].Task},{ov:!0,a:2,n:"Flush",t:8,sn:"Flush",rt:$n[0].Void},{a:4,n:"FromFile",is:!0,t:8,pi:[{n:"file",pt:$n[0].Object,ps:0}],sn:"FromFile",rt:$n[10].Task$1(System.IO.FileStream),p:[$n[0].Object]},{a:1,n:"GetInternalBuffer",t:8,sn:"GetInternalBuffer",rt:$n[0].Array.type(System.Byte)},{ov:!0,a:2,n:"Read",t:8,pi:[{n:"buffer",pt:$n[0].Array.type(System.Byte),ps:0},{n:"offset",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2}],sn:"Read",rt:$n[0].Int32,p:[$n[0].Array.type(System.Byte),$n[0].Int32,$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"ReadBytes",is:!0,t:8,pi:[{n:"path",pt:$n[0].String,ps:0}],sn:"ReadBytes",rt:$n[0].Array.type(System.Byte),p:[$n[0].String]},{a:4,n:"ReadBytesAsync",is:!0,t:8,pi:[{n:"path",pt:$n[0].String,ps:0}],sn:"ReadBytesAsync",rt:$n[10].Task$1(System.Array.type(System.Byte)),p:[$n[0].String]},{ov:!0,a:2,n:"Seek",t:8,pi:[{n:"offset",pt:$n[0].Int64,ps:0},{n:"origin",pt:$n[14].SeekOrigin,ps:1}],sn:"Seek",rt:$n[0].Int64,p:[$n[0].Int64,$n[14].SeekOrigin]},{ov:!0,a:2,n:"SetLength",t:8,pi:[{n:"value",pt:$n[0].Int64,ps:0}],sn:"SetLength",rt:$n[0].Void,p:[$n[0].Int64]},{ov:!0,a:2,n:"Write",t:8,pi:[{n:"buffer",pt:$n[0].Array.type(System.Byte),ps:0},{n:"offset",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2}],sn:"Write",rt:$n[0].Void,p:[$n[0].Array.type(System.Byte),$n[0].Int32,$n[0].Int32]},{ov:!0,a:2,n:"CanRead",t:16,rt:$n[0].Boolean,g:{ov:!0,a:2,n:"get_CanRead",t:8,rt:$n[0].Boolean,fg:"CanRead",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},fn:"CanRead"},{ov:!0,a:2,n:"CanSeek",t:16,rt:$n[0].Boolean,g:{ov:!0,a:2,n:"get_CanSeek",t:8,rt:$n[0].Boolean,fg:"CanSeek",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},fn:"CanSeek"},{ov:!0,a:2,n:"CanWrite",t:16,rt:$n[0].Boolean,g:{ov:!0,a:2,n:"get_CanWrite",t:8,rt:$n[0].Boolean,fg:"CanWrite",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},fn:"CanWrite"},{v:!0,a:2,n:"IsAsync",t:16,rt:$n[0].Boolean,g:{v:!0,a:2,n:"get_IsAsync",t:8,rt:$n[0].Boolean,fg:"IsAsync",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},fn:"IsAsync"},{ov:!0,a:2,n:"Length",t:16,rt:$n[0].Int64,g:{ov:!0,a:2,n:"get_Length",t:8,rt:$n[0].Int64,fg:"Length"},fn:"Length"},{a:2,n:"Name",t:16,rt:$n[0].String,g:{a:2,n:"get_Name",t:8,rt:$n[0].String,fg:"Name"},fn:"Name"},{ov:!0,a:2,n:"Position",t:16,rt:$n[0].Int64,g:{ov:!0,a:2,n:"get_Position",t:8,rt:$n[0].Int64,fg:"Position"},s:{ov:!0,a:2,n:"set_Position",t:8,p:[$n[0].Int64],rt:$n[0].Void,fs:"Position"},fn:"Position"},{a:1,n:"_buffer",t:4,rt:$n[0].Array.type(System.Byte),sn:"_buffer"},{a:1,n:"name",t:4,rt:$n[0].String,sn:"name"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Int64,sn:"Position"}]}},$n);$m("System.Globalization.BidiCategory",function(){return{att:256,a:4,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:"ArabicNumber",is:!0,t:4,rt:$n[1].BidiCategory,sn:"ArabicNumber",box:function($v){return H5.box($v,System.Globalization.BidiCategory,System.Enum.toStringFn(System.Globalization.BidiCategory))}},{a:2,n:"BoundaryNeutral",is:!0,t:4,rt:$n[1].BidiCategory,sn:"BoundaryNeutral",box:function($v){return H5.box($v,System.Globalization.BidiCategory,System.Enum.toStringFn(System.Globalization.BidiCategory))}},{a:2,n:"CommonNumberSeparator",is:!0,t:4,rt:$n[1].BidiCategory,sn:"CommonNumberSeparator",box:function($v){return H5.box($v,System.Globalization.BidiCategory,System.Enum.toStringFn(System.Globalization.BidiCategory))}},{a:2,n:"EuropeanNumber",is:!0,t:4,rt:$n[1].BidiCategory,sn:"EuropeanNumber",box:function($v){return H5.box($v,System.Globalization.BidiCategory,System.Enum.toStringFn(System.Globalization.BidiCategory))}},{a:2,n:"EuropeanNumberSeparator",is:!0,t:4,rt:$n[1].BidiCategory,sn:"EuropeanNumberSeparator",box:function($v){return H5.box($v,System.Globalization.BidiCategory,System.Enum.toStringFn(System.Globalization.BidiCategory))}},{a:2,n:"EuropeanNumberTerminator",is:!0,t:4,rt:$n[1].BidiCategory,sn:"EuropeanNumberTerminator",box:function($v){return H5.box($v,System.Globalization.BidiCategory,System.Enum.toStringFn(System.Globalization.BidiCategory))}},{a:2,n:"FirstStrongIsolate",is:!0,t:4,rt:$n[1].BidiCategory,sn:"FirstStrongIsolate",box:function($v){return H5.box($v,System.Globalization.BidiCategory,System.Enum.toStringFn(System.Globalization.BidiCategory))}},{a:2,n:"LeftToRight",is:!0,t:4,rt:$n[1].BidiCategory,sn:"LeftToRight",box:function($v){return H5.box($v,System.Globalization.BidiCategory,System.Enum.toStringFn(System.Globalization.BidiCategory))}},{a:2,n:"LeftToRightEmbedding",is:!0,t:4,rt:$n[1].BidiCategory,sn:"LeftToRightEmbedding",box:function($v){return H5.box($v,System.Globalization.BidiCategory,System.Enum.toStringFn(System.Globalization.BidiCategory))}},{a:2,n:"LeftToRightIsolate",is:!0,t:4,rt:$n[1].BidiCategory,sn:"LeftToRightIsolate",box:function($v){return H5.box($v,System.Globalization.BidiCategory,System.Enum.toStringFn(System.Globalization.BidiCategory))}},{a:2,n:"LeftToRightOverride",is:!0,t:4,rt:$n[1].BidiCategory,sn:"LeftToRightOverride",box:function($v){return H5.box($v,System.Globalization.BidiCategory,System.Enum.toStringFn(System.Globalization.BidiCategory))}},{a:2,n:"NonSpacingMark",is:!0,t:4,rt:$n[1].BidiCategory,sn:"NonSpacingMark",box:function($v){return H5.box($v,System.Globalization.BidiCategory,System.Enum.toStringFn(System.Globalization.BidiCategory))}},{a:2,n:"OtherNeutrals",is:!0,t:4,rt:$n[1].BidiCategory,sn:"OtherNeutrals",box:function($v){return H5.box($v,System.Globalization.BidiCategory,System.Enum.toStringFn(System.Globalization.BidiCategory))}},{a:2,n:"ParagraphSeparator",is:!0,t:4,rt:$n[1].BidiCategory,sn:"ParagraphSeparator",box:function($v){return H5.box($v,System.Globalization.BidiCategory,System.Enum.toStringFn(System.Globalization.BidiCategory))}},{a:2,n:"PopDirectionIsolate",is:!0,t:4,rt:$n[1].BidiCategory,sn:"PopDirectionIsolate",box:function($v){return H5.box($v,System.Globalization.BidiCategory,System.Enum.toStringFn(System.Globalization.BidiCategory))}},{a:2,n:"PopDirectionalFormat",is:!0,t:4,rt:$n[1].BidiCategory,sn:"PopDirectionalFormat",box:function($v){return H5.box($v,System.Globalization.BidiCategory,System.Enum.toStringFn(System.Globalization.BidiCategory))}},{a:2,n:"RightToLeft",is:!0,t:4,rt:$n[1].BidiCategory,sn:"RightToLeft",box:function($v){return H5.box($v,System.Globalization.BidiCategory,System.Enum.toStringFn(System.Globalization.BidiCategory))}},{a:2,n:"RightToLeftArabic",is:!0,t:4,rt:$n[1].BidiCategory,sn:"RightToLeftArabic",box:function($v){return H5.box($v,System.Globalization.BidiCategory,System.Enum.toStringFn(System.Globalization.BidiCategory))}},{a:2,n:"RightToLeftEmbedding",is:!0,t:4,rt:$n[1].BidiCategory,sn:"RightToLeftEmbedding",box:function($v){return H5.box($v,System.Globalization.BidiCategory,System.Enum.toStringFn(System.Globalization.BidiCategory))}},{a:2,n:"RightToLeftIsolate",is:!0,t:4,rt:$n[1].BidiCategory,sn:"RightToLeftIsolate",box:function($v){return H5.box($v,System.Globalization.BidiCategory,System.Enum.toStringFn(System.Globalization.BidiCategory))}},{a:2,n:"RightToLeftOverride",is:!0,t:4,rt:$n[1].BidiCategory,sn:"RightToLeftOverride",box:function($v){return H5.box($v,System.Globalization.BidiCategory,System.Enum.toStringFn(System.Globalization.BidiCategory))}},{a:2,n:"SegmentSeparator",is:!0,t:4,rt:$n[1].BidiCategory,sn:"SegmentSeparator",box:function($v){return H5.box($v,System.Globalization.BidiCategory,System.Enum.toStringFn(System.Globalization.BidiCategory))}},{a:2,n:"Whitespace",is:!0,t:4,rt:$n[1].BidiCategory,sn:"Whitespace",box:function($v){return H5.box($v,System.Globalization.BidiCategory,System.Enum.toStringFn(System.Globalization.BidiCategory))}}]}},$n);$m("System.Globalization.Calendar",function(){return{att:1048705,a:2,m:[{a:3,n:".ctor",t:1,sn:"ctor"},{a:4,n:"Add",t:8,pi:[{n:"time",pt:$n[0].DateTime,ps:0},{n:"value",pt:$n[0].Double,ps:1},{n:"scale",pt:$n[0].Int32,ps:2}],sn:"Add",rt:$n[0].DateTime,p:[$n[0].DateTime,$n[0].Double,$n[0].Int32],box:function($v){return H5.box($v,System.DateTime,System.DateTime.format)}},{v:!0,a:2,n:"AddDays",t:8,pi:[{n:"time",pt:$n[0].DateTime,ps:0},{n:"days",pt:$n[0].Int32,ps:1}],sn:"AddDays",rt:$n[0].DateTime,p:[$n[0].DateTime,$n[0].Int32],box:function($v){return H5.box($v,System.DateTime,System.DateTime.format)}},{v:!0,a:2,n:"AddHours",t:8,pi:[{n:"time",pt:$n[0].DateTime,ps:0},{n:"hours",pt:$n[0].Int32,ps:1}],sn:"AddHours",rt:$n[0].DateTime,p:[$n[0].DateTime,$n[0].Int32],box:function($v){return H5.box($v,System.DateTime,System.DateTime.format)}},{v:!0,a:2,n:"AddMilliseconds",t:8,pi:[{n:"time",pt:$n[0].DateTime,ps:0},{n:"milliseconds",pt:$n[0].Double,ps:1}],sn:"AddMilliseconds",rt:$n[0].DateTime,p:[$n[0].DateTime,$n[0].Double],box:function($v){return H5.box($v,System.DateTime,System.DateTime.format)}},{v:!0,a:2,n:"AddMinutes",t:8,pi:[{n:"time",pt:$n[0].DateTime,ps:0},{n:"minutes",pt:$n[0].Int32,ps:1}],sn:"AddMinutes",rt:$n[0].DateTime,p:[$n[0].DateTime,$n[0].Int32],box:function($v){return H5.box($v,System.DateTime,System.DateTime.format)}},{ab:!0,a:2,n:"AddMonths",t:8,pi:[{n:"time",pt:$n[0].DateTime,ps:0},{n:"months",pt:$n[0].Int32,ps:1}],sn:"AddMonths",rt:$n[0].DateTime,p:[$n[0].DateTime,$n[0].Int32],box:function($v){return H5.box($v,System.DateTime,System.DateTime.format)}},{v:!0,a:2,n:"AddSeconds",t:8,pi:[{n:"time",pt:$n[0].DateTime,ps:0},{n:"seconds",pt:$n[0].Int32,ps:1}],sn:"AddSeconds",rt:$n[0].DateTime,p:[$n[0].DateTime,$n[0].Int32],box:function($v){return H5.box($v,System.DateTime,System.DateTime.format)}},{v:!0,a:2,n:"AddWeeks",t:8,pi:[{n:"time",pt:$n[0].DateTime,ps:0},{n:"weeks",pt:$n[0].Int32,ps:1}],sn:"AddWeeks",rt:$n[0].DateTime,p:[$n[0].DateTime,$n[0].Int32],box:function($v){return H5.box($v,System.DateTime,System.DateTime.format)}},{ab:!0,a:2,n:"AddYears",t:8,pi:[{n:"time",pt:$n[0].DateTime,ps:0},{n:"years",pt:$n[0].Int32,ps:1}],sn:"AddYears",rt:$n[0].DateTime,p:[$n[0].DateTime,$n[0].Int32],box:function($v){return H5.box($v,System.DateTime,System.DateTime.format)}},{a:4,n:"CheckAddResult",is:!0,t:8,pi:[{n:"ticks",pt:$n[0].Int64,ps:0},{n:"minValue",pt:$n[0].DateTime,ps:1},{n:"maxValue",pt:$n[0].DateTime,ps:2}],sn:"CheckAddResult",rt:$n[0].Void,p:[$n[0].Int64,$n[0].DateTime,$n[0].DateTime]},{v:!0,a:2,n:"Clone",t:8,sn:"clone",rt:$n[0].Object},{ab:!0,a:2,n:"GetDayOfMonth",t:8,pi:[{n:"time",pt:$n[0].DateTime,ps:0}],sn:"GetDayOfMonth",rt:$n[0].Int32,p:[$n[0].DateTime],box:function($v){return H5.box($v,System.Int32)}},{ab:!0,a:2,n:"GetDayOfWeek",t:8,pi:[{n:"time",pt:$n[0].DateTime,ps:0}],sn:"GetDayOfWeek",rt:$n[0].DayOfWeek,p:[$n[0].DateTime],box:function($v){return H5.box($v,System.DayOfWeek,System.Enum.toStringFn(System.DayOfWeek))}},{ab:!0,a:2,n:"GetDayOfYear",t:8,pi:[{n:"time",pt:$n[0].DateTime,ps:0}],sn:"GetDayOfYear",rt:$n[0].Int32,p:[$n[0].DateTime],box:function($v){return H5.box($v,System.Int32)}},{v:!0,a:2,n:"GetDaysInMonth",t:8,pi:[{n:"year",pt:$n[0].Int32,ps:0},{n:"month",pt:$n[0].Int32,ps:1}],sn:"GetDaysInMonth",rt:$n[0].Int32,p:[$n[0].Int32,$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{ab:!0,a:2,n:"GetDaysInMonth",t:8,pi:[{n:"year",pt:$n[0].Int32,ps:0},{n:"month",pt:$n[0].Int32,ps:1},{n:"era",pt:$n[0].Int32,ps:2}],sn:"GetDaysInMonth$1",rt:$n[0].Int32,p:[$n[0].Int32,$n[0].Int32,$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{v:!0,a:2,n:"GetDaysInYear",t:8,pi:[{n:"year",pt:$n[0].Int32,ps:0}],sn:"GetDaysInYear",rt:$n[0].Int32,p:[$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{ab:!0,a:2,n:"GetDaysInYear",t:8,pi:[{n:"year",pt:$n[0].Int32,ps:0},{n:"era",pt:$n[0].Int32,ps:1}],sn:"GetDaysInYear$1",rt:$n[0].Int32,p:[$n[0].Int32,$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{ab:!0,a:2,n:"GetEra",t:8,pi:[{n:"time",pt:$n[0].DateTime,ps:0}],sn:"GetEra",rt:$n[0].Int32,p:[$n[0].DateTime],box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"GetFirstDayWeekOfYear",t:8,pi:[{n:"time",pt:$n[0].DateTime,ps:0},{n:"firstDayOfWeek",pt:$n[0].Int32,ps:1}],sn:"GetFirstDayWeekOfYear",rt:$n[0].Int32,p:[$n[0].DateTime,$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{v:!0,a:2,n:"GetHour",t:8,pi:[{n:"time",pt:$n[0].DateTime,ps:0}],sn:"GetHour",rt:$n[0].Int32,p:[$n[0].DateTime],box:function($v){return H5.box($v,System.Int32)}},{v:!0,a:2,n:"GetLeapMonth",t:8,pi:[{n:"year",pt:$n[0].Int32,ps:0}],sn:"GetLeapMonth",rt:$n[0].Int32,p:[$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{v:!0,a:2,n:"GetLeapMonth",t:8,pi:[{n:"year",pt:$n[0].Int32,ps:0},{n:"era",pt:$n[0].Int32,ps:1}],sn:"GetLeapMonth$1",rt:$n[0].Int32,p:[$n[0].Int32,$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{v:!0,a:2,n:"GetMilliseconds",t:8,pi:[{n:"time",pt:$n[0].DateTime,ps:0}],sn:"GetMilliseconds",rt:$n[0].Double,p:[$n[0].DateTime],box:function($v){return H5.box($v,System.Double,System.Double.format,System.Double.getHashCode)}},{v:!0,a:2,n:"GetMinute",t:8,pi:[{n:"time",pt:$n[0].DateTime,ps:0}],sn:"GetMinute",rt:$n[0].Int32,p:[$n[0].DateTime],box:function($v){return H5.box($v,System.Int32)}},{ab:!0,a:2,n:"GetMonth",t:8,pi:[{n:"time",pt:$n[0].DateTime,ps:0}],sn:"GetMonth",rt:$n[0].Int32,p:[$n[0].DateTime],box:function($v){return H5.box($v,System.Int32)}},{v:!0,a:2,n:"GetMonthsInYear",t:8,pi:[{n:"year",pt:$n[0].Int32,ps:0}],sn:"GetMonthsInYear",rt:$n[0].Int32,p:[$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{ab:!0,a:2,n:"GetMonthsInYear",t:8,pi:[{n:"year",pt:$n[0].Int32,ps:0},{n:"era",pt:$n[0].Int32,ps:1}],sn:"GetMonthsInYear$1",rt:$n[0].Int32,p:[$n[0].Int32,$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{v:!0,a:2,n:"GetSecond",t:8,pi:[{n:"time",pt:$n[0].DateTime,ps:0}],sn:"GetSecond",rt:$n[0].Int32,p:[$n[0].DateTime],box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"GetSystemTwoDigitYearSetting",is:!0,t:8,pi:[{n:"CalID",pt:$n[1].CalendarId,ps:0},{n:"defaultYearValue",pt:$n[0].Int32,ps:1}],sn:"GetSystemTwoDigitYearSetting",rt:$n[0].Int32,p:[$n[1].CalendarId,$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{v:!0,a:2,n:"GetWeekOfYear",t:8,pi:[{n:"time",pt:$n[0].DateTime,ps:0},{n:"rule",pt:$n[1].CalendarWeekRule,ps:1},{n:"firstDayOfWeek",pt:$n[0].DayOfWeek,ps:2}],sn:"GetWeekOfYear",rt:$n[0].Int32,p:[$n[0].DateTime,$n[1].CalendarWeekRule,$n[0].DayOfWeek],box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"GetWeekOfYearFullDays",t:8,pi:[{n:"time",pt:$n[0].DateTime,ps:0},{n:"firstDayOfWeek",pt:$n[0].Int32,ps:1},{n:"fullDays",pt:$n[0].Int32,ps:2}],sn:"GetWeekOfYearFullDays",rt:$n[0].Int32,p:[$n[0].DateTime,$n[0].Int32,$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"GetWeekOfYearOfMinSupportedDateTime",t:8,pi:[{n:"firstDayOfWeek",pt:$n[0].Int32,ps:0},{n:"minimumDaysInFirstWeek",pt:$n[0].Int32,ps:1}],sn:"GetWeekOfYearOfMinSupportedDateTime",rt:$n[0].Int32,p:[$n[0].Int32,$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{ab:!0,a:2,n:"GetYear",t:8,pi:[{n:"time",pt:$n[0].DateTime,ps:0}],sn:"GetYear",rt:$n[0].Int32,p:[$n[0].DateTime],box:function($v){return H5.box($v,System.Int32)}},{v:!0,a:2,n:"IsLeapDay",t:8,pi:[{n:"year",pt:$n[0].Int32,ps:0},{n:"month",pt:$n[0].Int32,ps:1},{n:"day",pt:$n[0].Int32,ps:2}],sn:"IsLeapDay",rt:$n[0].Boolean,p:[$n[0].Int32,$n[0].Int32,$n[0].Int32],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ab:!0,a:2,n:"IsLeapDay",t:8,pi:[{n:"year",pt:$n[0].Int32,ps:0},{n:"month",pt:$n[0].Int32,ps:1},{n:"day",pt:$n[0].Int32,ps:2},{n:"era",pt:$n[0].Int32,ps:3}],sn:"IsLeapDay$1",rt:$n[0].Boolean,p:[$n[0].Int32,$n[0].Int32,$n[0].Int32,$n[0].Int32],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{v:!0,a:2,n:"IsLeapMonth",t:8,pi:[{n:"year",pt:$n[0].Int32,ps:0},{n:"month",pt:$n[0].Int32,ps:1}],sn:"IsLeapMonth",rt:$n[0].Boolean,p:[$n[0].Int32,$n[0].Int32],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ab:!0,a:2,n:"IsLeapMonth",t:8,pi:[{n:"year",pt:$n[0].Int32,ps:0},{n:"month",pt:$n[0].Int32,ps:1},{n:"era",pt:$n[0].Int32,ps:2}],sn:"IsLeapMonth$1",rt:$n[0].Boolean,p:[$n[0].Int32,$n[0].Int32,$n[0].Int32],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{v:!0,a:2,n:"IsLeapYear",t:8,pi:[{n:"year",pt:$n[0].Int32,ps:0}],sn:"IsLeapYear",rt:$n[0].Boolean,p:[$n[0].Int32],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ab:!0,a:2,n:"IsLeapYear",t:8,pi:[{n:"year",pt:$n[0].Int32,ps:0},{n:"era",pt:$n[0].Int32,ps:1}],sn:"IsLeapYear$1",rt:$n[0].Boolean,p:[$n[0].Int32,$n[0].Int32],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{v:!0,a:4,n:"IsValidDay",t:8,pi:[{n:"year",pt:$n[0].Int32,ps:0},{n:"month",pt:$n[0].Int32,ps:1},{n:"day",pt:$n[0].Int32,ps:2},{n:"era",pt:$n[0].Int32,ps:3}],sn:"IsValidDay",rt:$n[0].Boolean,p:[$n[0].Int32,$n[0].Int32,$n[0].Int32,$n[0].Int32],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{v:!0,a:4,n:"IsValidMonth",t:8,pi:[{n:"year",pt:$n[0].Int32,ps:0},{n:"month",pt:$n[0].Int32,ps:1},{n:"era",pt:$n[0].Int32,ps:2}],sn:"IsValidMonth",rt:$n[0].Boolean,p:[$n[0].Int32,$n[0].Int32,$n[0].Int32],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{v:!0,a:4,n:"IsValidYear",t:8,pi:[{n:"year",pt:$n[0].Int32,ps:0},{n:"era",pt:$n[0].Int32,ps:1}],sn:"IsValidYear",rt:$n[0].Boolean,p:[$n[0].Int32,$n[0].Int32],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"ReadOnly",is:!0,t:8,pi:[{n:"calendar",pt:$n[1].Calendar,ps:0}],sn:"ReadOnly",rt:$n[1].Calendar,p:[$n[1].Calendar]},{a:4,n:"SetReadOnlyState",t:8,pi:[{n:"readOnly",pt:$n[0].Boolean,ps:0}],sn:"SetReadOnlyState",rt:$n[0].Void,p:[$n[0].Boolean]},{v:!0,a:2,n:"ToDateTime",t:8,pi:[{n:"year",pt:$n[0].Int32,ps:0},{n:"month",pt:$n[0].Int32,ps:1},{n:"day",pt:$n[0].Int32,ps:2},{n:"hour",pt:$n[0].Int32,ps:3},{n:"minute",pt:$n[0].Int32,ps:4},{n:"second",pt:$n[0].Int32,ps:5},{n:"millisecond",pt:$n[0].Int32,ps:6}],sn:"ToDateTime",rt:$n[0].DateTime,p:[$n[0].Int32,$n[0].Int32,$n[0].Int32,$n[0].Int32,$n[0].Int32,$n[0].Int32,$n[0].Int32],box:function($v){return H5.box($v,System.DateTime,System.DateTime.format)}},{ab:!0,a:2,n:"ToDateTime",t:8,pi:[{n:"year",pt:$n[0].Int32,ps:0},{n:"month",pt:$n[0].Int32,ps:1},{n:"day",pt:$n[0].Int32,ps:2},{n:"hour",pt:$n[0].Int32,ps:3},{n:"minute",pt:$n[0].Int32,ps:4},{n:"second",pt:$n[0].Int32,ps:5},{n:"millisecond",pt:$n[0].Int32,ps:6},{n:"era",pt:$n[0].Int32,ps:7}],sn:"ToDateTime$1",rt:$n[0].DateTime,p:[$n[0].Int32,$n[0].Int32,$n[0].Int32,$n[0].Int32,$n[0].Int32,$n[0].Int32,$n[0].Int32,$n[0].Int32],box:function($v){return H5.box($v,System.DateTime,System.DateTime.format)}},{v:!0,a:2,n:"ToFourDigitYear",t:8,pi:[{n:"year",pt:$n[0].Int32,ps:0}],sn:"ToFourDigitYear",rt:$n[0].Int32,p:[$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{v:!0,a:4,n:"TryToDateTime",t:8,pi:[{n:"year",pt:$n[0].Int32,ps:0},{n:"month",pt:$n[0].Int32,ps:1},{n:"day",pt:$n[0].Int32,ps:2},{n:"hour",pt:$n[0].Int32,ps:3},{n:"minute",pt:$n[0].Int32,ps:4},{n:"second",pt:$n[0].Int32,ps:5},{n:"millisecond",pt:$n[0].Int32,ps:6},{n:"era",pt:$n[0].Int32,ps:7},{n:"result",out:!0,pt:$n[0].DateTime,ps:8}],sn:"TryToDateTime",rt:$n[0].Boolean,p:[$n[0].Int32,$n[0].Int32,$n[0].Int32,$n[0].Int32,$n[0].Int32,$n[0].Int32,$n[0].Int32,$n[0].Int32,$n[0].DateTime],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:4,n:"VerifyWritable",t:8,sn:"VerifyWritable",rt:$n[0].Void},{v:!0,a:2,n:"AlgorithmType",t:16,rt:$n[1].CalendarAlgorithmType,g:{v:!0,a:2,n:"get_AlgorithmType",t:8,rt:$n[1].CalendarAlgorithmType,fg:"AlgorithmType",box:function($v){return H5.box($v,System.Globalization.CalendarAlgorithmType,System.Enum.toStringFn(System.Globalization.CalendarAlgorithmType))}},fn:"AlgorithmType"},{v:!0,a:4,n:"BaseCalendarID",t:16,rt:$n[1].CalendarId,g:{v:!0,a:4,n:"get_BaseCalendarID",t:8,rt:$n[1].CalendarId,fg:"BaseCalendarID",box:function($v){return H5.box($v,System.Globalization.CalendarId,System.Enum.toStringFn(System.Globalization.CalendarId))}},fn:"BaseCalendarID"},{v:!0,a:4,n:"CurrentEraValue",t:16,rt:$n[0].Int32,g:{v:!0,a:4,n:"get_CurrentEraValue",t:8,rt:$n[0].Int32,fg:"CurrentEraValue",box:function($v){return H5.box($v,System.Int32)}},fn:"CurrentEraValue"},{v:!0,a:3,n:"DaysInYearBeforeMinSupportedYear",t:16,rt:$n[0].Int32,g:{v:!0,a:3,n:"get_DaysInYearBeforeMinSupportedYear",t:8,rt:$n[0].Int32,fg:"DaysInYearBeforeMinSupportedYear",box:function($v){return H5.box($v,System.Int32)}},fn:"DaysInYearBeforeMinSupportedYear"},{ab:!0,a:2,n:"Eras",t:16,rt:$n[0].Array.type(System.Int32),g:{ab:!0,a:2,n:"get_Eras",t:8,rt:$n[0].Array.type(System.Int32),fg:"Eras"},fn:"Eras"},{v:!0,a:4,n:"ID",t:16,rt:$n[1].CalendarId,g:{v:!0,a:4,n:"get_ID",t:8,rt:$n[1].CalendarId,fg:"ID",box:function($v){return H5.box($v,System.Globalization.CalendarId,System.Enum.toStringFn(System.Globalization.CalendarId))}},fn:"ID"},{a:2,n:"IsReadOnly",t:16,rt:$n[0].Boolean,g:{a:2,n:"get_IsReadOnly",t:8,rt:$n[0].Boolean,fg:"IsReadOnly",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},fn:"IsReadOnly"},{v:!0,a:2,n:"MaxSupportedDateTime",t:16,rt:$n[0].DateTime,g:{v:!0,a:2,n:"get_MaxSupportedDateTime",t:8,rt:$n[0].DateTime,fg:"MaxSupportedDateTime",box:function($v){return H5.box($v,System.DateTime,System.DateTime.format)}},fn:"MaxSupportedDateTime"},{v:!0,a:2,n:"MinSupportedDateTime",t:16,rt:$n[0].DateTime,g:{v:!0,a:2,n:"get_MinSupportedDateTime",t:8,rt:$n[0].DateTime,fg:"MinSupportedDateTime",box:function($v){return H5.box($v,System.DateTime,System.DateTime.format)}},fn:"MinSupportedDateTime"},{v:!0,a:2,n:"TwoDigitYearMax",t:16,rt:$n[0].Int32,g:{v:!0,a:2,n:"get_TwoDigitYearMax",t:8,rt:$n[0].Int32,fg:"TwoDigitYearMax",box:function($v){return H5.box($v,System.Int32)}},s:{v:!0,a:2,n:"set_TwoDigitYearMax",t:8,p:[$n[0].Int32],rt:$n[0].Void,fs:"TwoDigitYearMax"},fn:"TwoDigitYearMax"},{a:2,n:"CurrentEra",is:!0,t:4,rt:$n[0].Int32,sn:"CurrentEra",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"DaysPer100Years",is:!0,t:4,rt:$n[0].Int32,sn:"DaysPer100Years",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"DaysPer400Years",is:!0,t:4,rt:$n[0].Int32,sn:"DaysPer400Years",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"DaysPer4Years",is:!0,t:4,rt:$n[0].Int32,sn:"DaysPer4Years",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"DaysPerYear",is:!0,t:4,rt:$n[0].Int32,sn:"DaysPerYear",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"DaysTo10000",is:!0,t:4,rt:$n[0].Int32,sn:"DaysTo10000",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"MaxMillis",is:!0,t:4,rt:$n[0].Int64,sn:"MaxMillis"},{a:4,n:"MillisPerDay",is:!0,t:4,rt:$n[0].Int32,sn:"MillisPerDay",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"MillisPerHour",is:!0,t:4,rt:$n[0].Int32,sn:"MillisPerHour",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"MillisPerMinute",is:!0,t:4,rt:$n[0].Int32,sn:"MillisPerMinute",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"MillisPerSecond",is:!0,t:4,rt:$n[0].Int32,sn:"MillisPerSecond",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"TicksPerDay",is:!0,t:4,rt:$n[0].Int64,sn:"TicksPerDay"},{a:4,n:"TicksPerHour",is:!0,t:4,rt:$n[0].Int64,sn:"TicksPerHour"},{a:4,n:"TicksPerMillisecond",is:!0,t:4,rt:$n[0].Int64,sn:"TicksPerMillisecond"},{a:4,n:"TicksPerMinute",is:!0,t:4,rt:$n[0].Int64,sn:"TicksPerMinute"},{a:4,n:"TicksPerSecond",is:!0,t:4,rt:$n[0].Int64,sn:"TicksPerSecond"},{a:1,n:"_isReadOnly",t:4,rt:$n[0].Boolean,sn:"_isReadOnly",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:4,n:"twoDigitYearMax",t:4,rt:$n[0].Int32,sn:"twoDigitYearMax",box:function($v){return H5.box($v,System.Int32)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Array.type(System.Int32),sn:"Eras"}]}},$n);$m("System.Globalization.CalendarAlgorithmType",function(){return{att:257,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:"LunarCalendar",is:!0,t:4,rt:$n[1].CalendarAlgorithmType,sn:"LunarCalendar",box:function($v){return H5.box($v,System.Globalization.CalendarAlgorithmType,System.Enum.toStringFn(System.Globalization.CalendarAlgorithmType))}},{a:2,n:"LunisolarCalendar",is:!0,t:4,rt:$n[1].CalendarAlgorithmType,sn:"LunisolarCalendar",box:function($v){return H5.box($v,System.Globalization.CalendarAlgorithmType,System.Enum.toStringFn(System.Globalization.CalendarAlgorithmType))}},{a:2,n:"SolarCalendar",is:!0,t:4,rt:$n[1].CalendarAlgorithmType,sn:"SolarCalendar",box:function($v){return H5.box($v,System.Globalization.CalendarAlgorithmType,System.Enum.toStringFn(System.Globalization.CalendarAlgorithmType))}},{a:2,n:"Unknown",is:!0,t:4,rt:$n[1].CalendarAlgorithmType,sn:"Unknown",box:function($v){return H5.box($v,System.Globalization.CalendarAlgorithmType,System.Enum.toStringFn(System.Globalization.CalendarAlgorithmType))}}]}},$n);$m("System.Globalization.CalendarWeekRule",function(){return{att:257,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:"FirstDay",is:!0,t:4,rt:$n[1].CalendarWeekRule,sn:"FirstDay",box:function($v){return H5.box($v,System.Globalization.CalendarWeekRule,System.Enum.toStringFn(System.Globalization.CalendarWeekRule))}},{a:2,n:"FirstFourDayWeek",is:!0,t:4,rt:$n[1].CalendarWeekRule,sn:"FirstFourDayWeek",box:function($v){return H5.box($v,System.Globalization.CalendarWeekRule,System.Enum.toStringFn(System.Globalization.CalendarWeekRule))}},{a:2,n:"FirstFullWeek",is:!0,t:4,rt:$n[1].CalendarWeekRule,sn:"FirstFullWeek",box:function($v){return H5.box($v,System.Globalization.CalendarWeekRule,System.Enum.toStringFn(System.Globalization.CalendarWeekRule))}}]}},$n);$m("System.Globalization.CultureNotFoundException",function(){return{att:1056769,a:2,at:[new System.SerializableAttribute],m:[{a:2,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].String],pi:[{n:"message",pt:$n[0].String,ps:0}],sn:"$ctor1"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[0].Exception],pi:[{n:"message",pt:$n[0].String,ps:0},{n:"innerException",pt:$n[0].Exception,ps:1}],sn:"$ctor2"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[0].String],pi:[{n:"paramName",pt:$n[0].String,ps:0},{n:"message",pt:$n[0].String,ps:1}],sn:"$ctor5"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[0].Int32,$n[0].Exception],pi:[{n:"message",pt:$n[0].String,ps:0},{n:"invalidCultureId",pt:$n[0].Int32,ps:1},{n:"innerException",pt:$n[0].Exception,ps:2}],sn:"$ctor3"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[0].Int32,$n[0].String],pi:[{n:"paramName",pt:$n[0].String,ps:0},{n:"invalidCultureId",pt:$n[0].Int32,ps:1},{n:"message",pt:$n[0].String,ps:2}],sn:"$ctor4"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[0].String,$n[0].Exception],pi:[{n:"message",pt:$n[0].String,ps:0},{n:"invalidCultureName",pt:$n[0].String,ps:1},{n:"innerException",pt:$n[0].Exception,ps:2}],sn:"$ctor6"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[0].String,$n[0].String],pi:[{n:"paramName",pt:$n[0].String,ps:0},{n:"invalidCultureName",pt:$n[0].String,ps:1},{n:"message",pt:$n[0].String,ps:2}],sn:"$ctor7"},{a:1,n:"DefaultMessage",is:!0,t:16,rt:$n[0].String,g:{a:1,n:"get_DefaultMessage",t:8,rt:$n[0].String,fg:"DefaultMessage",is:!0},fn:"DefaultMessage"},{a:1,n:"FormatedInvalidCultureId",t:16,rt:$n[0].String,g:{a:1,n:"get_FormatedInvalidCultureId",t:8,rt:$n[0].String,fg:"FormatedInvalidCultureId"},fn:"FormatedInvalidCultureId"},{v:!0,a:2,n:"InvalidCultureId",t:16,rt:$n[0].Nullable$1(System.Int32),g:{v:!0,a:2,n:"get_InvalidCultureId",t:8,rt:$n[0].Nullable$1(System.Int32),fg:"InvalidCultureId",box:function($v){return H5.box($v,System.Int32,System.Nullable.toString,System.Nullable.getHashCode)}},fn:"InvalidCultureId"},{v:!0,a:2,n:"InvalidCultureName",t:16,rt:$n[0].String,g:{v:!0,a:2,n:"get_InvalidCultureName",t:8,rt:$n[0].String,fg:"InvalidCultureName"},fn:"InvalidCultureName"},{ov:!0,a:2,n:"Message",t:16,rt:$n[0].String,g:{ov:!0,a:2,n:"get_Message",t:8,rt:$n[0].String,fg:"Message"},fn:"Message"},{a:1,n:"_invalidCultureId",t:4,rt:$n[0].Nullable$1(System.Int32),sn:"_invalidCultureId",box:function($v){return H5.box($v,System.Int32,System.Nullable.toString,System.Nullable.getHashCode)}},{a:1,n:"_invalidCultureName",t:4,rt:$n[0].String,sn:"_invalidCultureName"}]}},$n);$m("System.Globalization.FORMATFLAGS",function(){return{att:256,a:4,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:"None",is:!0,t:4,rt:$n[1].FORMATFLAGS,sn:"None",box:function($v){return H5.box($v,System.Globalization.FORMATFLAGS,System.Enum.toStringFn(System.Globalization.FORMATFLAGS))}},{a:2,n:"UseDigitPrefixInTokens",is:!0,t:4,rt:$n[1].FORMATFLAGS,sn:"UseDigitPrefixInTokens",box:function($v){return H5.box($v,System.Globalization.FORMATFLAGS,System.Enum.toStringFn(System.Globalization.FORMATFLAGS))}},{a:2,n:"UseGenitiveMonth",is:!0,t:4,rt:$n[1].FORMATFLAGS,sn:"UseGenitiveMonth",box:function($v){return H5.box($v,System.Globalization.FORMATFLAGS,System.Enum.toStringFn(System.Globalization.FORMATFLAGS))}},{a:2,n:"UseHebrewParsing",is:!0,t:4,rt:$n[1].FORMATFLAGS,sn:"UseHebrewParsing",box:function($v){return H5.box($v,System.Globalization.FORMATFLAGS,System.Enum.toStringFn(System.Globalization.FORMATFLAGS))}},{a:2,n:"UseLeapYearMonth",is:!0,t:4,rt:$n[1].FORMATFLAGS,sn:"UseLeapYearMonth",box:function($v){return H5.box($v,System.Globalization.FORMATFLAGS,System.Enum.toStringFn(System.Globalization.FORMATFLAGS))}},{a:2,n:"UseSpacesInDayNames",is:!0,t:4,rt:$n[1].FORMATFLAGS,sn:"UseSpacesInDayNames",box:function($v){return H5.box($v,System.Globalization.FORMATFLAGS,System.Enum.toStringFn(System.Globalization.FORMATFLAGS))}},{a:2,n:"UseSpacesInMonthNames",is:!0,t:4,rt:$n[1].FORMATFLAGS,sn:"UseSpacesInMonthNames",box:function($v){return H5.box($v,System.Globalization.FORMATFLAGS,System.Enum.toStringFn(System.Globalization.FORMATFLAGS))}}]}},$n);$m("System.Globalization.CalendarId",function(){return{att:256,a:4,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:"CHINESELUNISOLAR",is:!0,t:4,rt:$n[1].CalendarId,sn:"CHINESELUNISOLAR",box:function($v){return H5.box($v,System.Globalization.CalendarId,System.Enum.toStringFn(System.Globalization.CalendarId))}},{a:2,n:"GREGORIAN",is:!0,t:4,rt:$n[1].CalendarId,sn:"GREGORIAN",box:function($v){return H5.box($v,System.Globalization.CalendarId,System.Enum.toStringFn(System.Globalization.CalendarId))}},{a:2,n:"GREGORIAN_ARABIC",is:!0,t:4,rt:$n[1].CalendarId,sn:"GREGORIAN_ARABIC",box:function($v){return H5.box($v,System.Globalization.CalendarId,System.Enum.toStringFn(System.Globalization.CalendarId))}},{a:2,n:"GREGORIAN_ME_FRENCH",is:!0,t:4,rt:$n[1].CalendarId,sn:"GREGORIAN_ME_FRENCH",box:function($v){return H5.box($v,System.Globalization.CalendarId,System.Enum.toStringFn(System.Globalization.CalendarId))}},{a:2,n:"GREGORIAN_US",is:!0,t:4,rt:$n[1].CalendarId,sn:"GREGORIAN_US",box:function($v){return H5.box($v,System.Globalization.CalendarId,System.Enum.toStringFn(System.Globalization.CalendarId))}},{a:2,n:"GREGORIAN_XLIT_ENGLISH",is:!0,t:4,rt:$n[1].CalendarId,sn:"GREGORIAN_XLIT_ENGLISH",box:function($v){return H5.box($v,System.Globalization.CalendarId,System.Enum.toStringFn(System.Globalization.CalendarId))}},{a:2,n:"GREGORIAN_XLIT_FRENCH",is:!0,t:4,rt:$n[1].CalendarId,sn:"GREGORIAN_XLIT_FRENCH",box:function($v){return H5.box($v,System.Globalization.CalendarId,System.Enum.toStringFn(System.Globalization.CalendarId))}},{a:2,n:"HEBREW",is:!0,t:4,rt:$n[1].CalendarId,sn:"HEBREW",box:function($v){return H5.box($v,System.Globalization.CalendarId,System.Enum.toStringFn(System.Globalization.CalendarId))}},{a:2,n:"HIJRI",is:!0,t:4,rt:$n[1].CalendarId,sn:"HIJRI",box:function($v){return H5.box($v,System.Globalization.CalendarId,System.Enum.toStringFn(System.Globalization.CalendarId))}},{a:2,n:"JAPAN",is:!0,t:4,rt:$n[1].CalendarId,sn:"JAPAN",box:function($v){return H5.box($v,System.Globalization.CalendarId,System.Enum.toStringFn(System.Globalization.CalendarId))}},{a:2,n:"JAPANESELUNISOLAR",is:!0,t:4,rt:$n[1].CalendarId,sn:"JAPANESELUNISOLAR",box:function($v){return H5.box($v,System.Globalization.CalendarId,System.Enum.toStringFn(System.Globalization.CalendarId))}},{a:2,n:"JULIAN",is:!0,t:4,rt:$n[1].CalendarId,sn:"JULIAN",box:function($v){return H5.box($v,System.Globalization.CalendarId,System.Enum.toStringFn(System.Globalization.CalendarId))}},{a:2,n:"KOREA",is:!0,t:4,rt:$n[1].CalendarId,sn:"KOREA",box:function($v){return H5.box($v,System.Globalization.CalendarId,System.Enum.toStringFn(System.Globalization.CalendarId))}},{a:2,n:"KOREANLUNISOLAR",is:!0,t:4,rt:$n[1].CalendarId,sn:"KOREANLUNISOLAR",box:function($v){return H5.box($v,System.Globalization.CalendarId,System.Enum.toStringFn(System.Globalization.CalendarId))}},{a:2,n:"LAST_CALENDAR",is:!0,t:4,rt:$n[1].CalendarId,sn:"LAST_CALENDAR",box:function($v){return H5.box($v,System.Globalization.CalendarId,System.Enum.toStringFn(System.Globalization.CalendarId))}},{a:2,n:"LUNAR_ETO_CHN",is:!0,t:4,rt:$n[1].CalendarId,sn:"LUNAR_ETO_CHN",box:function($v){return H5.box($v,System.Globalization.CalendarId,System.Enum.toStringFn(System.Globalization.CalendarId))}},{a:2,n:"LUNAR_ETO_KOR",is:!0,t:4,rt:$n[1].CalendarId,sn:"LUNAR_ETO_KOR",box:function($v){return H5.box($v,System.Globalization.CalendarId,System.Enum.toStringFn(System.Globalization.CalendarId))}},{a:2,n:"LUNAR_ETO_ROKUYOU",is:!0,t:4,rt:$n[1].CalendarId,sn:"LUNAR_ETO_ROKUYOU",box:function($v){return H5.box($v,System.Globalization.CalendarId,System.Enum.toStringFn(System.Globalization.CalendarId))}},{a:2,n:"PERSIAN",is:!0,t:4,rt:$n[1].CalendarId,sn:"PERSIAN",box:function($v){return H5.box($v,System.Globalization.CalendarId,System.Enum.toStringFn(System.Globalization.CalendarId))}},{a:2,n:"SAKA",is:!0,t:4,rt:$n[1].CalendarId,sn:"SAKA",box:function($v){return H5.box($v,System.Globalization.CalendarId,System.Enum.toStringFn(System.Globalization.CalendarId))}},{a:2,n:"TAIWAN",is:!0,t:4,rt:$n[1].CalendarId,sn:"TAIWAN",box:function($v){return H5.box($v,System.Globalization.CalendarId,System.Enum.toStringFn(System.Globalization.CalendarId))}},{a:2,n:"TAIWANLUNISOLAR",is:!0,t:4,rt:$n[1].CalendarId,sn:"TAIWANLUNISOLAR",box:function($v){return H5.box($v,System.Globalization.CalendarId,System.Enum.toStringFn(System.Globalization.CalendarId))}},{a:2,n:"THAI",is:!0,t:4,rt:$n[1].CalendarId,sn:"THAI",box:function($v){return H5.box($v,System.Globalization.CalendarId,System.Enum.toStringFn(System.Globalization.CalendarId))}},{a:2,n:"UMALQURA",is:!0,t:4,rt:$n[1].CalendarId,sn:"UMALQURA",box:function($v){return H5.box($v,System.Globalization.CalendarId,System.Enum.toStringFn(System.Globalization.CalendarId))}},{a:2,n:"UNINITIALIZED_VALUE",is:!0,t:4,rt:$n[1].CalendarId,sn:"UNINITIALIZED_VALUE",box:function($v){return H5.box($v,System.Globalization.CalendarId,System.Enum.toStringFn(System.Globalization.CalendarId))}}]}},$n);$m("System.Globalization.DateTimeFormatInfoScanner",function(){return{nested:[$n[1].DateTimeFormatInfoScanner.FoundDatePattern],att:1048576,a:4,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:4,n:"AddDateWordOrPostfix",t:8,pi:[{n:"formatPostfix",pt:$n[0].String,ps:0},{n:"str",pt:$n[0].String,ps:1}],sn:"AddDateWordOrPostfix",rt:$n[0].Void,p:[$n[0].String,$n[0].String]},{a:4,n:"AddDateWords",t:8,pi:[{n:"pattern",pt:$n[0].String,ps:0},{n:"index",pt:$n[0].Int32,ps:1},{n:"formatPostfix",pt:$n[0].String,ps:2}],sn:"AddDateWords",rt:$n[0].Int32,p:[$n[0].String,$n[0].Int32,$n[0].String],box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"AddIgnorableSymbols",t:8,pi:[{n:"text",pt:$n[0].String,ps:0}],sn:"AddIgnorableSymbols",rt:$n[0].Void,p:[$n[0].String]},{a:1,n:"ArrayElementsBeginWithDigit",is:!0,t:8,pi:[{n:"array",pt:$n[0].Array.type(System.String),ps:0}],sn:"ArrayElementsBeginWithDigit",rt:$n[0].Boolean,p:[$n[0].Array.type(System.String)],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"ArrayElementsHaveSpace",is:!0,t:8,pi:[{n:"array",pt:$n[0].Array.type(System.String),ps:0}],sn:"ArrayElementsHaveSpace",rt:$n[0].Boolean,p:[$n[0].Array.type(System.String)],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"EqualStringArrays",is:!0,t:8,pi:[{n:"array1",pt:$n[0].Array.type(System.String),ps:0},{n:"array2",pt:$n[0].Array.type(System.String),ps:1}],sn:"EqualStringArrays",rt:$n[0].Boolean,p:[$n[0].Array.type(System.String),$n[0].Array.type(System.String)],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:4,n:"GetDateWordsOfDTFI",t:8,pi:[{n:"dtfi",pt:$n[1].DateTimeFormatInfo,ps:0}],sn:"GetDateWordsOfDTFI",rt:$n[0].Array.type(System.String),p:[$n[1].DateTimeFormatInfo]},{a:4,n:"GetFormatFlagGenitiveMonth",is:!0,t:8,pi:[{n:"monthNames",pt:$n[0].Array.type(System.String),ps:0},{n:"genitveMonthNames",pt:$n[0].Array.type(System.String),ps:1},{n:"abbrevMonthNames",pt:$n[0].Array.type(System.String),ps:2},{n:"genetiveAbbrevMonthNames",pt:$n[0].Array.type(System.String),ps:3}],sn:"GetFormatFlagGenitiveMonth",rt:$n[1].FORMATFLAGS,p:[$n[0].Array.type(System.String),$n[0].Array.type(System.String),$n[0].Array.type(System.String),$n[0].Array.type(System.String)],box:function($v){return H5.box($v,System.Globalization.FORMATFLAGS,System.Enum.toStringFn(System.Globalization.FORMATFLAGS))}},{a:4,n:"GetFormatFlagUseHebrewCalendar",is:!0,t:8,pi:[{n:"calID",pt:$n[0].Int32,ps:0}],sn:"GetFormatFlagUseHebrewCalendar",rt:$n[1].FORMATFLAGS,p:[$n[0].Int32],box:function($v){return H5.box($v,System.Globalization.FORMATFLAGS,System.Enum.toStringFn(System.Globalization.FORMATFLAGS))}},{a:4,n:"GetFormatFlagUseSpaceInDayNames",is:!0,t:8,pi:[{n:"dayNames",pt:$n[0].Array.type(System.String),ps:0},{n:"abbrevDayNames",pt:$n[0].Array.type(System.String),ps:1}],sn:"GetFormatFlagUseSpaceInDayNames",rt:$n[1].FORMATFLAGS,p:[$n[0].Array.type(System.String),$n[0].Array.type(System.String)],box:function($v){return H5.box($v,System.Globalization.FORMATFLAGS,System.Enum.toStringFn(System.Globalization.FORMATFLAGS))}},{a:4,n:"GetFormatFlagUseSpaceInMonthNames",is:!0,t:8,pi:[{n:"monthNames",pt:$n[0].Array.type(System.String),ps:0},{n:"genitveMonthNames",pt:$n[0].Array.type(System.String),ps:1},{n:"abbrevMonthNames",pt:$n[0].Array.type(System.String),ps:2},{n:"genetiveAbbrevMonthNames",pt:$n[0].Array.type(System.String),ps:3}],sn:"GetFormatFlagUseSpaceInMonthNames",rt:$n[1].FORMATFLAGS,p:[$n[0].Array.type(System.String),$n[0].Array.type(System.String),$n[0].Array.type(System.String),$n[0].Array.type(System.String)],box:function($v){return H5.box($v,System.Globalization.FORMATFLAGS,System.Enum.toStringFn(System.Globalization.FORMATFLAGS))}},{a:4,n:"ScanDateWord",t:8,pi:[{n:"pattern",pt:$n[0].String,ps:0}],sn:"ScanDateWord",rt:$n[0].Void,p:[$n[0].String]},{a:4,n:"ScanRepeatChar",is:!0,t:8,pi:[{n:"pattern",pt:$n[0].String,ps:0},{n:"ch",pt:$n[0].Char,ps:1},{n:"index",pt:$n[0].Int32,ps:2},{n:"count",out:!0,pt:$n[0].Int32,ps:3}],sn:"ScanRepeatChar",rt:$n[0].Int32,p:[$n[0].String,$n[0].Char,$n[0].Int32,$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"SkipWhiteSpacesAndNonLetter",is:!0,t:8,pi:[{n:"pattern",pt:$n[0].String,ps:0},{n:"currentIndex",pt:$n[0].Int32,ps:1}],sn:"SkipWhiteSpacesAndNonLetter",rt:$n[0].Int32,p:[$n[0].String,$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"KnownWords",is:!0,t:16,rt:$n[3].Dictionary$2(System.String,System.String),g:{a:1,n:"get_KnownWords",t:8,rt:$n[3].Dictionary$2(System.String,System.String),fg:"KnownWords",is:!0},fn:"KnownWords"},{a:4,n:"CJKDaySuff",is:!0,t:4,rt:$n[0].String,sn:"CJKDaySuff"},{a:4,n:"CJKHourSuff",is:!0,t:4,rt:$n[0].String,sn:"CJKHourSuff"},{a:4,n:"CJKMinuteSuff",is:!0,t:4,rt:$n[0].String,sn:"CJKMinuteSuff"},{a:4,n:"CJKMonthSuff",is:!0,t:4,rt:$n[0].String,sn:"CJKMonthSuff"},{a:4,n:"CJKSecondSuff",is:!0,t:4,rt:$n[0].String,sn:"CJKSecondSuff"},{a:4,n:"CJKYearSuff",is:!0,t:4,rt:$n[0].String,sn:"CJKYearSuff"},{a:4,n:"ChineseHourSuff",is:!0,t:4,rt:$n[0].String,sn:"ChineseHourSuff"},{a:4,n:"IgnorableSymbolChar",is:!0,t:4,rt:$n[0].Char,sn:"IgnorableSymbolChar",box:function($v){return H5.box($v,System.Char,String.fromCharCode,System.Char.getHashCode)}},{a:4,n:"KoreanDaySuff",is:!0,t:4,rt:$n[0].String,sn:"KoreanDaySuff"},{a:4,n:"KoreanHourSuff",is:!0,t:4,rt:$n[0].String,sn:"KoreanHourSuff"},{a:4,n:"KoreanMinuteSuff",is:!0,t:4,rt:$n[0].String,sn:"KoreanMinuteSuff"},{a:4,n:"KoreanMonthSuff",is:!0,t:4,rt:$n[0].String,sn:"KoreanMonthSuff"},{a:4,n:"KoreanSecondSuff",is:!0,t:4,rt:$n[0].String,sn:"KoreanSecondSuff"},{a:4,n:"KoreanYearSuff",is:!0,t:4,rt:$n[0].String,sn:"KoreanYearSuff"},{a:4,n:"MonthPostfixChar",is:!0,t:4,rt:$n[0].Char,sn:"MonthPostfixChar",box:function($v){return H5.box($v,System.Char,String.fromCharCode,System.Char.getHashCode)}},{a:1,n:"_ymdFlags",t:4,rt:$n[1].DateTimeFormatInfoScanner.FoundDatePattern,sn:"_ymdFlags",box:function($v){return H5.box($v,System.Globalization.DateTimeFormatInfoScanner.FoundDatePattern,System.Enum.toStringFn(System.Globalization.DateTimeFormatInfoScanner.FoundDatePattern))}},{a:4,n:"m_dateWords",t:4,rt:$n[3].List$1(System.String),sn:"m_dateWords"},{a:1,n:"s_knownWords",is:!0,t:4,rt:$n[3].Dictionary$2(System.String,System.String),sn:"s_knownWords"}]}},$n);$m("System.Globalization.DateTimeFormatInfoScanner.FoundDatePattern",function(){return{td:$n[1].DateTimeFormatInfoScanner,att:259,a:1,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:"FoundDayPatternFlag",is:!0,t:4,rt:$n[1].DateTimeFormatInfoScanner.FoundDatePattern,sn:"FoundDayPatternFlag",box:function($v){return H5.box($v,System.Globalization.DateTimeFormatInfoScanner.FoundDatePattern,System.Enum.toStringFn(System.Globalization.DateTimeFormatInfoScanner.FoundDatePattern))}},{a:2,n:"FoundMonthPatternFlag",is:!0,t:4,rt:$n[1].DateTimeFormatInfoScanner.FoundDatePattern,sn:"FoundMonthPatternFlag",box:function($v){return H5.box($v,System.Globalization.DateTimeFormatInfoScanner.FoundDatePattern,System.Enum.toStringFn(System.Globalization.DateTimeFormatInfoScanner.FoundDatePattern))}},{a:2,n:"FoundYMDPatternFlag",is:!0,t:4,rt:$n[1].DateTimeFormatInfoScanner.FoundDatePattern,sn:"FoundYMDPatternFlag",box:function($v){return H5.box($v,System.Globalization.DateTimeFormatInfoScanner.FoundDatePattern,System.Enum.toStringFn(System.Globalization.DateTimeFormatInfoScanner.FoundDatePattern))}},{a:2,n:"FoundYearPatternFlag",is:!0,t:4,rt:$n[1].DateTimeFormatInfoScanner.FoundDatePattern,sn:"FoundYearPatternFlag",box:function($v){return H5.box($v,System.Globalization.DateTimeFormatInfoScanner.FoundDatePattern,System.Enum.toStringFn(System.Globalization.DateTimeFormatInfoScanner.FoundDatePattern))}},{a:2,n:"None",is:!0,t:4,rt:$n[1].DateTimeFormatInfoScanner.FoundDatePattern,sn:"None",box:function($v){return H5.box($v,System.Globalization.DateTimeFormatInfoScanner.FoundDatePattern,System.Enum.toStringFn(System.Globalization.DateTimeFormatInfoScanner.FoundDatePattern))}}]}},$n);$m("System.Globalization.DateTimeStyles",function(){return{att:257,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:"AdjustToUniversal",is:!0,t:4,rt:$n[1].DateTimeStyles,sn:"AdjustToUniversal",box:function($v){return H5.box($v,System.Globalization.DateTimeStyles,System.Enum.toStringFn(System.Globalization.DateTimeStyles))}},{a:2,n:"AllowInnerWhite",is:!0,t:4,rt:$n[1].DateTimeStyles,sn:"AllowInnerWhite",box:function($v){return H5.box($v,System.Globalization.DateTimeStyles,System.Enum.toStringFn(System.Globalization.DateTimeStyles))}},{a:2,n:"AllowLeadingWhite",is:!0,t:4,rt:$n[1].DateTimeStyles,sn:"AllowLeadingWhite",box:function($v){return H5.box($v,System.Globalization.DateTimeStyles,System.Enum.toStringFn(System.Globalization.DateTimeStyles))}},{a:2,n:"AllowTrailingWhite",is:!0,t:4,rt:$n[1].DateTimeStyles,sn:"AllowTrailingWhite",box:function($v){return H5.box($v,System.Globalization.DateTimeStyles,System.Enum.toStringFn(System.Globalization.DateTimeStyles))}},{a:2,n:"AllowWhiteSpaces",is:!0,t:4,rt:$n[1].DateTimeStyles,sn:"AllowWhiteSpaces",box:function($v){return H5.box($v,System.Globalization.DateTimeStyles,System.Enum.toStringFn(System.Globalization.DateTimeStyles))}},{a:2,n:"AssumeLocal",is:!0,t:4,rt:$n[1].DateTimeStyles,sn:"AssumeLocal",box:function($v){return H5.box($v,System.Globalization.DateTimeStyles,System.Enum.toStringFn(System.Globalization.DateTimeStyles))}},{a:2,n:"AssumeUniversal",is:!0,t:4,rt:$n[1].DateTimeStyles,sn:"AssumeUniversal",box:function($v){return H5.box($v,System.Globalization.DateTimeStyles,System.Enum.toStringFn(System.Globalization.DateTimeStyles))}},{a:2,n:"NoCurrentDateDefault",is:!0,t:4,rt:$n[1].DateTimeStyles,sn:"NoCurrentDateDefault",box:function($v){return H5.box($v,System.Globalization.DateTimeStyles,System.Enum.toStringFn(System.Globalization.DateTimeStyles))}},{a:2,n:"None",is:!0,t:4,rt:$n[1].DateTimeStyles,sn:"None",box:function($v){return H5.box($v,System.Globalization.DateTimeStyles,System.Enum.toStringFn(System.Globalization.DateTimeStyles))}},{a:2,n:"RoundtripKind",is:!0,t:4,rt:$n[1].DateTimeStyles,sn:"RoundtripKind",box:function($v){return H5.box($v,System.Globalization.DateTimeStyles,System.Enum.toStringFn(System.Globalization.DateTimeStyles))}}]}},$n);$m("System.Globalization.DaylightTime",function(){return{att:1048577,a:2,m:[{a:1,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].DateTime,$n[0].DateTime,$n[0].TimeSpan],pi:[{n:"start",pt:$n[0].DateTime,ps:0},{n:"end",pt:$n[0].DateTime,ps:1},{n:"delta",pt:$n[0].TimeSpan,ps:2}],sn:"$ctor1"},{a:2,n:"Delta",t:16,rt:$n[0].TimeSpan,g:{a:2,n:"get_Delta",t:8,rt:$n[0].TimeSpan,fg:"Delta"},fn:"Delta"},{a:2,n:"End",t:16,rt:$n[0].DateTime,g:{a:2,n:"get_End",t:8,rt:$n[0].DateTime,fg:"End",box:function($v){return H5.box($v,System.DateTime,System.DateTime.format)}},fn:"End"},{a:2,n:"Start",t:16,rt:$n[0].DateTime,g:{a:2,n:"get_Start",t:8,rt:$n[0].DateTime,fg:"Start",box:function($v){return H5.box($v,System.DateTime,System.DateTime.format)}},fn:"Start"},{a:1,n:"_delta",t:4,rt:$n[0].TimeSpan,sn:"_delta",ro:!0},{a:1,n:"_end",t:4,rt:$n[0].DateTime,sn:"_end",ro:!0,box:function($v){return H5.box($v,System.DateTime,System.DateTime.format)}},{a:1,n:"_start",t:4,rt:$n[0].DateTime,sn:"_start",ro:!0,box:function($v){return H5.box($v,System.DateTime,System.DateTime.format)}}]}},$n);$m("System.Globalization.DaylightTimeStruct",function(){return{att:1048840,a:4,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].DateTime,$n[0].DateTime,$n[0].TimeSpan],pi:[{n:"start",pt:$n[0].DateTime,ps:0},{n:"end",pt:$n[0].DateTime,ps:1},{n:"delta",pt:$n[0].TimeSpan,ps:2}],sn:"$ctor1"},{a:2,n:"Delta",t:4,rt:$n[0].TimeSpan,sn:"Delta",ro:!0},{a:2,n:"End",t:4,rt:$n[0].DateTime,sn:"End",ro:!0,box:function($v){return H5.box($v,System.DateTime,System.DateTime.format)}},{a:2,n:"Start",t:4,rt:$n[0].DateTime,sn:"Start",ro:!0,box:function($v){return H5.box($v,System.DateTime,System.DateTime.format)}}]}},$n);$m("System.Globalization.GlobalizationMode",function(){return{att:1048832,a:4,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:1,n:"GetGlobalizationInvariantMode",is:!0,t:8,sn:"GetGlobalizationInvariantMode",rt:$n[0].Boolean,box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:4,n:"GetInvariantSwitchValue",is:!0,t:8,sn:"GetInvariantSwitchValue",rt:$n[0].Boolean,box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:4,n:"Invariant",is:!0,t:16,rt:$n[0].Boolean,g:{a:4,n:"get_Invariant",t:8,rt:$n[0].Boolean,fg:"Invariant",is:!0,box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},fn:"Invariant"},{a:1,n:"__Property__Initializer__Invariant",is:!0,t:4,rt:$n[0].Boolean,sn:"__Property__Initializer__Invariant",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,backing:!0,n:"k__BackingField",is:!0,t:4,rt:$n[0].Boolean,sn:"Invariant",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}}]}},$n);$m("System.Globalization.SortVersion",function(){return{att:1057025,a:2,at:[new System.SerializableAttribute],m:[{a:2,n:".ctor",t:1,p:[$n[0].Int32,$n[0].Guid],pi:[{n:"fullVersion",pt:$n[0].Int32,ps:0},{n:"sortId",pt:$n[0].Guid,ps:1}],sn:"ctor"},{a:4,n:".ctor",t:1,p:[$n[0].Int32,$n[0].Int32,$n[0].Guid],pi:[{n:"nlsVersion",pt:$n[0].Int32,ps:0},{n:"effectiveId",pt:$n[0].Int32,ps:1},{n:"customVersion",pt:$n[0].Guid,ps:2}],sn:"$ctor1"},{a:2,n:"Equals",t:8,pi:[{n:"other",pt:$n[1].SortVersion,ps:0}],sn:"equalsT",rt:$n[0].Boolean,p:[$n[1].SortVersion],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ov:!0,a:2,n:"Equals",t:8,pi:[{n:"obj",pt:$n[0].Object,ps:0}],sn:"equals",rt:$n[0].Boolean,p:[$n[0].Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ov:!0,a:2,n:"GetHashCode",t:8,sn:"getHashCode",rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"op_Equality",is:!0,t:8,pi:[{n:"left",pt:$n[1].SortVersion,ps:0},{n:"right",pt:$n[1].SortVersion,ps:1}],sn:"op_Equality",rt:$n[0].Boolean,p:[$n[1].SortVersion,$n[1].SortVersion],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"op_Inequality",is:!0,t:8,pi:[{n:"left",pt:$n[1].SortVersion,ps:0},{n:"right",pt:$n[1].SortVersion,ps:1}],sn:"op_Inequality",rt:$n[0].Boolean,p:[$n[1].SortVersion,$n[1].SortVersion],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"FullVersion",t:16,rt:$n[0].Int32,g:{a:2,n:"get_FullVersion",t:8,rt:$n[0].Int32,fg:"FullVersion",box:function($v){return H5.box($v,System.Int32)}},fn:"FullVersion"},{a:2,n:"SortId",t:16,rt:$n[0].Guid,g:{a:2,n:"get_SortId",t:8,rt:$n[0].Guid,fg:"SortId"},fn:"SortId"},{a:1,n:"m_NlsVersion",t:4,rt:$n[0].Int32,sn:"m_NlsVersion",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"m_SortId",t:4,rt:$n[0].Guid,sn:"m_SortId"}]}},$n);$m("System.Globalization.UnicodeCategory",function(){return{att:257,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:"ClosePunctuation",is:!0,t:4,rt:$n[1].UnicodeCategory,sn:"ClosePunctuation",box:function($v){return H5.box($v,System.Globalization.UnicodeCategory,System.Enum.toStringFn(System.Globalization.UnicodeCategory))}},{a:2,n:"ConnectorPunctuation",is:!0,t:4,rt:$n[1].UnicodeCategory,sn:"ConnectorPunctuation",box:function($v){return H5.box($v,System.Globalization.UnicodeCategory,System.Enum.toStringFn(System.Globalization.UnicodeCategory))}},{a:2,n:"Control",is:!0,t:4,rt:$n[1].UnicodeCategory,sn:"Control",box:function($v){return H5.box($v,System.Globalization.UnicodeCategory,System.Enum.toStringFn(System.Globalization.UnicodeCategory))}},{a:2,n:"CurrencySymbol",is:!0,t:4,rt:$n[1].UnicodeCategory,sn:"CurrencySymbol",box:function($v){return H5.box($v,System.Globalization.UnicodeCategory,System.Enum.toStringFn(System.Globalization.UnicodeCategory))}},{a:2,n:"DashPunctuation",is:!0,t:4,rt:$n[1].UnicodeCategory,sn:"DashPunctuation",box:function($v){return H5.box($v,System.Globalization.UnicodeCategory,System.Enum.toStringFn(System.Globalization.UnicodeCategory))}},{a:2,n:"DecimalDigitNumber",is:!0,t:4,rt:$n[1].UnicodeCategory,sn:"DecimalDigitNumber",box:function($v){return H5.box($v,System.Globalization.UnicodeCategory,System.Enum.toStringFn(System.Globalization.UnicodeCategory))}},{a:2,n:"EnclosingMark",is:!0,t:4,rt:$n[1].UnicodeCategory,sn:"EnclosingMark",box:function($v){return H5.box($v,System.Globalization.UnicodeCategory,System.Enum.toStringFn(System.Globalization.UnicodeCategory))}},{a:2,n:"FinalQuotePunctuation",is:!0,t:4,rt:$n[1].UnicodeCategory,sn:"FinalQuotePunctuation",box:function($v){return H5.box($v,System.Globalization.UnicodeCategory,System.Enum.toStringFn(System.Globalization.UnicodeCategory))}},{a:2,n:"Format",is:!0,t:4,rt:$n[1].UnicodeCategory,sn:"Format",box:function($v){return H5.box($v,System.Globalization.UnicodeCategory,System.Enum.toStringFn(System.Globalization.UnicodeCategory))}},{a:2,n:"InitialQuotePunctuation",is:!0,t:4,rt:$n[1].UnicodeCategory,sn:"InitialQuotePunctuation",box:function($v){return H5.box($v,System.Globalization.UnicodeCategory,System.Enum.toStringFn(System.Globalization.UnicodeCategory))}},{a:2,n:"LetterNumber",is:!0,t:4,rt:$n[1].UnicodeCategory,sn:"LetterNumber",box:function($v){return H5.box($v,System.Globalization.UnicodeCategory,System.Enum.toStringFn(System.Globalization.UnicodeCategory))}},{a:2,n:"LineSeparator",is:!0,t:4,rt:$n[1].UnicodeCategory,sn:"LineSeparator",box:function($v){return H5.box($v,System.Globalization.UnicodeCategory,System.Enum.toStringFn(System.Globalization.UnicodeCategory))}},{a:2,n:"LowercaseLetter",is:!0,t:4,rt:$n[1].UnicodeCategory,sn:"LowercaseLetter",box:function($v){return H5.box($v,System.Globalization.UnicodeCategory,System.Enum.toStringFn(System.Globalization.UnicodeCategory))}},{a:2,n:"MathSymbol",is:!0,t:4,rt:$n[1].UnicodeCategory,sn:"MathSymbol",box:function($v){return H5.box($v,System.Globalization.UnicodeCategory,System.Enum.toStringFn(System.Globalization.UnicodeCategory))}},{a:2,n:"ModifierLetter",is:!0,t:4,rt:$n[1].UnicodeCategory,sn:"ModifierLetter",box:function($v){return H5.box($v,System.Globalization.UnicodeCategory,System.Enum.toStringFn(System.Globalization.UnicodeCategory))}},{a:2,n:"ModifierSymbol",is:!0,t:4,rt:$n[1].UnicodeCategory,sn:"ModifierSymbol",box:function($v){return H5.box($v,System.Globalization.UnicodeCategory,System.Enum.toStringFn(System.Globalization.UnicodeCategory))}},{a:2,n:"NonSpacingMark",is:!0,t:4,rt:$n[1].UnicodeCategory,sn:"NonSpacingMark",box:function($v){return H5.box($v,System.Globalization.UnicodeCategory,System.Enum.toStringFn(System.Globalization.UnicodeCategory))}},{a:2,n:"OpenPunctuation",is:!0,t:4,rt:$n[1].UnicodeCategory,sn:"OpenPunctuation",box:function($v){return H5.box($v,System.Globalization.UnicodeCategory,System.Enum.toStringFn(System.Globalization.UnicodeCategory))}},{a:2,n:"OtherLetter",is:!0,t:4,rt:$n[1].UnicodeCategory,sn:"OtherLetter",box:function($v){return H5.box($v,System.Globalization.UnicodeCategory,System.Enum.toStringFn(System.Globalization.UnicodeCategory))}},{a:2,n:"OtherNotAssigned",is:!0,t:4,rt:$n[1].UnicodeCategory,sn:"OtherNotAssigned",box:function($v){return H5.box($v,System.Globalization.UnicodeCategory,System.Enum.toStringFn(System.Globalization.UnicodeCategory))}},{a:2,n:"OtherNumber",is:!0,t:4,rt:$n[1].UnicodeCategory,sn:"OtherNumber",box:function($v){return H5.box($v,System.Globalization.UnicodeCategory,System.Enum.toStringFn(System.Globalization.UnicodeCategory))}},{a:2,n:"OtherPunctuation",is:!0,t:4,rt:$n[1].UnicodeCategory,sn:"OtherPunctuation",box:function($v){return H5.box($v,System.Globalization.UnicodeCategory,System.Enum.toStringFn(System.Globalization.UnicodeCategory))}},{a:2,n:"OtherSymbol",is:!0,t:4,rt:$n[1].UnicodeCategory,sn:"OtherSymbol",box:function($v){return H5.box($v,System.Globalization.UnicodeCategory,System.Enum.toStringFn(System.Globalization.UnicodeCategory))}},{a:2,n:"ParagraphSeparator",is:!0,t:4,rt:$n[1].UnicodeCategory,sn:"ParagraphSeparator",box:function($v){return H5.box($v,System.Globalization.UnicodeCategory,System.Enum.toStringFn(System.Globalization.UnicodeCategory))}},{a:2,n:"PrivateUse",is:!0,t:4,rt:$n[1].UnicodeCategory,sn:"PrivateUse",box:function($v){return H5.box($v,System.Globalization.UnicodeCategory,System.Enum.toStringFn(System.Globalization.UnicodeCategory))}},{a:2,n:"SpaceSeparator",is:!0,t:4,rt:$n[1].UnicodeCategory,sn:"SpaceSeparator",box:function($v){return H5.box($v,System.Globalization.UnicodeCategory,System.Enum.toStringFn(System.Globalization.UnicodeCategory))}},{a:2,n:"SpacingCombiningMark",is:!0,t:4,rt:$n[1].UnicodeCategory,sn:"SpacingCombiningMark",box:function($v){return H5.box($v,System.Globalization.UnicodeCategory,System.Enum.toStringFn(System.Globalization.UnicodeCategory))}},{a:2,n:"Surrogate",is:!0,t:4,rt:$n[1].UnicodeCategory,sn:"Surrogate",box:function($v){return H5.box($v,System.Globalization.UnicodeCategory,System.Enum.toStringFn(System.Globalization.UnicodeCategory))}},{a:2,n:"TitlecaseLetter",is:!0,t:4,rt:$n[1].UnicodeCategory,sn:"TitlecaseLetter",box:function($v){return H5.box($v,System.Globalization.UnicodeCategory,System.Enum.toStringFn(System.Globalization.UnicodeCategory))}},{a:2,n:"UppercaseLetter",is:!0,t:4,rt:$n[1].UnicodeCategory,sn:"UppercaseLetter",box:function($v){return H5.box($v,System.Globalization.UnicodeCategory,System.Enum.toStringFn(System.Globalization.UnicodeCategory))}}]}},$n);$m("System.Globalization.CultureInfo",function(){return{att:1048577,a:2,m:[{a:2,n:".ctor",t:1,p:[$n[0].String],pi:[{n:"name",pt:$n[0].String,ps:0}],sn:"ctor"},{a:2,n:"Clone",t:8,sn:"clone",rt:$n[0].Object},{a:2,n:"CreateSpecificCulture",is:!0,t:8,pi:[{n:"name",pt:$n[0].String,ps:0}],sn:"getCultureInfo",rt:$n[1].CultureInfo,p:[$n[0].String]},{a:2,n:"GetCultureInfo",is:!0,t:8,pi:[{n:"name",pt:$n[0].String,ps:0}],sn:"getCultureInfo",rt:$n[1].CultureInfo,p:[$n[0].String]},{a:2,n:"GetCultures",is:!0,t:8,sn:"getCultures",rt:System.Array.type(System.Globalization.CultureInfo)},{v:!0,a:2,n:"GetFormat",t:8,pi:[{n:"formatType",pt:$n[0].Type,ps:0}],sn:"getFormat",rt:$n[0].Object,p:[$n[0].Type]},{a:2,n:"CurrentCulture",is:!0,t:16,rt:$n[1].CultureInfo,g:{a:2,n:"get_CurrentCulture",is:!0,t:8,tpc:0,def:function(){return this.getCurrentCulture()},rt:$n[1].CultureInfo},s:{a:2,n:"set_CurrentCulture",is:!0,t:8,pi:[{n:"value",pt:$n[1].CultureInfo,ps:0}],tpc:0,def:function(value){return this.setCurrentCulture(value)},rt:$n[0].Void,p:[$n[1].CultureInfo]}},{a:2,n:"DateTimeFormat",t:16,rt:$n[1].DateTimeFormatInfo,g:{a:2,n:"get_DateTimeFormat",t:8,rt:$n[1].DateTimeFormatInfo,fg:"dateTimeFormat"},s:{a:2,n:"set_DateTimeFormat",t:8,p:[$n[1].DateTimeFormatInfo],rt:$n[0].Void,fs:"dateTimeFormat"},fn:"dateTimeFormat"},{a:2,n:"EnglishName",t:16,rt:$n[0].String,g:{a:2,n:"get_EnglishName",t:8,rt:$n[0].String,fg:"englishName"},s:{a:2,n:"set_EnglishName",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"englishName"},fn:"englishName"},{a:2,n:"InvariantCulture",is:!0,t:16,rt:$n[1].CultureInfo,g:{a:2,n:"get_InvariantCulture",t:8,rt:$n[1].CultureInfo,fg:"invariantCulture",is:!0},fn:"invariantCulture"},{a:2,n:"Name",t:16,rt:$n[0].String,g:{a:2,n:"get_Name",t:8,rt:$n[0].String,fg:"name"},fn:"name"},{a:2,n:"NativeName",t:16,rt:$n[0].String,g:{a:2,n:"get_NativeName",t:8,rt:$n[0].String,fg:"nativeName"},s:{a:2,n:"set_NativeName",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"nativeName"},fn:"nativeName"},{a:2,n:"NumberFormat",t:16,rt:$n[1].NumberFormatInfo,g:{a:2,n:"get_NumberFormat",t:8,rt:$n[1].NumberFormatInfo,fg:"numberFormat"},s:{a:2,n:"set_NumberFormat",t:8,p:[$n[1].NumberFormatInfo],rt:$n[0].Void,fs:"numberFormat"},fn:"numberFormat"},{v:!0,a:2,n:"TextInfo",t:16,rt:$n[1].TextInfo,g:{v:!0,a:2,n:"get_TextInfo",t:8,rt:$n[1].TextInfo,fg:"TextInfo"},fn:"TextInfo"},{a:1,backing:!0,n:"k__BackingField",is:!0,t:4,rt:$n[1].CultureInfo,sn:"CurrentCulture"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[1].DateTimeFormatInfo,sn:"dateTimeFormat"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"englishName"},{a:1,backing:!0,n:"k__BackingField",is:!0,t:4,rt:$n[1].CultureInfo,sn:"invariantCulture"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"name"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"nativeName"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[1].NumberFormatInfo,sn:"numberFormat"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[1].TextInfo,sn:"TextInfo"}]}},$n);$m("System.Globalization.DateTimeFormatInfo",function(){return{att:1048833,a:2,m:[{a:2,n:".ctor",t:1,sn:"ctor"},{a:2,n:"Clone",t:8,sn:"clone",rt:$n[0].Object},{a:2,n:"GetAbbreviatedDayName",t:8,pi:[{n:"dayofweek",pt:$n[0].DayOfWeek,ps:0}],sn:"getAbbreviatedDayName",rt:$n[0].String,p:[$n[0].DayOfWeek]},{a:2,n:"GetAbbreviatedMonthName",t:8,pi:[{n:"month",pt:$n[0].Int32,ps:0}],sn:"getAbbreviatedMonthName",rt:$n[0].String,p:[$n[0].Int32]},{a:2,n:"GetAllDateTimePatterns",t:8,sn:"getAllDateTimePatterns",rt:$n[0].Array.type(System.String)},{a:2,n:"GetAllDateTimePatterns",t:8,pi:[{n:"format",pt:$n[0].Char,ps:0}],sn:"getAllDateTimePatterns",rt:$n[0].Array.type(System.String),p:[$n[0].Char]},{a:2,n:"GetDayName",t:8,pi:[{n:"dayofweek",pt:$n[0].DayOfWeek,ps:0}],sn:"getDayName",rt:$n[0].String,p:[$n[0].DayOfWeek]},{a:2,n:"GetFormat",t:8,pi:[{n:"formatType",pt:$n[0].Type,ps:0}],sn:"getFormat",rt:$n[0].Object,p:[$n[0].Type]},{a:2,n:"GetMonthName",t:8,pi:[{n:"month",pt:$n[0].Int32,ps:0}],sn:"getMonthName",rt:$n[0].String,p:[$n[0].Int32]},{a:2,n:"GetShortestDayName",t:8,pi:[{n:"dayOfWeek",pt:$n[0].DayOfWeek,ps:0}],sn:"getShortestDayName",rt:$n[0].String,p:[$n[0].DayOfWeek]},{a:2,n:"AMDesignator",t:16,rt:$n[0].String,g:{a:2,n:"get_AMDesignator",t:8,rt:$n[0].String,fg:"amDesignator"},s:{a:2,n:"set_AMDesignator",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"amDesignator"},fn:"amDesignator"},{a:2,n:"AbbreviatedDayNames",t:16,rt:$n[0].Array.type(System.String),g:{a:2,n:"get_AbbreviatedDayNames",t:8,rt:$n[0].Array.type(System.String),fg:"abbreviatedDayNames"},s:{a:2,n:"set_AbbreviatedDayNames",t:8,p:[$n[0].Array.type(System.String)],rt:$n[0].Void,fs:"abbreviatedDayNames"},fn:"abbreviatedDayNames"},{a:2,n:"AbbreviatedMonthGenitiveNames",t:16,rt:$n[0].Array.type(System.String),g:{a:2,n:"get_AbbreviatedMonthGenitiveNames",t:8,rt:$n[0].Array.type(System.String),fg:"abbreviatedMonthGenitiveNames"},s:{a:2,n:"set_AbbreviatedMonthGenitiveNames",t:8,p:[$n[0].Array.type(System.String)],rt:$n[0].Void,fs:"abbreviatedMonthGenitiveNames"},fn:"abbreviatedMonthGenitiveNames"},{a:2,n:"AbbreviatedMonthNames",t:16,rt:$n[0].Array.type(System.String),g:{a:2,n:"get_AbbreviatedMonthNames",t:8,rt:$n[0].Array.type(System.String),fg:"abbreviatedMonthNames"},s:{a:2,n:"set_AbbreviatedMonthNames",t:8,p:[$n[0].Array.type(System.String)],rt:$n[0].Void,fs:"abbreviatedMonthNames"},fn:"abbreviatedMonthNames"},{a:2,n:"CurrentInfo",is:!0,t:16,rt:$n[1].DateTimeFormatInfo,g:{a:2,n:"get_CurrentInfo",t:8,rt:$n[1].DateTimeFormatInfo,fg:"currentInfo",is:!0},fn:"currentInfo"},{a:2,n:"DateSeparator",t:16,rt:$n[0].String,g:{a:2,n:"get_DateSeparator",t:8,rt:$n[0].String,fg:"dateSeparator"},s:{a:2,n:"set_DateSeparator",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"dateSeparator"},fn:"dateSeparator"},{a:2,n:"DayNames",t:16,rt:$n[0].Array.type(System.String),g:{a:2,n:"get_DayNames",t:8,rt:$n[0].Array.type(System.String),fg:"dayNames"},s:{a:2,n:"set_DayNames",t:8,p:[$n[0].Array.type(System.String)],rt:$n[0].Void,fs:"dayNames"},fn:"dayNames"},{a:2,n:"FirstDayOfWeek",t:16,rt:$n[0].DayOfWeek,g:{a:2,n:"get_FirstDayOfWeek",t:8,rt:$n[0].DayOfWeek,fg:"firstDayOfWeek",box:function($v){return H5.box($v,System.DayOfWeek,System.Enum.toStringFn(System.DayOfWeek))}},s:{a:2,n:"set_FirstDayOfWeek",t:8,p:[$n[0].DayOfWeek],rt:$n[0].Void,fs:"firstDayOfWeek"},fn:"firstDayOfWeek"},{a:2,n:"FullDateTimePattern",t:16,rt:$n[0].String,g:{a:2,n:"get_FullDateTimePattern",t:8,rt:$n[0].String,fg:"fullDateTimePattern"},s:{a:2,n:"set_FullDateTimePattern",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"fullDateTimePattern"},fn:"fullDateTimePattern"},{a:2,n:"InvariantInfo",is:!0,t:16,rt:$n[1].DateTimeFormatInfo,g:{a:2,n:"get_InvariantInfo",t:8,rt:$n[1].DateTimeFormatInfo,fg:"invariantInfo",is:!0},fn:"invariantInfo"},{a:2,n:"LongDatePattern",t:16,rt:$n[0].String,g:{a:2,n:"get_LongDatePattern",t:8,rt:$n[0].String,fg:"longDatePattern"},s:{a:2,n:"set_LongDatePattern",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"longDatePattern"},fn:"longDatePattern"},{a:2,n:"LongTimePattern",t:16,rt:$n[0].String,g:{a:2,n:"get_LongTimePattern",t:8,rt:$n[0].String,fg:"longTimePattern"},s:{a:2,n:"set_LongTimePattern",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"longTimePattern"},fn:"longTimePattern"},{a:2,n:"MonthDayPattern",t:16,rt:$n[0].String,g:{a:2,n:"get_MonthDayPattern",t:8,rt:$n[0].String,fg:"monthDayPattern"},s:{a:2,n:"set_MonthDayPattern",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"monthDayPattern"},fn:"monthDayPattern"},{a:2,n:"MonthGenitiveNames",t:16,rt:$n[0].Array.type(System.String),g:{a:2,n:"get_MonthGenitiveNames",t:8,rt:$n[0].Array.type(System.String),fg:"monthGenitiveNames"},s:{a:2,n:"set_MonthGenitiveNames",t:8,p:[$n[0].Array.type(System.String)],rt:$n[0].Void,fs:"monthGenitiveNames"},fn:"monthGenitiveNames"},{a:2,n:"MonthNames",t:16,rt:$n[0].Array.type(System.String),g:{a:2,n:"get_MonthNames",t:8,rt:$n[0].Array.type(System.String),fg:"monthNames"},s:{a:2,n:"set_MonthNames",t:8,p:[$n[0].Array.type(System.String)],rt:$n[0].Void,fs:"monthNames"},fn:"monthNames"},{a:2,n:"PMDesignator",t:16,rt:$n[0].String,g:{a:2,n:"get_PMDesignator",t:8,rt:$n[0].String,fg:"pmDesignator"},s:{a:2,n:"set_PMDesignator",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"pmDesignator"},fn:"pmDesignator"},{a:2,n:"RFC1123Pattern",t:16,rt:$n[0].String,g:{a:2,n:"get_RFC1123Pattern",t:8,rt:$n[0].String,fg:"rfc1123Pattern"},s:{a:2,n:"set_RFC1123Pattern",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"rfc1123Pattern"},fn:"rfc1123Pattern"},{a:2,n:"RoundtripFormat",t:16,rt:$n[0].String,g:{a:2,n:"get_RoundtripFormat",t:8,rt:$n[0].String,fg:"roundtripFormat"},s:{a:2,n:"set_RoundtripFormat",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"roundtripFormat"},fn:"roundtripFormat"},{a:2,n:"ShortDatePattern",t:16,rt:$n[0].String,g:{a:2,n:"get_ShortDatePattern",t:8,rt:$n[0].String,fg:"shortDatePattern"},s:{a:2,n:"set_ShortDatePattern",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"shortDatePattern"},fn:"shortDatePattern"},{a:2,n:"ShortTimePattern",t:16,rt:$n[0].String,g:{a:2,n:"get_ShortTimePattern",t:8,rt:$n[0].String,fg:"shortTimePattern"},s:{a:2,n:"set_ShortTimePattern",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"shortTimePattern"},fn:"shortTimePattern"},{a:2,n:"ShortestDayNames",t:16,rt:$n[0].Array.type(System.String),g:{a:2,n:"get_ShortestDayNames",t:8,rt:$n[0].Array.type(System.String),fg:"shortestDayNames"},s:{a:2,n:"set_ShortestDayNames",t:8,p:[$n[0].Array.type(System.String)],rt:$n[0].Void,fs:"shortestDayNames"},fn:"shortestDayNames"},{a:2,n:"SortableDateTimePattern",t:16,rt:$n[0].String,g:{a:2,n:"get_SortableDateTimePattern",t:8,rt:$n[0].String,fg:"sortableDateTimePattern"},s:{a:2,n:"set_SortableDateTimePattern",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"sortableDateTimePattern"},fn:"sortableDateTimePattern"},{a:2,n:"TimeSeparator",t:16,rt:$n[0].String,g:{a:2,n:"get_TimeSeparator",t:8,rt:$n[0].String,fg:"timeSeparator"},s:{a:2,n:"set_TimeSeparator",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"timeSeparator"},fn:"timeSeparator"},{a:2,n:"UniversalSortableDateTimePattern",t:16,rt:$n[0].String,g:{a:2,n:"get_UniversalSortableDateTimePattern",t:8,rt:$n[0].String,fg:"universalSortableDateTimePattern"},s:{a:2,n:"set_UniversalSortableDateTimePattern",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"universalSortableDateTimePattern"},fn:"universalSortableDateTimePattern"},{a:2,n:"YearMonthPattern",t:16,rt:$n[0].String,g:{a:2,n:"get_YearMonthPattern",t:8,rt:$n[0].String,fg:"yearMonthPattern"},s:{a:2,n:"set_YearMonthPattern",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"yearMonthPattern"},fn:"yearMonthPattern"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"amDesignator"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Array.type(System.String),sn:"abbreviatedDayNames"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Array.type(System.String),sn:"abbreviatedMonthGenitiveNames"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Array.type(System.String),sn:"abbreviatedMonthNames"},{a:1,backing:!0,n:"k__BackingField",is:!0,t:4,rt:$n[1].DateTimeFormatInfo,sn:"currentInfo"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"dateSeparator"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Array.type(System.String),sn:"dayNames"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].DayOfWeek,sn:"firstDayOfWeek",box:function($v){return H5.box($v,System.DayOfWeek,System.Enum.toStringFn(System.DayOfWeek))}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"fullDateTimePattern"},{a:1,backing:!0,n:"k__BackingField",is:!0,t:4,rt:$n[1].DateTimeFormatInfo,sn:"invariantInfo"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"longDatePattern"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"longTimePattern"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"monthDayPattern"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Array.type(System.String),sn:"monthGenitiveNames"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Array.type(System.String),sn:"monthNames"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"pmDesignator"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"rfc1123Pattern"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"roundtripFormat"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"shortDatePattern"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"shortTimePattern"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Array.type(System.String),sn:"shortestDayNames"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"sortableDateTimePattern"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"timeSeparator"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"universalSortableDateTimePattern"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"yearMonthPattern"}]}},$n);$m("System.Globalization.NumberFormatInfo",function(){return{att:1048833,a:2,m:[{a:2,n:".ctor",t:1,sn:"ctor"},{a:2,n:"Clone",t:8,sn:"clone",rt:$n[0].Object},{a:2,n:"GetFormat",t:8,pi:[{n:"formatType",pt:$n[0].Type,ps:0}],sn:"getFormat",rt:$n[0].Object,p:[$n[0].Type]},{a:2,n:"CurrencyDecimalDigits",t:16,rt:$n[0].Int32,g:{a:2,n:"get_CurrencyDecimalDigits",t:8,rt:$n[0].Int32,fg:"currencyDecimalDigits",box:function($v){return H5.box($v,System.Int32)}},s:{a:2,n:"set_CurrencyDecimalDigits",t:8,p:[$n[0].Int32],rt:$n[0].Void,fs:"currencyDecimalDigits"},fn:"currencyDecimalDigits"},{a:2,n:"CurrencyDecimalSeparator",t:16,rt:$n[0].String,g:{a:2,n:"get_CurrencyDecimalSeparator",t:8,rt:$n[0].String,fg:"currencyDecimalSeparator"},s:{a:2,n:"set_CurrencyDecimalSeparator",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"currencyDecimalSeparator"},fn:"currencyDecimalSeparator"},{a:2,n:"CurrencyGroupSeparator",t:16,rt:$n[0].String,g:{a:2,n:"get_CurrencyGroupSeparator",t:8,rt:$n[0].String,fg:"currencyGroupSeparator"},s:{a:2,n:"set_CurrencyGroupSeparator",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"currencyGroupSeparator"},fn:"currencyGroupSeparator"},{a:2,n:"CurrencyGroupSizes",t:16,rt:$n[0].Array.type(System.Int32),g:{a:2,n:"get_CurrencyGroupSizes",t:8,rt:$n[0].Array.type(System.Int32),fg:"currencyGroupSizes"},s:{a:2,n:"set_CurrencyGroupSizes",t:8,p:[$n[0].Array.type(System.Int32)],rt:$n[0].Void,fs:"currencyGroupSizes"},fn:"currencyGroupSizes"},{a:2,n:"CurrencyNegativePattern",t:16,rt:$n[0].Int32,g:{a:2,n:"get_CurrencyNegativePattern",t:8,rt:$n[0].Int32,fg:"currencyNegativePattern",box:function($v){return H5.box($v,System.Int32)}},s:{a:2,n:"set_CurrencyNegativePattern",t:8,p:[$n[0].Int32],rt:$n[0].Void,fs:"currencyNegativePattern"},fn:"currencyNegativePattern"},{a:2,n:"CurrencyPositivePattern",t:16,rt:$n[0].Int32,g:{a:2,n:"get_CurrencyPositivePattern",t:8,rt:$n[0].Int32,fg:"currencyPositivePattern",box:function($v){return H5.box($v,System.Int32)}},s:{a:2,n:"set_CurrencyPositivePattern",t:8,p:[$n[0].Int32],rt:$n[0].Void,fs:"currencyPositivePattern"},fn:"currencyPositivePattern"},{a:2,n:"CurrencySymbol",t:16,rt:$n[0].String,g:{a:2,n:"get_CurrencySymbol",t:8,rt:$n[0].String,fg:"currencySymbol"},s:{a:2,n:"set_CurrencySymbol",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"currencySymbol"},fn:"currencySymbol"},{a:2,n:"CurrentInfo",is:!0,t:16,rt:$n[1].NumberFormatInfo,g:{a:2,n:"get_CurrentInfo",t:8,rt:$n[1].NumberFormatInfo,fg:"currentInfo",is:!0},fn:"currentInfo"},{a:2,n:"InvariantInfo",is:!0,t:16,rt:$n[1].NumberFormatInfo,g:{a:2,n:"get_InvariantInfo",t:8,rt:$n[1].NumberFormatInfo,fg:"invariantInfo",is:!0},fn:"invariantInfo"},{a:2,n:"NaNSymbol",t:16,rt:$n[0].String,g:{a:2,n:"get_NaNSymbol",t:8,rt:$n[0].String,fg:"nanSymbol"},s:{a:2,n:"set_NaNSymbol",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"nanSymbol"},fn:"nanSymbol"},{a:2,n:"NegativeInfinitySymbol",t:16,rt:$n[0].String,g:{a:2,n:"get_NegativeInfinitySymbol",t:8,rt:$n[0].String,fg:"negativeInfinitySymbol"},s:{a:2,n:"set_NegativeInfinitySymbol",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"negativeInfinitySymbol"},fn:"negativeInfinitySymbol"},{a:2,n:"NegativeSign",t:16,rt:$n[0].String,g:{a:2,n:"get_NegativeSign",t:8,rt:$n[0].String,fg:"negativeSign"},s:{a:2,n:"set_NegativeSign",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"negativeSign"},fn:"negativeSign"},{a:2,n:"NumberDecimalDigits",t:16,rt:$n[0].Int32,g:{a:2,n:"get_NumberDecimalDigits",t:8,rt:$n[0].Int32,fg:"numberDecimalDigits",box:function($v){return H5.box($v,System.Int32)}},s:{a:2,n:"set_NumberDecimalDigits",t:8,p:[$n[0].Int32],rt:$n[0].Void,fs:"numberDecimalDigits"},fn:"numberDecimalDigits"},{a:2,n:"NumberDecimalSeparator",t:16,rt:$n[0].String,g:{a:2,n:"get_NumberDecimalSeparator",t:8,rt:$n[0].String,fg:"numberDecimalSeparator"},s:{a:2,n:"set_NumberDecimalSeparator",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"numberDecimalSeparator"},fn:"numberDecimalSeparator"},{a:2,n:"NumberGroupSeparator",t:16,rt:$n[0].String,g:{a:2,n:"get_NumberGroupSeparator",t:8,rt:$n[0].String,fg:"numberGroupSeparator"},s:{a:2,n:"set_NumberGroupSeparator",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"numberGroupSeparator"},fn:"numberGroupSeparator"},{a:2,n:"NumberGroupSizes",t:16,rt:$n[0].Array.type(System.Int32),g:{a:2,n:"get_NumberGroupSizes",t:8,rt:$n[0].Array.type(System.Int32),fg:"numberGroupSizes"},s:{a:2,n:"set_NumberGroupSizes",t:8,p:[$n[0].Array.type(System.Int32)],rt:$n[0].Void,fs:"numberGroupSizes"},fn:"numberGroupSizes"},{a:2,n:"PercentDecimalDigits",t:16,rt:$n[0].Int32,g:{a:2,n:"get_PercentDecimalDigits",t:8,rt:$n[0].Int32,fg:"percentDecimalDigits",box:function($v){return H5.box($v,System.Int32)}},s:{a:2,n:"set_PercentDecimalDigits",t:8,p:[$n[0].Int32],rt:$n[0].Void,fs:"percentDecimalDigits"},fn:"percentDecimalDigits"},{a:2,n:"PercentDecimalSeparator",t:16,rt:$n[0].String,g:{a:2,n:"get_PercentDecimalSeparator",t:8,rt:$n[0].String,fg:"percentDecimalSeparator"},s:{a:2,n:"set_PercentDecimalSeparator",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"percentDecimalSeparator"},fn:"percentDecimalSeparator"},{a:2,n:"PercentGroupSeparator",t:16,rt:$n[0].String,g:{a:2,n:"get_PercentGroupSeparator",t:8,rt:$n[0].String,fg:"percentGroupSeparator"},s:{a:2,n:"set_PercentGroupSeparator",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"percentGroupSeparator"},fn:"percentGroupSeparator"},{a:2,n:"PercentGroupSizes",t:16,rt:$n[0].Array.type(System.Int32),g:{a:2,n:"get_PercentGroupSizes",t:8,rt:$n[0].Array.type(System.Int32),fg:"percentGroupSizes"},s:{a:2,n:"set_PercentGroupSizes",t:8,p:[$n[0].Array.type(System.Int32)],rt:$n[0].Void,fs:"percentGroupSizes"},fn:"percentGroupSizes"},{a:2,n:"PercentNegativePattern",t:16,rt:$n[0].Int32,g:{a:2,n:"get_PercentNegativePattern",t:8,rt:$n[0].Int32,fg:"percentNegativePattern",box:function($v){return H5.box($v,System.Int32)}},s:{a:2,n:"set_PercentNegativePattern",t:8,p:[$n[0].Int32],rt:$n[0].Void,fs:"percentNegativePattern"},fn:"percentNegativePattern"},{a:2,n:"PercentPositivePattern",t:16,rt:$n[0].Int32,g:{a:2,n:"get_PercentPositivePattern",t:8,rt:$n[0].Int32,fg:"percentPositivePattern",box:function($v){return H5.box($v,System.Int32)}},s:{a:2,n:"set_PercentPositivePattern",t:8,p:[$n[0].Int32],rt:$n[0].Void,fs:"percentPositivePattern"},fn:"percentPositivePattern"},{a:2,n:"PercentSymbol",t:16,rt:$n[0].String,g:{a:2,n:"get_PercentSymbol",t:8,rt:$n[0].String,fg:"percentSymbol"},s:{a:2,n:"set_PercentSymbol",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"percentSymbol"},fn:"percentSymbol"},{a:2,n:"PositiveInfinitySymbol",t:16,rt:$n[0].String,g:{a:2,n:"get_PositiveInfinitySymbol",t:8,rt:$n[0].String,fg:"positiveInfinitySymbol"},s:{a:2,n:"set_PositiveInfinitySymbol",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"positiveInfinitySymbol"},fn:"positiveInfinitySymbol"},{a:2,n:"PositiveSign",t:16,rt:$n[0].String,g:{a:2,n:"get_PositiveSign",t:8,rt:$n[0].String,fg:"positiveSign"},s:{a:2,n:"set_PositiveSign",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"positiveSign"},fn:"positiveSign"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Int32,sn:"currencyDecimalDigits",box:function($v){return H5.box($v,System.Int32)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"currencyDecimalSeparator"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"currencyGroupSeparator"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Array.type(System.Int32),sn:"currencyGroupSizes"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Int32,sn:"currencyNegativePattern",box:function($v){return H5.box($v,System.Int32)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Int32,sn:"currencyPositivePattern",box:function($v){return H5.box($v,System.Int32)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"currencySymbol"},{a:1,backing:!0,n:"k__BackingField",is:!0,t:4,rt:$n[1].NumberFormatInfo,sn:"currentInfo"},{a:1,backing:!0,n:"k__BackingField",is:!0,t:4,rt:$n[1].NumberFormatInfo,sn:"invariantInfo"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"nanSymbol"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"negativeInfinitySymbol"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"negativeSign"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Int32,sn:"numberDecimalDigits",box:function($v){return H5.box($v,System.Int32)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"numberDecimalSeparator"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"numberGroupSeparator"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Array.type(System.Int32),sn:"numberGroupSizes"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Int32,sn:"percentDecimalDigits",box:function($v){return H5.box($v,System.Int32)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"percentDecimalSeparator"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"percentGroupSeparator"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Array.type(System.Int32),sn:"percentGroupSizes"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Int32,sn:"percentNegativePattern",box:function($v){return H5.box($v,System.Int32)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Int32,sn:"percentPositivePattern",box:function($v){return H5.box($v,System.Int32)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"percentSymbol"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"positiveInfinitySymbol"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"positiveSign"}]}},$n);$m("System.Globalization.TextInfo",function(){return{att:1048577,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{v:!0,a:2,n:"Clone",t:8,sn:"clone",rt:$n[0].Object},{a:1,n:"VerifyWritable",t:8,sn:"VerifyWritable",rt:$n[0].Void},{v:!0,a:2,n:"ANSICodePage",t:16,rt:$n[0].Int32,g:{v:!0,a:2,n:"get_ANSICodePage",t:8,rt:$n[0].Int32,fg:"ANSICodePage",box:function($v){return H5.box($v,System.Int32)}},fn:"ANSICodePage"},{a:2,n:"CultureName",t:16,rt:$n[0].String,g:{a:2,n:"get_CultureName",t:8,rt:$n[0].String,fg:"CultureName"},fn:"CultureName"},{v:!0,a:2,n:"EBCDICCodePage",t:16,rt:$n[0].Int32,g:{v:!0,a:2,n:"get_EBCDICCodePage",t:8,rt:$n[0].Int32,fg:"EBCDICCodePage",box:function($v){return H5.box($v,System.Int32)}},fn:"EBCDICCodePage"},{a:2,n:"IsReadOnly",t:16,rt:$n[0].Boolean,g:{a:2,n:"get_IsReadOnly",t:8,rt:$n[0].Boolean,fg:"IsReadOnly",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},fn:"IsReadOnly"},{a:2,n:"IsRightToLeft",t:16,rt:$n[0].Boolean,g:{a:2,n:"get_IsRightToLeft",t:8,rt:$n[0].Boolean,fg:"IsRightToLeft",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},fn:"IsRightToLeft"},{a:2,n:"LCID",t:16,rt:$n[0].Int32,g:{a:2,n:"get_LCID",t:8,rt:$n[0].Int32,fg:"LCID",box:function($v){return H5.box($v,System.Int32)}},fn:"LCID"},{v:!0,a:2,n:"ListSeparator",t:16,rt:$n[0].String,g:{v:!0,a:2,n:"get_ListSeparator",t:8,rt:$n[0].String,fg:"ListSeparator"},s:{v:!0,a:2,n:"set_ListSeparator",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"ListSeparator"},fn:"ListSeparator"},{v:!0,a:2,n:"MacCodePage",t:16,rt:$n[0].Int32,g:{v:!0,a:2,n:"get_MacCodePage",t:8,rt:$n[0].Int32,fg:"MacCodePage",box:function($v){return H5.box($v,System.Int32)}},fn:"MacCodePage"},{v:!0,a:2,n:"OEMCodePage",t:16,rt:$n[0].Int32,g:{v:!0,a:2,n:"get_OEMCodePage",t:8,rt:$n[0].Int32,fg:"OEMCodePage",box:function($v){return H5.box($v,System.Int32)}},fn:"OEMCodePage"},{a:1,n:"listSeparator",t:4,rt:$n[0].String,sn:"listSeparator"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Int32,sn:"ANSICodePage",box:function($v){return H5.box($v,System.Int32)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"CultureName"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Int32,sn:"EBCDICCodePage",box:function($v){return H5.box($v,System.Int32)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Boolean,sn:"IsReadOnly",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Boolean,sn:"IsRightToLeft",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Int32,sn:"LCID",box:function($v){return H5.box($v,System.Int32)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Int32,sn:"MacCodePage",box:function($v){return H5.box($v,System.Int32)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Int32,sn:"OEMCodePage",box:function($v){return H5.box($v,System.Int32)}}]}},$n);$m("System.ComponentModel.DefaultValueAttribute",function(){return{att:1048577,a:2,m:[{a:2,n:".ctor",t:1,p:[$n[0].Boolean],pi:[{n:"value",pt:$n[0].Boolean,ps:0}],sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].Byte],pi:[{n:"value",pt:$n[0].Byte,ps:0}],sn:"$ctor1"},{a:2,n:".ctor",t:1,p:[$n[0].Char],pi:[{n:"value",pt:$n[0].Char,ps:0}],sn:"$ctor2"},{a:2,n:".ctor",t:1,p:[$n[0].Double],pi:[{n:"value",pt:$n[0].Double,ps:0}],sn:"$ctor3"},{a:2,n:".ctor",t:1,p:[$n[0].Int16],pi:[{n:"value",pt:$n[0].Int16,ps:0}],sn:"$ctor4"},{a:2,n:".ctor",t:1,p:[$n[0].Int32],pi:[{n:"value",pt:$n[0].Int32,ps:0}],sn:"$ctor5"},{a:2,n:".ctor",t:1,p:[$n[0].Int64],pi:[{n:"value",pt:$n[0].Int64,ps:0}],sn:"$ctor6"},{a:2,n:".ctor",t:1,p:[$n[0].Object],pi:[{n:"value",pt:$n[0].Object,ps:0}],sn:"$ctor7"},{a:2,n:".ctor",t:1,p:[$n[0].SByte],pi:[{n:"value",pt:$n[0].SByte,ps:0}],sn:"$ctor8"},{a:2,n:".ctor",t:1,p:[$n[0].Single],pi:[{n:"value",pt:$n[0].Single,ps:0}],sn:"$ctor9"},{a:2,n:".ctor",t:1,p:[$n[0].String],pi:[{n:"value",pt:$n[0].String,ps:0}],sn:"$ctor10"},{a:2,n:".ctor",t:1,p:[$n[0].UInt16],pi:[{n:"value",pt:$n[0].UInt16,ps:0}],sn:"$ctor12"},{a:2,n:".ctor",t:1,p:[$n[0].UInt32],pi:[{n:"value",pt:$n[0].UInt32,ps:0}],sn:"$ctor13"},{a:2,n:".ctor",t:1,p:[$n[0].UInt64],pi:[{n:"value",pt:$n[0].UInt64,ps:0}],sn:"$ctor14"},{a:2,n:".ctor",t:1,p:[$n[0].Type,$n[0].String],pi:[{n:"type",pt:$n[0].Type,ps:0},{n:"value",pt:$n[0].String,ps:1}],sn:"$ctor11"},{ov:!0,a:2,n:"Equals",t:8,pi:[{n:"obj",pt:$n[0].Object,ps:0}],sn:"equals",rt:$n[0].Boolean,p:[$n[0].Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ov:!0,a:2,n:"GetHashCode",t:8,sn:"getHashCode",rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}},{a:3,n:"SetValue",t:8,pi:[{n:"value",pt:$n[0].Object,ps:0}],sn:"setValue",rt:$n[0].Void,p:[$n[0].Object]},{v:!0,a:2,n:"Value",t:16,rt:$n[0].Object,g:{v:!0,a:2,n:"get_Value",t:8,rt:$n[0].Object,fg:"Value"},fn:"Value"},{a:1,n:"_value",t:4,rt:$n[0].Object,sn:"_value"}]}},$n);$m("System.ComponentModel.BrowsableAttribute",function(){return{att:1048833,a:2,m:[{a:2,n:".ctor",t:1,p:[$n[0].Boolean],pi:[{n:"browsable",pt:$n[0].Boolean,ps:0}],sn:"ctor"},{ov:!0,a:2,n:"Equals",t:8,pi:[{n:"obj",pt:$n[0].Object,ps:0}],sn:"equals",rt:$n[0].Boolean,p:[$n[0].Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ov:!0,a:2,n:"GetHashCode",t:8,sn:"getHashCode",rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"Browsable",t:16,rt:$n[0].Boolean,g:{a:2,n:"get_Browsable",t:8,rt:$n[0].Boolean,fg:"Browsable",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},fn:"Browsable"},{a:2,n:"Default",is:!0,t:4,rt:$n[15].BrowsableAttribute,sn:"default",ro:!0},{a:2,n:"No",is:!0,t:4,rt:$n[15].BrowsableAttribute,sn:"no",ro:!0},{a:2,n:"Yes",is:!0,t:4,rt:$n[15].BrowsableAttribute,sn:"yes",ro:!0},{a:1,n:"browsable",t:4,rt:$n[0].Boolean,sn:"browsable",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}}]}},$n);$m("System.Collections.BitArray",function(){return{nested:[$n[6].BitArray.BitArrayEnumeratorSimple],att:1048833,a:2,m:[{a:2,n:".ctor",t:1,p:[$n[0].Array.type(System.Boolean)],pi:[{n:"values",pt:$n[0].Array.type(System.Boolean),ps:0}],sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].Array.type(System.Byte)],pi:[{n:"bytes",pt:$n[0].Array.type(System.Byte),ps:0}],sn:"$ctor1"},{a:2,n:".ctor",t:1,p:[$n[6].BitArray],pi:[{n:"bits",pt:$n[6].BitArray,ps:0}],sn:"$ctor2"},{a:2,n:".ctor",t:1,p:[$n[0].Int32],pi:[{n:"length",pt:$n[0].Int32,ps:0}],sn:"$ctor3"},{a:2,n:".ctor",t:1,p:[$n[0].Array.type(System.Int32)],pi:[{n:"values",pt:$n[0].Array.type(System.Int32),ps:0}],sn:"$ctor5"},{a:2,n:".ctor",t:1,p:[$n[0].Int32,$n[0].Boolean],pi:[{n:"length",pt:$n[0].Int32,ps:0},{n:"defaultValue",pt:$n[0].Boolean,ps:1}],sn:"$ctor4"},{a:2,n:"And",t:8,pi:[{n:"value",pt:$n[6].BitArray,ps:0}],sn:"And",rt:$n[6].BitArray,p:[$n[6].BitArray]},{a:2,n:"Clone",t:8,sn:"clone",rt:$n[0].Object},{a:2,n:"CopyTo",t:8,pi:[{n:"array",pt:Array,ps:0},{n:"index",pt:$n[0].Int32,ps:1}],sn:"copyTo",rt:$n[0].Void,p:[Array,$n[0].Int32]},{a:2,n:"Get",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0}],sn:"Get",rt:$n[0].Boolean,p:[$n[0].Int32],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"GetArrayLength",is:!0,t:8,pi:[{n:"n",pt:$n[0].Int32,ps:0},{n:"div",pt:$n[0].Int32,ps:1}],sn:"GetArrayLength",rt:$n[0].Int32,p:[$n[0].Int32,$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"GetEnumerator",t:8,sn:"GetEnumerator",rt:$n[6].IEnumerator},{a:2,n:"Not",t:8,sn:"Not",rt:$n[6].BitArray},{a:2,n:"Or",t:8,pi:[{n:"value",pt:$n[6].BitArray,ps:0}],sn:"Or",rt:$n[6].BitArray,p:[$n[6].BitArray]},{a:2,n:"Set",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0},{n:"value",pt:$n[0].Boolean,ps:1}],sn:"Set",rt:$n[0].Void,p:[$n[0].Int32,$n[0].Boolean]},{a:2,n:"SetAll",t:8,pi:[{n:"value",pt:$n[0].Boolean,ps:0}],sn:"SetAll",rt:$n[0].Void,p:[$n[0].Boolean]},{a:2,n:"Xor",t:8,pi:[{n:"value",pt:$n[6].BitArray,ps:0}],sn:"Xor",rt:$n[6].BitArray,p:[$n[6].BitArray]},{a:2,n:"Count",t:16,rt:$n[0].Int32,g:{a:2,n:"get_Count",t:8,rt:$n[0].Int32,fg:"Count",box:function($v){return H5.box($v,System.Int32)}},fn:"Count"},{a:2,n:"IsReadOnly",t:16,rt:$n[0].Boolean,g:{a:2,n:"get_IsReadOnly",t:8,rt:$n[0].Boolean,fg:"IsReadOnly",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},fn:"IsReadOnly"},{a:2,n:"Item",t:16,rt:$n[0].Boolean,p:[$n[0].Int32],i:!0,ipi:[{n:"index",pt:$n[0].Int32,ps:0}],g:{a:2,n:"get_Item",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0}],sn:"getItem",rt:$n[0].Boolean,p:[$n[0].Int32],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},s:{a:2,n:"set_Item",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0},{n:"value",pt:$n[0].Boolean,ps:1}],sn:"setItem",rt:$n[0].Void,p:[$n[0].Int32,$n[0].Boolean]}},{a:2,n:"Length",t:16,rt:$n[0].Int32,g:{a:2,n:"get_Length",t:8,rt:$n[0].Int32,fg:"Length",box:function($v){return H5.box($v,System.Int32)}},s:{a:2,n:"set_Length",t:8,p:[$n[0].Int32],rt:$n[0].Void,fs:"Length"},fn:"Length"},{a:1,n:"BitsPerByte",is:!0,t:4,rt:$n[0].Int32,sn:"BitsPerByte",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"BitsPerInt32",is:!0,t:4,rt:$n[0].Int32,sn:"BitsPerInt32",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"BytesPerInt32",is:!0,t:4,rt:$n[0].Int32,sn:"BytesPerInt32",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"_ShrinkThreshold",is:!0,t:4,rt:$n[0].Int32,sn:"_ShrinkThreshold",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"_version",t:4,rt:$n[0].Int32,sn:"_version",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"m_array",t:4,rt:$n[0].Array.type(System.Int32),sn:"m_array"},{a:1,n:"m_length",t:4,rt:$n[0].Int32,sn:"m_length",box:function($v){return H5.box($v,System.Int32)}}]}},$n);$m("System.Collections.BitArray.BitArrayEnumeratorSimple",function(){return{td:$n[6].BitArray,att:1048579,a:1,m:[{a:4,n:".ctor",t:1,p:[$n[6].BitArray],pi:[{n:"bitarray",pt:$n[6].BitArray,ps:0}],sn:"ctor"},{v:!0,a:2,n:"MoveNext",t:8,sn:"moveNext",rt:$n[0].Boolean,box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Reset",t:8,sn:"reset",rt:$n[0].Void},{v:!0,a:2,n:"Current",t:16,rt:$n[0].Object,g:{v:!0,a:2,n:"get_Current",t:8,rt:$n[0].Object,fg:"Current"},fn:"Current"},{a:1,n:"bitarray",t:4,rt:$n[6].BitArray,sn:"bitarray"},{a:1,n:"currentElement",t:4,rt:$n[0].Boolean,sn:"currentElement",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"index",t:4,rt:$n[0].Int32,sn:"index",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"version",t:4,rt:$n[0].Int32,sn:"version",box:function($v){return H5.box($v,System.Int32)}}]}},$n);$m("System.Collections.DictionaryEntry",function(){return{att:1057033,a:2,at:[new System.SerializableAttribute],m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].Object,$n[0].Object],pi:[{n:"key",pt:$n[0].Object,ps:0},{n:"value",pt:$n[0].Object,ps:1}],sn:"$ctor1"},{a:2,n:"Key",t:16,rt:$n[0].Object,g:{a:2,n:"get_Key",t:8,rt:$n[0].Object,fg:"Key"},s:{a:2,n:"set_Key",t:8,p:[$n[0].Object],rt:$n[0].Void,fs:"Key"},fn:"Key"},{a:2,n:"Value",t:16,rt:$n[0].Object,g:{a:2,n:"get_Value",t:8,rt:$n[0].Object,fg:"Value"},s:{a:2,n:"set_Value",t:8,p:[$n[0].Object],rt:$n[0].Void,fs:"Value"},fn:"Value"},{a:1,n:"_key",t:4,rt:$n[0].Object,sn:"_key"},{a:1,n:"_value",t:4,rt:$n[0].Object,sn:"_value"}]}},$n);$m("System.Collections.IDictionaryEnumerator",function(){return{att:1048737,a:2,m:[{ab:!0,a:2,n:"Entry",t:16,rt:$n[6].DictionaryEntry,g:{ab:!0,a:2,n:"get_Entry",t:8,rt:$n[6].DictionaryEntry,fg:"System$Collections$IDictionaryEnumerator$Entry"},fn:"System$Collections$IDictionaryEnumerator$Entry"},{ab:!0,a:2,n:"Key",t:16,rt:$n[0].Object,g:{ab:!0,a:2,n:"get_Key",t:8,rt:$n[0].Object,fg:"System$Collections$IDictionaryEnumerator$Key"},fn:"System$Collections$IDictionaryEnumerator$Key"},{ab:!0,a:2,n:"Value",t:16,rt:$n[0].Object,g:{ab:!0,a:2,n:"get_Value",t:8,rt:$n[0].Object,fg:"System$Collections$IDictionaryEnumerator$Value"},fn:"System$Collections$IDictionaryEnumerator$Value"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[6].DictionaryEntry,sn:"System$Collections$IDictionaryEnumerator$Entry"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Object,sn:"System$Collections$IDictionaryEnumerator$Key"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Object,sn:"System$Collections$IDictionaryEnumerator$Value"}]}},$n);$m("System.Collections.IComparer",function(){return{att:1048737,a:2,m:[{ab:!0,a:2,n:"Compare",t:8,pi:[{n:"x",pt:$n[0].Object,ps:0},{n:"y",pt:$n[0].Object,ps:1}],sn:"System$Collections$IComparer$compare",rt:$n[0].Int32,p:[$n[0].Object,$n[0].Object],box:function($v){return H5.box($v,System.Int32)}}]}},$n);$m("System.Collections.IEnumerator",function(){return{att:1048737,a:2,m:[{ab:!0,a:2,n:"MoveNext",t:8,sn:"System$Collections$IEnumerator$moveNext",rt:$n[0].Boolean,box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ab:!0,a:2,n:"Reset",t:8,sn:"System$Collections$IEnumerator$reset",rt:$n[0].Void},{ab:!0,a:2,n:"Current",t:16,rt:$n[0].Object,g:{ab:!0,a:2,n:"get_Current",t:8,rt:$n[0].Object,fg:"System$Collections$IEnumerator$Current"},fn:"System$Collections$IEnumerator$Current"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Object,sn:"System$Collections$IEnumerator$Current"}]}},$n);$m("System.Collections.IEqualityComparer",function(){return{att:1048737,a:2,m:[{ab:!0,a:2,n:"Equals",t:8,pi:[{n:"x",pt:$n[0].Object,ps:0},{n:"y",pt:$n[0].Object,ps:1}],sn:"System$Collections$IEqualityComparer$equals",rt:$n[0].Boolean,p:[$n[0].Object,$n[0].Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ab:!0,a:2,n:"GetHashCode",t:8,pi:[{n:"obj",pt:$n[0].Object,ps:0}],sn:"System$Collections$IEqualityComparer$getHashCode",rt:$n[0].Int32,p:[$n[0].Object],box:function($v){return H5.box($v,System.Int32)}}]}},$n);$m("System.Collections.IStructuralComparable",function(){return{att:1048737,a:2,m:[{ab:!0,a:2,n:"CompareTo",t:8,pi:[{n:"other",pt:$n[0].Object,ps:0},{n:"comparer",pt:$n[6].IComparer,ps:1}],sn:"System$Collections$IStructuralComparable$CompareTo",rt:$n[0].Int32,p:[$n[0].Object,$n[6].IComparer],box:function($v){return H5.box($v,System.Int32)}}]}},$n);$m("System.Collections.IStructuralEquatable",function(){return{att:1048737,a:2,m:[{ab:!0,a:2,n:"Equals",t:8,pi:[{n:"other",pt:$n[0].Object,ps:0},{n:"comparer",pt:$n[6].IEqualityComparer,ps:1}],sn:"System$Collections$IStructuralEquatable$Equals",rt:$n[0].Boolean,p:[$n[0].Object,$n[6].IEqualityComparer],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ab:!0,a:2,n:"GetHashCode",t:8,pi:[{n:"comparer",pt:$n[6].IEqualityComparer,ps:0}],sn:"System$Collections$IStructuralEquatable$GetHashCode",rt:$n[0].Int32,p:[$n[6].IEqualityComparer],box:function($v){return H5.box($v,System.Int32)}}]}},$n);$m("System.Collections.HashHelpers",function(){return{att:1048960,a:4,s:!0,m:[{a:2,n:"Combine",is:!0,t:8,pi:[{n:"h1",pt:$n[0].Int32,ps:0},{n:"h2",pt:$n[0].Int32,ps:1}],sn:"Combine",rt:$n[0].Int32,p:[$n[0].Int32,$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"ExpandPrime",is:!0,t:8,pi:[{n:"oldSize",pt:$n[0].Int32,ps:0}],sn:"ExpandPrime",rt:$n[0].Int32,p:[$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"GetMinPrime",is:!0,t:8,sn:"GetMinPrime",rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"GetPrime",is:!0,t:8,pi:[{n:"min",pt:$n[0].Int32,ps:0}],sn:"GetPrime",rt:$n[0].Int32,p:[$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"IsPrime",is:!0,t:8,pi:[{n:"candidate",pt:$n[0].Int32,ps:0}],sn:"IsPrime",rt:$n[0].Boolean,p:[$n[0].Int32],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"HashPrime",is:!0,t:4,rt:$n[0].Int32,sn:"HashPrime",box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"MaxPrimeArrayLength",is:!0,t:4,rt:$n[0].Int32,sn:"MaxPrimeArrayLength",box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"RandomSeed",is:!0,t:4,rt:$n[0].Int32,sn:"RandomSeed",ro:!0,box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"primes",is:!0,t:4,rt:$n[0].Array.type(System.Int32),sn:"primes",ro:!0}]}},$n);$m("System.Collections.ICollection",function(){return{att:1048737,a:2,m:[{ab:!0,a:2,n:"CopyTo",t:8,pi:[{n:"array",pt:Array,ps:0},{n:"arrayIndex",pt:$n[0].Int32,ps:1}],tpc:0,def:function(array,arrayIndex){return System.Array.copyTo(this,array,arrayIndex)},rt:$n[0].Void,p:[Array,$n[0].Int32]},{ab:!0,a:2,n:"Count",t:16,rt:$n[0].Int32,g:{ab:!0,a:2,n:"get_Count",t:8,tpc:0,def:function(){return System.Array.getCount(this)},rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}}},{ab:!0,a:2,n:"IsSynchronized",t:16,rt:$n[0].Boolean,g:{ab:!0,a:2,n:"get_IsSynchronized",t:8,rt:$n[0].Boolean,fg:"System$Collections$ICollection$IsSynchronized",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},fn:"System$Collections$ICollection$IsSynchronized"},{ab:!0,a:2,n:"SyncRoot",t:16,rt:$n[0].Object,g:{ab:!0,a:2,n:"get_SyncRoot",t:8,rt:$n[0].Object,fg:"System$Collections$ICollection$SyncRoot"},fn:"System$Collections$ICollection$SyncRoot"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Int32,sn:"System$Collections$ICollection$Count",box:function($v){return H5.box($v,System.Int32)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Boolean,sn:"System$Collections$ICollection$IsSynchronized",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Object,sn:"System$Collections$ICollection$SyncRoot"}]}},$n);$m("System.Collections.IDictionary",function(){return{att:1048737,a:2,m:[{ab:!0,a:2,n:"Add",t:8,pi:[{n:"key",pt:$n[0].Object,ps:0},{n:"value",pt:$n[0].Object,ps:1}],sn:"System$Collections$IDictionary$add",rt:$n[0].Void,p:[$n[0].Object,$n[0].Object]},{ab:!0,a:2,n:"Clear",t:8,sn:"System$Collections$IDictionary$clear",rt:$n[0].Void},{ab:!0,a:2,n:"Contains",t:8,pi:[{n:"key",pt:$n[0].Object,ps:0}],sn:"System$Collections$IDictionary$contains",rt:$n[0].Boolean,p:[$n[0].Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ab:!0,a:2,n:"GetEnumerator",t:8,sn:"System$Collections$IDictionary$GetEnumerator",rt:$n[6].IDictionaryEnumerator},{ab:!0,a:2,n:"Remove",t:8,pi:[{n:"key",pt:$n[0].Object,ps:0}],sn:"System$Collections$IDictionary$remove",rt:$n[0].Void,p:[$n[0].Object]},{ab:!0,a:2,n:"IsFixedSize",t:16,rt:$n[0].Boolean,g:{ab:!0,a:2,n:"get_IsFixedSize",t:8,rt:$n[0].Boolean,fg:"System$Collections$IDictionary$IsFixedSize",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},fn:"System$Collections$IDictionary$IsFixedSize"},{ab:!0,a:2,n:"IsReadOnly",t:16,rt:$n[0].Boolean,g:{ab:!0,a:2,n:"get_IsReadOnly",t:8,rt:$n[0].Boolean,fg:"System$Collections$IDictionary$IsReadOnly",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},fn:"System$Collections$IDictionary$IsReadOnly"},{ab:!0,a:2,n:"Item",t:16,rt:$n[0].Object,p:[$n[0].Object],i:!0,ipi:[{n:"key",pt:$n[0].Object,ps:0}],g:{ab:!0,a:2,n:"get_Item",t:8,pi:[{n:"key",pt:$n[0].Object,ps:0}],sn:"System$Collections$IDictionary$getItem",rt:$n[0].Object,p:[$n[0].Object]},s:{ab:!0,a:2,n:"set_Item",t:8,pi:[{n:"key",pt:$n[0].Object,ps:0},{n:"value",pt:$n[0].Object,ps:1}],sn:"System$Collections$IDictionary$setItem",rt:$n[0].Void,p:[$n[0].Object,$n[0].Object]}},{ab:!0,a:2,n:"Keys",t:16,rt:$n[6].ICollection,g:{ab:!0,a:2,n:"get_Keys",t:8,rt:$n[6].ICollection,fg:"System$Collections$IDictionary$Keys"},fn:"System$Collections$IDictionary$Keys"},{ab:!0,a:2,n:"Values",t:16,rt:$n[6].ICollection,g:{ab:!0,a:2,n:"get_Values",t:8,rt:$n[6].ICollection,fg:"System$Collections$IDictionary$Values"},fn:"System$Collections$IDictionary$Values"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Boolean,sn:"System$Collections$IDictionary$IsFixedSize",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Boolean,sn:"System$Collections$IDictionary$IsReadOnly",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Object,sn:"System$Collections$IDictionary$Item"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[6].ICollection,sn:"System$Collections$IDictionary$Keys"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[6].ICollection,sn:"System$Collections$IDictionary$Values"}]}},$n);$m("System.Collections.IEnumerable",function(){return{att:1048737,a:2,m:[{ab:!0,a:2,n:"GetEnumerator",t:8,tpc:0,def:function(){return H5.getEnumerator(this)},rt:$n[6].IEnumerator}]}},$n);$m("System.Collections.IList",function(){return{att:1048737,a:2,m:[{ab:!0,a:2,n:"Add",t:8,pi:[{n:"value",pt:$n[0].Object,ps:0}],tpc:0,def:function(value){return System.Array.add(this,value,Object)},rt:$n[0].Int32,p:[$n[0].Object],box:function($v){return H5.box($v,System.Int32)}},{ab:!0,a:2,n:"Clear",t:8,tpc:0,def:function(){return System.Array.clear(this,Object)},rt:$n[0].Void},{ab:!0,a:2,n:"Contains",t:8,pi:[{n:"value",pt:$n[0].Object,ps:0}],tpc:0,def:function(value){return System.Array.contains(this,value)},rt:$n[0].Boolean,p:[$n[0].Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ab:!0,a:2,n:"IndexOf",t:8,pi:[{n:"value",pt:$n[0].Object,ps:0}],tpc:0,def:function(value){return System.Array.indexOf(this,value,0,null)},rt:$n[0].Int32,p:[$n[0].Object],box:function($v){return H5.box($v,System.Int32)}},{ab:!0,a:2,n:"Insert",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0},{n:"value",pt:$n[0].Object,ps:1}],tpc:0,def:function(index,value){return System.Array.insert(this,index,value,Object)},rt:$n[0].Void,p:[$n[0].Int32,$n[0].Object]},{ab:!0,a:2,n:"Remove",t:8,pi:[{n:"value",pt:$n[0].Object,ps:0}],tpc:0,def:function(value){return System.Array.remove(this,value,Object)},rt:$n[0].Void,p:[$n[0].Object]},{ab:!0,a:2,n:"RemoveAt",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0}],tpc:0,def:function(index){return System.Array.removeAt(this,index,Object)},rt:$n[0].Void,p:[$n[0].Int32]},{ab:!0,a:2,n:"IsFixedSize",t:16,rt:$n[0].Boolean,g:{ab:!0,a:2,n:"get_IsFixedSize",t:8,tpc:0,def:function(){return System.Array.isFixedSize(this)},rt:$n[0].Boolean,box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}}},{ab:!0,a:2,n:"IsReadOnly",t:16,rt:$n[0].Boolean,g:{ab:!0,a:2,n:"get_IsReadOnly",t:8,tpc:0,def:function(){return System.Array.getIsReadOnly(this,Object)},rt:$n[0].Boolean,box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}}},{ab:!0,a:2,n:"Item",t:16,rt:$n[0].Object,p:[$n[0].Int32],i:!0,ipi:[{n:"index",pt:$n[0].Int32,ps:0}],g:{ab:!0,a:2,n:"get_Item",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0}],tpc:0,def:function(index){return System.Array.getItem(this,index)},rt:$n[0].Object,p:[$n[0].Int32]},s:{ab:!0,a:2,n:"set_Item",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0},{n:"value",pt:$n[0].Object,ps:1}],tpc:0,def:function(index,value){return System.Array.setItem(this,index,value)},rt:$n[0].Void,p:[$n[0].Int32,$n[0].Object]}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Boolean,sn:"System$Collections$IList$IsFixedSize",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Boolean,sn:"System$Collections$IList$IsReadOnly",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Object,sn:"System$Collections$IList$Item"}]}},$n);$m("System.Collections.KeyValuePairs",function(){return{att:1048576,a:4,m:[{a:2,n:".ctor",t:1,p:[$n[0].Object,$n[0].Object],pi:[{n:"key",pt:$n[0].Object,ps:0},{n:"value",pt:$n[0].Object,ps:1}],sn:"ctor"},{a:2,n:"Key",t:16,rt:$n[0].Object,g:{a:2,n:"get_Key",t:8,rt:$n[0].Object,fg:"Key"},fn:"Key"},{a:2,n:"Value",t:16,rt:$n[0].Object,g:{a:2,n:"get_Value",t:8,rt:$n[0].Object,fg:"Value"},fn:"Value"},{a:1,n:"key",t:4,rt:$n[0].Object,sn:"key"},{a:1,n:"value",t:4,rt:$n[0].Object,sn:"value"}]}},$n);$m("System.Collections.SortedList",function(){return{nested:[$n[6].SortedList.SyncSortedList,$n[6].SortedList.SortedListEnumerator,$n[6].SortedList.KeyList,$n[6].SortedList.ValueList,$n[6].SortedList.SortedListDebugView],att:1048577,a:2,m:[{a:2,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[6].IComparer],pi:[{n:"comparer",pt:$n[6].IComparer,ps:0}],sn:"$ctor1"},{a:2,n:".ctor",t:1,p:[$n[6].IDictionary],pi:[{n:"d",pt:$n[6].IDictionary,ps:0}],sn:"$ctor3"},{a:2,n:".ctor",t:1,p:[$n[0].Int32],pi:[{n:"initialCapacity",pt:$n[0].Int32,ps:0}],sn:"$ctor5"},{a:2,n:".ctor",t:1,p:[$n[6].IComparer,$n[0].Int32],pi:[{n:"comparer",pt:$n[6].IComparer,ps:0},{n:"capacity",pt:$n[0].Int32,ps:1}],sn:"$ctor2"},{a:2,n:".ctor",t:1,p:[$n[6].IDictionary,$n[6].IComparer],pi:[{n:"d",pt:$n[6].IDictionary,ps:0},{n:"comparer",pt:$n[6].IComparer,ps:1}],sn:"$ctor4"},{v:!0,a:2,n:"Add",t:8,pi:[{n:"key",pt:$n[0].Object,ps:0},{n:"value",pt:$n[0].Object,ps:1}],sn:"add",rt:$n[0].Void,p:[$n[0].Object,$n[0].Object]},{v:!0,a:2,n:"Clear",t:8,sn:"clear",rt:$n[0].Void},{v:!0,a:2,n:"Clone",t:8,sn:"clone",rt:$n[0].Object},{v:!0,a:2,n:"Contains",t:8,pi:[{n:"key",pt:$n[0].Object,ps:0}],sn:"contains",rt:$n[0].Boolean,p:[$n[0].Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{v:!0,a:2,n:"ContainsKey",t:8,pi:[{n:"key",pt:$n[0].Object,ps:0}],sn:"ContainsKey",rt:$n[0].Boolean,p:[$n[0].Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{v:!0,a:2,n:"ContainsValue",t:8,pi:[{n:"value",pt:$n[0].Object,ps:0}],sn:"ContainsValue",rt:$n[0].Boolean,p:[$n[0].Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{v:!0,a:2,n:"CopyTo",t:8,pi:[{n:"array",pt:Array,ps:0},{n:"arrayIndex",pt:$n[0].Int32,ps:1}],sn:"copyTo",rt:$n[0].Void,p:[Array,$n[0].Int32]},{a:1,n:"EnsureCapacity",t:8,pi:[{n:"min",pt:$n[0].Int32,ps:0}],sn:"EnsureCapacity",rt:$n[0].Void,p:[$n[0].Int32]},{v:!0,a:2,n:"GetByIndex",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0}],sn:"GetByIndex",rt:$n[0].Object,p:[$n[0].Int32]},{v:!0,a:2,n:"GetEnumerator",t:8,sn:"GetEnumerator",rt:$n[6].IDictionaryEnumerator},{v:!0,a:2,n:"GetKey",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0}],sn:"GetKey",rt:$n[0].Object,p:[$n[0].Int32]},{v:!0,a:2,n:"GetKeyList",t:8,sn:"GetKeyList",rt:$n[6].IList},{v:!0,a:2,n:"GetValueList",t:8,sn:"GetValueList",rt:$n[6].IList},{v:!0,a:2,n:"IndexOfKey",t:8,pi:[{n:"key",pt:$n[0].Object,ps:0}],sn:"IndexOfKey",rt:$n[0].Int32,p:[$n[0].Object],box:function($v){return H5.box($v,System.Int32)}},{v:!0,a:2,n:"IndexOfValue",t:8,pi:[{n:"value",pt:$n[0].Object,ps:0}],sn:"IndexOfValue",rt:$n[0].Int32,p:[$n[0].Object],box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"Init",t:8,sn:"Init",rt:$n[0].Void},{a:1,n:"Insert",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0},{n:"key",pt:$n[0].Object,ps:1},{n:"value",pt:$n[0].Object,ps:2}],sn:"Insert",rt:$n[0].Void,p:[$n[0].Int32,$n[0].Object,$n[0].Object]},{v:!0,a:2,n:"Remove",t:8,pi:[{n:"key",pt:$n[0].Object,ps:0}],sn:"remove",rt:$n[0].Void,p:[$n[0].Object]},{v:!0,a:2,n:"RemoveAt",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0}],sn:"RemoveAt",rt:$n[0].Void,p:[$n[0].Int32]},{v:!0,a:2,n:"SetByIndex",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0},{n:"value",pt:$n[0].Object,ps:1}],sn:"SetByIndex",rt:$n[0].Void,p:[$n[0].Int32,$n[0].Object]},{a:2,n:"Synchronized",is:!0,t:8,pi:[{n:"list",pt:$n[6].SortedList,ps:0}],sn:"Synchronized",rt:$n[6].SortedList,p:[$n[6].SortedList]},{v:!0,a:4,n:"ToKeyValuePairsArray",t:8,sn:"ToKeyValuePairsArray",rt:System.Array.type(System.Collections.KeyValuePairs)},{v:!0,a:2,n:"TrimToSize",t:8,sn:"TrimToSize",rt:$n[0].Void},{v:!0,a:2,n:"Capacity",t:16,rt:$n[0].Int32,g:{v:!0,a:2,n:"get_Capacity",t:8,rt:$n[0].Int32,fg:"Capacity",box:function($v){return H5.box($v,System.Int32)}},s:{v:!0,a:2,n:"set_Capacity",t:8,p:[$n[0].Int32],rt:$n[0].Void,fs:"Capacity"},fn:"Capacity"},{v:!0,a:2,n:"Count",t:16,rt:$n[0].Int32,g:{v:!0,a:2,n:"get_Count",t:8,rt:$n[0].Int32,fg:"Count",box:function($v){return H5.box($v,System.Int32)}},fn:"Count"},{v:!0,a:2,n:"IsFixedSize",t:16,rt:$n[0].Boolean,g:{v:!0,a:2,n:"get_IsFixedSize",t:8,rt:$n[0].Boolean,fg:"IsFixedSize",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},fn:"IsFixedSize"},{v:!0,a:2,n:"IsReadOnly",t:16,rt:$n[0].Boolean,g:{v:!0,a:2,n:"get_IsReadOnly",t:8,rt:$n[0].Boolean,fg:"IsReadOnly",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},fn:"IsReadOnly"},{v:!0,a:2,n:"IsSynchronized",t:16,rt:$n[0].Boolean,g:{v:!0,a:2,n:"get_IsSynchronized",t:8,rt:$n[0].Boolean,fg:"IsSynchronized",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},fn:"IsSynchronized"},{v:!0,a:2,n:"Item",t:16,rt:$n[0].Object,p:[$n[0].Object],i:!0,ipi:[{n:"key",pt:$n[0].Object,ps:0}],g:{v:!0,a:2,n:"get_Item",t:8,pi:[{n:"key",pt:$n[0].Object,ps:0}],sn:"getItem",rt:$n[0].Object,p:[$n[0].Object]},s:{v:!0,a:2,n:"set_Item",t:8,pi:[{n:"key",pt:$n[0].Object,ps:0},{n:"value",pt:$n[0].Object,ps:1}],sn:"setItem",rt:$n[0].Void,p:[$n[0].Object,$n[0].Object]}},{v:!0,a:2,n:"Keys",t:16,rt:$n[6].ICollection,g:{v:!0,a:2,n:"get_Keys",t:8,rt:$n[6].ICollection,fg:"Keys"},fn:"Keys"},{v:!0,a:2,n:"SyncRoot",t:16,rt:$n[0].Object,g:{v:!0,a:2,n:"get_SyncRoot",t:8,rt:$n[0].Object,fg:"SyncRoot"},fn:"SyncRoot"},{v:!0,a:2,n:"Values",t:16,rt:$n[6].ICollection,g:{v:!0,a:2,n:"get_Values",t:8,rt:$n[6].ICollection,fg:"Values"},fn:"Values"},{a:1,n:"_size",t:4,rt:$n[0].Int32,sn:"_size",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"comparer",t:4,rt:$n[6].IComparer,sn:"comparer"},{a:1,n:"emptyArray",is:!0,t:4,rt:$n[0].Array.type(System.Object),sn:"emptyArray"},{a:1,n:"keyList",t:4,rt:$n[6].SortedList.KeyList,sn:"keyList"},{a:1,n:"keys",t:4,rt:$n[0].Array.type(System.Object),sn:"keys"},{a:1,n:"valueList",t:4,rt:$n[6].SortedList.ValueList,sn:"valueList"},{a:1,n:"values",t:4,rt:$n[0].Array.type(System.Object),sn:"values"},{a:1,n:"version",t:4,rt:$n[0].Int32,sn:"version",box:function($v){return H5.box($v,System.Int32)}}]}},$n);$m("System.Collections.SortedList.SyncSortedList",function(){return{td:$n[6].SortedList,att:1056771,a:1,at:[new System.SerializableAttribute],m:[{a:4,n:".ctor",t:1,p:[$n[6].SortedList],pi:[{n:"list",pt:$n[6].SortedList,ps:0}],sn:"ctor"},{ov:!0,a:2,n:"Add",t:8,pi:[{n:"key",pt:$n[0].Object,ps:0},{n:"value",pt:$n[0].Object,ps:1}],sn:"add",rt:$n[0].Void,p:[$n[0].Object,$n[0].Object]},{ov:!0,a:2,n:"Clear",t:8,sn:"clear",rt:$n[0].Void},{ov:!0,a:2,n:"Clone",t:8,sn:"clone",rt:$n[0].Object},{ov:!0,a:2,n:"Contains",t:8,pi:[{n:"key",pt:$n[0].Object,ps:0}],sn:"contains",rt:$n[0].Boolean,p:[$n[0].Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ov:!0,a:2,n:"ContainsKey",t:8,pi:[{n:"key",pt:$n[0].Object,ps:0}],sn:"ContainsKey",rt:$n[0].Boolean,p:[$n[0].Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ov:!0,a:2,n:"ContainsValue",t:8,pi:[{n:"key",pt:$n[0].Object,ps:0}],sn:"ContainsValue",rt:$n[0].Boolean,p:[$n[0].Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ov:!0,a:2,n:"CopyTo",t:8,pi:[{n:"array",pt:Array,ps:0},{n:"index",pt:$n[0].Int32,ps:1}],sn:"copyTo",rt:$n[0].Void,p:[Array,$n[0].Int32]},{ov:!0,a:2,n:"GetByIndex",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0}],sn:"GetByIndex",rt:$n[0].Object,p:[$n[0].Int32]},{ov:!0,a:2,n:"GetEnumerator",t:8,sn:"GetEnumerator",rt:$n[6].IDictionaryEnumerator},{ov:!0,a:2,n:"GetKey",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0}],sn:"GetKey",rt:$n[0].Object,p:[$n[0].Int32]},{ov:!0,a:2,n:"GetKeyList",t:8,sn:"GetKeyList",rt:$n[6].IList},{ov:!0,a:2,n:"GetValueList",t:8,sn:"GetValueList",rt:$n[6].IList},{ov:!0,a:2,n:"IndexOfKey",t:8,pi:[{n:"key",pt:$n[0].Object,ps:0}],sn:"IndexOfKey",rt:$n[0].Int32,p:[$n[0].Object],box:function($v){return H5.box($v,System.Int32)}},{ov:!0,a:2,n:"IndexOfValue",t:8,pi:[{n:"value",pt:$n[0].Object,ps:0}],sn:"IndexOfValue",rt:$n[0].Int32,p:[$n[0].Object],box:function($v){return H5.box($v,System.Int32)}},{ov:!0,a:2,n:"Remove",t:8,pi:[{n:"key",pt:$n[0].Object,ps:0}],sn:"remove",rt:$n[0].Void,p:[$n[0].Object]},{ov:!0,a:2,n:"RemoveAt",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0}],sn:"RemoveAt",rt:$n[0].Void,p:[$n[0].Int32]},{ov:!0,a:2,n:"SetByIndex",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0},{n:"value",pt:$n[0].Object,ps:1}],sn:"SetByIndex",rt:$n[0].Void,p:[$n[0].Int32,$n[0].Object]},{ov:!0,a:4,n:"ToKeyValuePairsArray",t:8,sn:"ToKeyValuePairsArray",rt:System.Array.type(System.Collections.KeyValuePairs)},{ov:!0,a:2,n:"TrimToSize",t:8,sn:"TrimToSize",rt:$n[0].Void},{ov:!0,a:2,n:"Capacity",t:16,rt:$n[0].Int32,g:{ov:!0,a:2,n:"get_Capacity",t:8,rt:$n[0].Int32,fg:"Capacity",box:function($v){return H5.box($v,System.Int32)}},fn:"Capacity"},{ov:!0,a:2,n:"Count",t:16,rt:$n[0].Int32,g:{ov:!0,a:2,n:"get_Count",t:8,rt:$n[0].Int32,fg:"Count",box:function($v){return H5.box($v,System.Int32)}},fn:"Count"},{ov:!0,a:2,n:"IsFixedSize",t:16,rt:$n[0].Boolean,g:{ov:!0,a:2,n:"get_IsFixedSize",t:8,rt:$n[0].Boolean,fg:"IsFixedSize",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},fn:"IsFixedSize"},{ov:!0,a:2,n:"IsReadOnly",t:16,rt:$n[0].Boolean,g:{ov:!0,a:2,n:"get_IsReadOnly",t:8,rt:$n[0].Boolean,fg:"IsReadOnly",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},fn:"IsReadOnly"},{ov:!0,a:2,n:"IsSynchronized",t:16,rt:$n[0].Boolean,g:{ov:!0,a:2,n:"get_IsSynchronized",t:8,rt:$n[0].Boolean,fg:"IsSynchronized",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},fn:"IsSynchronized"},{ov:!0,a:2,n:"Item",t:16,rt:$n[0].Object,p:[$n[0].Object],i:!0,ipi:[{n:"key",pt:$n[0].Object,ps:0}],g:{ov:!0,a:2,n:"get_Item",t:8,pi:[{n:"key",pt:$n[0].Object,ps:0}],sn:"getItem",rt:$n[0].Object,p:[$n[0].Object]},s:{ov:!0,a:2,n:"set_Item",t:8,pi:[{n:"key",pt:$n[0].Object,ps:0},{n:"value",pt:$n[0].Object,ps:1}],sn:"setItem",rt:$n[0].Void,p:[$n[0].Object,$n[0].Object]}},{ov:!0,a:2,n:"SyncRoot",t:16,rt:$n[0].Object,g:{ov:!0,a:2,n:"get_SyncRoot",t:8,rt:$n[0].Object,fg:"SyncRoot"},fn:"SyncRoot"},{a:1,n:"_list",t:4,rt:$n[6].SortedList,sn:"_list"},{a:1,n:"_root",t:4,rt:$n[0].Object,sn:"_root"}]}},$n);$m("System.Collections.SortedList.SortedListEnumerator",function(){return{td:$n[6].SortedList,att:1056771,a:1,at:[new System.SerializableAttribute],m:[{a:4,n:".ctor",t:1,p:[$n[6].SortedList,$n[0].Int32,$n[0].Int32,$n[0].Int32],pi:[{n:"sortedList",pt:$n[6].SortedList,ps:0},{n:"index",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2},{n:"getObjRetType",pt:$n[0].Int32,ps:3}],sn:"ctor"},{a:2,n:"Clone",t:8,sn:"clone",rt:$n[0].Object},{v:!0,a:2,n:"MoveNext",t:8,sn:"moveNext",rt:$n[0].Boolean,box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{v:!0,a:2,n:"Reset",t:8,sn:"reset",rt:$n[0].Void},{v:!0,a:2,n:"Current",t:16,rt:$n[0].Object,g:{v:!0,a:2,n:"get_Current",t:8,rt:$n[0].Object,fg:"Current"},fn:"Current"},{v:!0,a:2,n:"Entry",t:16,rt:$n[6].DictionaryEntry,g:{v:!0,a:2,n:"get_Entry",t:8,rt:$n[6].DictionaryEntry,fg:"Entry"},fn:"Entry"},{v:!0,a:2,n:"Key",t:16,rt:$n[0].Object,g:{v:!0,a:2,n:"get_Key",t:8,rt:$n[0].Object,fg:"Key"},fn:"Key"},{v:!0,a:2,n:"Value",t:16,rt:$n[0].Object,g:{v:!0,a:2,n:"get_Value",t:8,rt:$n[0].Object,fg:"Value"},fn:"Value"},{a:4,n:"DictEntry",is:!0,t:4,rt:$n[0].Int32,sn:"DictEntry",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"Keys",is:!0,t:4,rt:$n[0].Int32,sn:"Keys",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"Values",is:!0,t:4,rt:$n[0].Int32,sn:"Values",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"current",t:4,rt:$n[0].Boolean,sn:"current",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"endIndex",t:4,rt:$n[0].Int32,sn:"endIndex",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"getObjectRetType",t:4,rt:$n[0].Int32,sn:"getObjectRetType",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"index",t:4,rt:$n[0].Int32,sn:"index",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"key",t:4,rt:$n[0].Object,sn:"key"},{a:1,n:"sortedList",t:4,rt:$n[6].SortedList,sn:"sortedList"},{a:1,n:"startIndex",t:4,rt:$n[0].Int32,sn:"startIndex",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"value",t:4,rt:$n[0].Object,sn:"value"},{a:1,n:"version",t:4,rt:$n[0].Int32,sn:"version",box:function($v){return H5.box($v,System.Int32)}}]}},$n);$m("System.Collections.SortedList.KeyList",function(){return{td:$n[6].SortedList,att:1056771,a:1,at:[new System.SerializableAttribute],m:[{a:4,n:".ctor",t:1,p:[$n[6].SortedList],pi:[{n:"sortedList",pt:$n[6].SortedList,ps:0}],sn:"ctor"},{v:!0,a:2,n:"Add",t:8,pi:[{n:"key",pt:$n[0].Object,ps:0}],sn:"add",rt:$n[0].Int32,p:[$n[0].Object],box:function($v){return H5.box($v,System.Int32)}},{v:!0,a:2,n:"Clear",t:8,sn:"clear",rt:$n[0].Void},{v:!0,a:2,n:"Contains",t:8,pi:[{n:"key",pt:$n[0].Object,ps:0}],sn:"contains",rt:$n[0].Boolean,p:[$n[0].Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{v:!0,a:2,n:"CopyTo",t:8,pi:[{n:"array",pt:Array,ps:0},{n:"arrayIndex",pt:$n[0].Int32,ps:1}],sn:"copyTo",rt:$n[0].Void,p:[Array,$n[0].Int32]},{v:!0,a:2,n:"GetEnumerator",t:8,sn:"GetEnumerator",rt:$n[6].IEnumerator},{v:!0,a:2,n:"IndexOf",t:8,pi:[{n:"key",pt:$n[0].Object,ps:0}],sn:"indexOf",rt:$n[0].Int32,p:[$n[0].Object],box:function($v){return H5.box($v,System.Int32)}},{v:!0,a:2,n:"Insert",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0},{n:"value",pt:$n[0].Object,ps:1}],sn:"insert",rt:$n[0].Void,p:[$n[0].Int32,$n[0].Object]},{v:!0,a:2,n:"Remove",t:8,pi:[{n:"key",pt:$n[0].Object,ps:0}],sn:"remove",rt:$n[0].Void,p:[$n[0].Object]},{v:!0,a:2,n:"RemoveAt",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0}],sn:"removeAt",rt:$n[0].Void,p:[$n[0].Int32]},{v:!0,a:2,n:"Count",t:16,rt:$n[0].Int32,g:{v:!0,a:2,n:"get_Count",t:8,rt:$n[0].Int32,fg:"Count",box:function($v){return H5.box($v,System.Int32)}},fn:"Count"},{v:!0,a:2,n:"IsFixedSize",t:16,rt:$n[0].Boolean,g:{v:!0,a:2,n:"get_IsFixedSize",t:8,rt:$n[0].Boolean,fg:"IsFixedSize",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},fn:"IsFixedSize"},{v:!0,a:2,n:"IsReadOnly",t:16,rt:$n[0].Boolean,g:{v:!0,a:2,n:"get_IsReadOnly",t:8,rt:$n[0].Boolean,fg:"IsReadOnly",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},fn:"IsReadOnly"},{v:!0,a:2,n:"IsSynchronized",t:16,rt:$n[0].Boolean,g:{v:!0,a:2,n:"get_IsSynchronized",t:8,rt:$n[0].Boolean,fg:"IsSynchronized",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},fn:"IsSynchronized"},{v:!0,a:2,n:"Item",t:16,rt:$n[0].Object,p:[$n[0].Int32],i:!0,ipi:[{n:"index",pt:$n[0].Int32,ps:0}],g:{v:!0,a:2,n:"get_Item",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0}],sn:"getItem",rt:$n[0].Object,p:[$n[0].Int32]},s:{v:!0,a:2,n:"set_Item",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0},{n:"value",pt:$n[0].Object,ps:1}],sn:"setItem",rt:$n[0].Void,p:[$n[0].Int32,$n[0].Object]}},{v:!0,a:2,n:"SyncRoot",t:16,rt:$n[0].Object,g:{v:!0,a:2,n:"get_SyncRoot",t:8,rt:$n[0].Object,fg:"SyncRoot"},fn:"SyncRoot"},{a:1,n:"sortedList",t:4,rt:$n[6].SortedList,sn:"sortedList"}]}},$n);$m("System.Collections.SortedList.ValueList",function(){return{td:$n[6].SortedList,att:1048579,a:1,m:[{a:4,n:".ctor",t:1,p:[$n[6].SortedList],pi:[{n:"sortedList",pt:$n[6].SortedList,ps:0}],sn:"ctor"},{v:!0,a:2,n:"Add",t:8,pi:[{n:"key",pt:$n[0].Object,ps:0}],sn:"add",rt:$n[0].Int32,p:[$n[0].Object],box:function($v){return H5.box($v,System.Int32)}},{v:!0,a:2,n:"Clear",t:8,sn:"clear",rt:$n[0].Void},{v:!0,a:2,n:"Contains",t:8,pi:[{n:"value",pt:$n[0].Object,ps:0}],sn:"contains",rt:$n[0].Boolean,p:[$n[0].Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{v:!0,a:2,n:"CopyTo",t:8,pi:[{n:"array",pt:Array,ps:0},{n:"arrayIndex",pt:$n[0].Int32,ps:1}],sn:"copyTo",rt:$n[0].Void,p:[Array,$n[0].Int32]},{v:!0,a:2,n:"GetEnumerator",t:8,sn:"GetEnumerator",rt:$n[6].IEnumerator},{v:!0,a:2,n:"IndexOf",t:8,pi:[{n:"value",pt:$n[0].Object,ps:0}],sn:"indexOf",rt:$n[0].Int32,p:[$n[0].Object],box:function($v){return H5.box($v,System.Int32)}},{v:!0,a:2,n:"Insert",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0},{n:"value",pt:$n[0].Object,ps:1}],sn:"insert",rt:$n[0].Void,p:[$n[0].Int32,$n[0].Object]},{v:!0,a:2,n:"Remove",t:8,pi:[{n:"value",pt:$n[0].Object,ps:0}],sn:"remove",rt:$n[0].Void,p:[$n[0].Object]},{v:!0,a:2,n:"RemoveAt",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0}],sn:"removeAt",rt:$n[0].Void,p:[$n[0].Int32]},{v:!0,a:2,n:"Count",t:16,rt:$n[0].Int32,g:{v:!0,a:2,n:"get_Count",t:8,rt:$n[0].Int32,fg:"Count",box:function($v){return H5.box($v,System.Int32)}},fn:"Count"},{v:!0,a:2,n:"IsFixedSize",t:16,rt:$n[0].Boolean,g:{v:!0,a:2,n:"get_IsFixedSize",t:8,rt:$n[0].Boolean,fg:"IsFixedSize",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},fn:"IsFixedSize"},{v:!0,a:2,n:"IsReadOnly",t:16,rt:$n[0].Boolean,g:{v:!0,a:2,n:"get_IsReadOnly",t:8,rt:$n[0].Boolean,fg:"IsReadOnly",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},fn:"IsReadOnly"},{v:!0,a:2,n:"IsSynchronized",t:16,rt:$n[0].Boolean,g:{v:!0,a:2,n:"get_IsSynchronized",t:8,rt:$n[0].Boolean,fg:"IsSynchronized",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},fn:"IsSynchronized"},{v:!0,a:2,n:"Item",t:16,rt:$n[0].Object,p:[$n[0].Int32],i:!0,ipi:[{n:"index",pt:$n[0].Int32,ps:0}],g:{v:!0,a:2,n:"get_Item",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0}],sn:"getItem",rt:$n[0].Object,p:[$n[0].Int32]},s:{v:!0,a:2,n:"set_Item",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0},{n:"value",pt:$n[0].Object,ps:1}],sn:"setItem",rt:$n[0].Void,p:[$n[0].Int32,$n[0].Object]}},{v:!0,a:2,n:"SyncRoot",t:16,rt:$n[0].Object,g:{v:!0,a:2,n:"get_SyncRoot",t:8,rt:$n[0].Object,fg:"SyncRoot"},fn:"SyncRoot"},{a:1,n:"sortedList",t:4,rt:$n[6].SortedList,sn:"sortedList"}]}},$n);$m("System.Collections.SortedList.SortedListDebugView",function(){return{td:$n[6].SortedList,att:1048581,a:4,m:[{a:2,n:".ctor",t:1,p:[$n[6].SortedList],pi:[{n:"sortedList",pt:$n[6].SortedList,ps:0}],sn:"ctor"},{a:2,n:"Items",t:16,rt:System.Array.type(System.Collections.KeyValuePairs),g:{a:2,n:"get_Items",t:8,rt:System.Array.type(System.Collections.KeyValuePairs),fg:"Items"},fn:"Items"},{a:1,n:"sortedList",t:4,rt:$n[6].SortedList,sn:"sortedList"}]}},$n);$m("System.Collections.ObjectModel.Collection$1",function(T){return{att:1056769,a:2,at:[new System.SerializableAttribute],m:[{a:2,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[3].IList$1(T)],pi:[{n:"list",pt:$n[3].IList$1(T),ps:0}],sn:"$ctor1"},{a:2,n:"Add",t:8,pi:[{n:"item",pt:T,ps:0}],sn:"add",rt:$n[0].Void,p:[T]},{a:2,n:"Clear",t:8,sn:"clear",rt:$n[0].Void},{v:!0,a:3,n:"ClearItems",t:8,sn:"ClearItems",rt:$n[0].Void},{a:2,n:"Contains",t:8,pi:[{n:"item",pt:T,ps:0}],sn:"contains",rt:$n[0].Boolean,p:[T],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"CopyTo",t:8,pi:[{n:"array",pt:System.Array.type(T),ps:0},{n:"index",pt:$n[0].Int32,ps:1}],sn:"copyTo",rt:$n[0].Void,p:[System.Array.type(T),$n[0].Int32]},{a:2,n:"GetEnumerator",t:8,sn:"GetEnumerator",rt:$n[3].IEnumerator$1(T)},{a:2,n:"IndexOf",t:8,pi:[{n:"item",pt:T,ps:0}],sn:"indexOf",rt:$n[0].Int32,p:[T],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"Insert",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0},{n:"item",pt:T,ps:1}],sn:"insert",rt:$n[0].Void,p:[$n[0].Int32,T]},{v:!0,a:3,n:"InsertItem",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0},{n:"item",pt:T,ps:1}],sn:"InsertItem",rt:$n[0].Void,p:[$n[0].Int32,T]},{a:1,n:"IsCompatibleObject",is:!0,t:8,pi:[{n:"value",pt:$n[0].Object,ps:0}],sn:"IsCompatibleObject",rt:$n[0].Boolean,p:[$n[0].Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Remove",t:8,pi:[{n:"item",pt:T,ps:0}],sn:"remove",rt:$n[0].Boolean,p:[T],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"RemoveAt",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0}],sn:"removeAt",rt:$n[0].Void,p:[$n[0].Int32]},{v:!0,a:3,n:"RemoveItem",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0}],sn:"RemoveItem",rt:$n[0].Void,p:[$n[0].Int32]},{v:!0,a:3,n:"SetItem",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0},{n:"item",pt:T,ps:1}],sn:"SetItem",rt:$n[0].Void,p:[$n[0].Int32,T]},{a:2,n:"Count",t:16,rt:$n[0].Int32,g:{a:2,n:"get_Count",t:8,rt:$n[0].Int32,fg:"Count",box:function($v){return H5.box($v,System.Int32)}},fn:"Count"},{a:2,n:"Item",t:16,rt:T,p:[$n[0].Int32],i:!0,ipi:[{n:"index",pt:$n[0].Int32,ps:0}],g:{a:2,n:"get_Item",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0}],sn:"getItem",rt:T,p:[$n[0].Int32]},s:{a:2,n:"set_Item",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0},{n:"value",pt:T,ps:1}],sn:"setItem",rt:$n[0].Void,p:[$n[0].Int32,T]}},{a:3,n:"Items",t:16,rt:$n[3].IList$1(T),g:{a:3,n:"get_Items",t:8,rt:$n[3].IList$1(T),fg:"Items"},fn:"Items"},{a:1,n:"_syncRoot",t:4,rt:$n[0].Object,sn:"_syncRoot"},{a:1,n:"items",t:4,rt:$n[3].IList$1(T),sn:"items"}]}},$n);$m("System.Collections.ObjectModel.ReadOnlyCollection$1",function(T){return{att:1048577,a:2,m:[{a:2,n:".ctor",t:1,p:[$n[3].IList$1(T)],pi:[{n:"list",pt:$n[3].IList$1(T),ps:0}],sn:"ctor"},{a:2,n:"Contains",t:8,pi:[{n:"value",pt:T,ps:0}],sn:"contains",rt:$n[0].Boolean,p:[T],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"CopyTo",t:8,pi:[{n:"array",pt:System.Array.type(T),ps:0},{n:"index",pt:$n[0].Int32,ps:1}],sn:"copyTo",rt:$n[0].Void,p:[System.Array.type(T),$n[0].Int32]},{a:2,n:"GetEnumerator",t:8,sn:"GetEnumerator",rt:$n[3].IEnumerator$1(T)},{a:2,n:"IndexOf",t:8,pi:[{n:"value",pt:T,ps:0}],sn:"indexOf",rt:$n[0].Int32,p:[T],box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"IsCompatibleObject",is:!0,t:8,pi:[{n:"value",pt:$n[0].Object,ps:0}],sn:"IsCompatibleObject",rt:$n[0].Boolean,p:[$n[0].Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Count",t:16,rt:$n[0].Int32,g:{a:2,n:"get_Count",t:8,rt:$n[0].Int32,fg:"Count",box:function($v){return H5.box($v,System.Int32)}},fn:"Count"},{a:2,n:"Item",t:16,rt:T,p:[$n[0].Int32],i:!0,ipi:[{n:"index",pt:$n[0].Int32,ps:0}],g:{a:2,n:"get_Item",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0}],sn:"getItem",rt:T,p:[$n[0].Int32]}},{a:3,n:"Items",t:16,rt:$n[3].IList$1(T),g:{a:3,n:"get_Items",t:8,rt:$n[3].IList$1(T),fg:"Items"},fn:"Items"},{a:1,n:"list",t:4,rt:$n[3].IList$1(T),sn:"list"}]}},$n);$m("System.Collections.ObjectModel.ReadOnlyDictionary$2",function(TKey,TValue){return{nested:[$n[5].ReadOnlyDictionary$2.DictionaryEnumerator,$n[5].ReadOnlyDictionary$2.KeyCollection,$n[5].ReadOnlyDictionary$2.ValueCollection],att:1048577,a:2,m:[{a:2,n:".ctor",t:1,p:[$n[3].IDictionary$2(TKey,TValue)],pi:[{n:"dictionary",pt:$n[3].IDictionary$2(TKey,TValue),ps:0}],sn:"ctor"},{a:2,n:"ContainsKey",t:8,pi:[{n:"key",pt:TKey,ps:0}],sn:"containsKey",rt:$n[0].Boolean,p:[TKey],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"GetEnumerator",t:8,sn:"GetEnumerator",rt:$n[3].IEnumerator$1(System.Collections.Generic.KeyValuePair$2(TKey,TValue))},{a:1,n:"IsCompatibleKey",is:!0,t:8,pi:[{n:"key",pt:$n[0].Object,ps:0}],sn:"IsCompatibleKey",rt:$n[0].Boolean,p:[$n[0].Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"TryGetValue",t:8,pi:[{n:"key",pt:TKey,ps:0},{n:"value",out:!0,pt:TValue,ps:1}],sn:"tryGetValue",rt:$n[0].Boolean,p:[TKey,TValue],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Count",t:16,rt:$n[0].Int32,g:{a:2,n:"get_Count",t:8,rt:$n[0].Int32,fg:"Count",box:function($v){return H5.box($v,System.Int32)}},fn:"Count"},{a:3,n:"Dictionary",t:16,rt:$n[3].IDictionary$2(TKey,TValue),g:{a:3,n:"get_Dictionary",t:8,rt:$n[3].IDictionary$2(TKey,TValue),fg:"Dictionary"},fn:"Dictionary"},{a:2,n:"Item",t:16,rt:TValue,p:[TKey],i:!0,ipi:[{n:"key",pt:TKey,ps:0}],g:{a:2,n:"get_Item",t:8,pi:[{n:"key",pt:TKey,ps:0}],sn:"getItem",rt:TValue,p:[TKey]}},{a:2,n:"Keys",t:16,rt:$n[5].ReadOnlyDictionary$2.KeyCollection(TKey,TValue),g:{a:2,n:"get_Keys",t:8,rt:$n[5].ReadOnlyDictionary$2.KeyCollection(TKey,TValue),fg:"Keys"},fn:"Keys"},{a:2,n:"Values",t:16,rt:$n[5].ReadOnlyDictionary$2.ValueCollection(TKey,TValue),g:{a:2,n:"get_Values",t:8,rt:$n[5].ReadOnlyDictionary$2.ValueCollection(TKey,TValue),fg:"Values"},fn:"Values"},{a:1,n:"NotSupported_ReadOnlyCollection",is:!0,t:4,rt:$n[0].String,sn:"NotSupported_ReadOnlyCollection"},{a:1,n:"_keys",t:4,rt:$n[5].ReadOnlyDictionary$2.KeyCollection(TKey,TValue),sn:"_keys"},{a:1,n:"_values",t:4,rt:$n[5].ReadOnlyDictionary$2.ValueCollection(TKey,TValue),sn:"_values"},{a:1,n:"m_dictionary",t:4,rt:$n[3].IDictionary$2(TKey,TValue),sn:"m_dictionary",ro:!0}]}},$n);$m("System.Collections.ObjectModel.ReadOnlyDictionary$2.DictionaryEnumerator",function(TKey,TValue){return{td:$n[5].ReadOnlyDictionary$2(TKey,TValue),att:1048843,a:1,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[3].IDictionary$2(TKey,TValue)],pi:[{n:"dictionary",pt:$n[3].IDictionary$2(TKey,TValue),ps:0}],sn:"$ctor1"},{a:2,n:"MoveNext",t:8,sn:"moveNext",rt:$n[0].Boolean,box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Reset",t:8,sn:"reset",rt:$n[0].Void},{a:2,n:"Current",t:16,rt:$n[0].Object,g:{a:2,n:"get_Current",t:8,rt:$n[0].Object,fg:"Current"},fn:"Current"},{a:2,n:"Entry",t:16,rt:$n[6].DictionaryEntry,g:{a:2,n:"get_Entry",t:8,rt:$n[6].DictionaryEntry,fg:"Entry"},fn:"Entry"},{a:2,n:"Key",t:16,rt:$n[0].Object,g:{a:2,n:"get_Key",t:8,rt:$n[0].Object,fg:"Key"},fn:"Key"},{a:2,n:"Value",t:16,rt:$n[0].Object,g:{a:2,n:"get_Value",t:8,rt:$n[0].Object,fg:"Value"},fn:"Value"},{a:1,n:"_dictionary",t:4,rt:$n[3].IDictionary$2(TKey,TValue),sn:"_dictionary",ro:!0},{a:1,n:"_enumerator",t:4,rt:$n[3].IEnumerator$1(System.Collections.Generic.KeyValuePair$2(TKey,TValue)),sn:"_enumerator"}]}},$n);$m("System.Collections.ObjectModel.ReadOnlyDictionary$2.KeyCollection",function(TKey,TValue){return{td:$n[5].ReadOnlyDictionary$2(TKey,TValue),att:1048834,a:2,m:[{a:4,n:".ctor",t:1,p:[$n[3].ICollection$1(TKey)],pi:[{n:"collection",pt:$n[3].ICollection$1(TKey),ps:0}],sn:"ctor"},{a:2,n:"CopyTo",t:8,pi:[{n:"array",pt:System.Array.type(TKey),ps:0},{n:"arrayIndex",pt:$n[0].Int32,ps:1}],sn:"copyTo",rt:$n[0].Void,p:[System.Array.type(TKey),$n[0].Int32]},{a:2,n:"GetEnumerator",t:8,sn:"GetEnumerator",rt:$n[3].IEnumerator$1(TKey)},{a:2,n:"Count",t:16,rt:$n[0].Int32,g:{a:2,n:"get_Count",t:8,rt:$n[0].Int32,fg:"Count",box:function($v){return H5.box($v,System.Int32)}},fn:"Count"},{a:1,n:"_collection",t:4,rt:$n[3].ICollection$1(TKey),sn:"_collection",ro:!0}]}},$n);$m("System.Collections.ObjectModel.ReadOnlyDictionary$2.ValueCollection",function(TKey,TValue){return{td:$n[5].ReadOnlyDictionary$2(TKey,TValue),att:1048834,a:2,m:[{a:4,n:".ctor",t:1,p:[$n[3].ICollection$1(TValue)],pi:[{n:"collection",pt:$n[3].ICollection$1(TValue),ps:0}],sn:"ctor"},{a:2,n:"CopyTo",t:8,pi:[{n:"array",pt:System.Array.type(TValue),ps:0},{n:"arrayIndex",pt:$n[0].Int32,ps:1}],sn:"copyTo",rt:$n[0].Void,p:[System.Array.type(TValue),$n[0].Int32]},{a:2,n:"GetEnumerator",t:8,sn:"GetEnumerator",rt:$n[3].IEnumerator$1(TValue)},{a:2,n:"Count",t:16,rt:$n[0].Int32,g:{a:2,n:"get_Count",t:8,rt:$n[0].Int32,fg:"Count",box:function($v){return H5.box($v,System.Int32)}},fn:"Count"},{a:1,n:"_collection",t:4,rt:$n[3].ICollection$1(TValue),sn:"_collection",ro:!0}]}},$n);$m("System.Collections.ObjectModel.ReadOnlyDictionaryHelpers",function(){return{att:1048960,a:4,s:!0,m:[{a:4,n:"CopyToNonGenericICollectionHelper",is:!0,t:8,pi:[{n:"collection",pt:$n[3].ICollection$1(System.Object),ps:0},{n:"array",pt:Array,ps:1},{n:"index",pt:$n[0].Int32,ps:2}],tpc:1,tprm:["T"],sn:"CopyToNonGenericICollectionHelper",rt:$n[0].Void,p:[$n[3].ICollection$1(System.Object),Array,$n[0].Int32]}]}},$n);$m("System.Collections.Generic.BitHelper",function(){return{att:1048832,a:4,m:[{a:4,n:".ctor",t:1,p:[$n[0].Array.type(System.Int32),$n[0].Int32],pi:[{n:"bitArray",pt:$n[0].Array.type(System.Int32),ps:0},{n:"length",pt:$n[0].Int32,ps:1}],sn:"ctor"},{a:4,n:"IsMarked",t:8,pi:[{n:"bitPosition",pt:$n[0].Int32,ps:0}],sn:"IsMarked",rt:$n[0].Boolean,p:[$n[0].Int32],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:4,n:"MarkBit",t:8,pi:[{n:"bitPosition",pt:$n[0].Int32,ps:0}],sn:"MarkBit",rt:$n[0].Void,p:[$n[0].Int32]},{a:4,n:"ToIntArrayLength",is:!0,t:8,pi:[{n:"n",pt:$n[0].Int32,ps:0}],sn:"ToIntArrayLength",rt:$n[0].Int32,p:[$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"IntSize",is:!0,t:4,rt:$n[0].Byte,sn:"IntSize",box:function($v){return H5.box($v,System.Byte)}},{a:1,n:"MarkedBitFlag",is:!0,t:4,rt:$n[0].Byte,sn:"MarkedBitFlag",box:function($v){return H5.box($v,System.Byte)}},{a:1,n:"_array",t:4,rt:$n[0].Array.type(System.Int32),sn:"_array",ro:!0},{a:1,n:"_length",t:4,rt:$n[0].Int32,sn:"_length",ro:!0,box:function($v){return H5.box($v,System.Int32)}}]}},$n);$m("System.Collections.Generic.HashSet$1",function(T){return{nested:[$n[3].HashSet$1.ElementCount,$n[3].HashSet$1.Slot,$n[3].HashSet$1.Enumerator],att:1048577,a:2,m:[{a:2,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[3].IEnumerable$1(T)],pi:[{n:"collection",pt:$n[3].IEnumerable$1(T),ps:0}],sn:"$ctor1"},{a:2,n:".ctor",t:1,p:[$n[3].IEqualityComparer$1(T)],pi:[{n:"comparer",pt:$n[3].IEqualityComparer$1(T),ps:0}],sn:"$ctor3"},{a:2,n:".ctor",t:1,p:[$n[3].IEnumerable$1(T),$n[3].IEqualityComparer$1(T)],pi:[{n:"collection",pt:$n[3].IEnumerable$1(T),ps:0},{n:"comparer",pt:$n[3].IEqualityComparer$1(T),ps:1}],sn:"$ctor2"},{a:2,n:"Add",t:8,pi:[{n:"item",pt:T,ps:0}],sn:"add",rt:$n[0].Boolean,p:[T],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"AddIfNotPresent",t:8,pi:[{n:"value",pt:T,ps:0}],sn:"AddIfNotPresent",rt:$n[0].Boolean,p:[T],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"AddOrGetLocation",t:8,pi:[{n:"value",pt:T,ps:0},{n:"location",out:!0,pt:$n[0].Int32,ps:1}],sn:"AddOrGetLocation",rt:$n[0].Boolean,p:[T,$n[0].Int32],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"AreEqualityComparersEqual",is:!0,t:8,pi:[{n:"set1",pt:$n[3].HashSet$1(T),ps:0},{n:"set2",pt:$n[3].HashSet$1(T),ps:1}],sn:"AreEqualityComparersEqual",rt:$n[0].Boolean,p:[$n[3].HashSet$1(T),$n[3].HashSet$1(T)],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"ArrayClear",t:8,pi:[{n:"array",pt:Array,ps:0},{n:"index",pt:$n[0].Int32,ps:1},{n:"length",pt:$n[0].Int32,ps:2}],sn:"ArrayClear",rt:$n[0].Void,p:[Array,$n[0].Int32,$n[0].Int32]},{a:1,n:"CheckUniqueAndUnfoundElements",t:8,pi:[{n:"other",pt:$n[3].IEnumerable$1(T),ps:0},{n:"returnIfUnfound",pt:$n[0].Boolean,ps:1}],sn:"CheckUniqueAndUnfoundElements",rt:$n[3].HashSet$1.ElementCount(T),p:[$n[3].IEnumerable$1(T),$n[0].Boolean]},{a:2,n:"Clear",t:8,sn:"clear",rt:$n[0].Void},{a:2,n:"Contains",t:8,pi:[{n:"item",pt:T,ps:0}],sn:"contains",rt:$n[0].Boolean,p:[T],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"ContainsAllElements",t:8,pi:[{n:"other",pt:$n[3].IEnumerable$1(T),ps:0}],sn:"ContainsAllElements",rt:$n[0].Boolean,p:[$n[3].IEnumerable$1(T)],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"CopyTo",t:8,pi:[{n:"array",pt:System.Array.type(T),ps:0}],sn:"CopyTo",rt:$n[0].Void,p:[System.Array.type(T)]},{a:2,n:"CopyTo",t:8,pi:[{n:"array",pt:System.Array.type(T),ps:0},{n:"arrayIndex",pt:$n[0].Int32,ps:1}],sn:"copyTo",rt:$n[0].Void,p:[System.Array.type(T),$n[0].Int32]},{a:2,n:"CopyTo",t:8,pi:[{n:"array",pt:System.Array.type(T),ps:0},{n:"arrayIndex",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2}],sn:"CopyTo$1",rt:$n[0].Void,p:[System.Array.type(T),$n[0].Int32,$n[0].Int32]},{a:2,n:"ExceptWith",t:8,pi:[{n:"other",pt:$n[3].IEnumerable$1(T),ps:0}],sn:"exceptWith",rt:$n[0].Void,p:[$n[3].IEnumerable$1(T)]},{a:2,n:"GetEnumerator",t:8,sn:"GetEnumerator",rt:$n[3].HashSet$1.Enumerator(T)},{a:4,n:"HashSetEquals",is:!0,t:8,pi:[{n:"set1",pt:$n[3].HashSet$1(T),ps:0},{n:"set2",pt:$n[3].HashSet$1(T),ps:1},{n:"comparer",pt:$n[3].IEqualityComparer$1(T),ps:2}],sn:"HashSetEquals",rt:$n[0].Boolean,p:[$n[3].HashSet$1(T),$n[3].HashSet$1(T),$n[3].IEqualityComparer$1(T)],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"IncreaseCapacity",t:8,sn:"IncreaseCapacity",rt:$n[0].Void},{a:1,n:"Initialize",t:8,pi:[{n:"capacity",pt:$n[0].Int32,ps:0}],sn:"Initialize",rt:$n[0].Void,p:[$n[0].Int32]},{a:1,n:"InternalGetHashCode",t:8,pi:[{n:"item",pt:T,ps:0}],sn:"InternalGetHashCode",rt:$n[0].Int32,p:[T],box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"InternalIndexOf",t:8,pi:[{n:"item",pt:T,ps:0}],sn:"InternalIndexOf",rt:$n[0].Int32,p:[T],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"IntersectWith",t:8,pi:[{n:"other",pt:$n[3].IEnumerable$1(T),ps:0}],sn:"intersectWith",rt:$n[0].Void,p:[$n[3].IEnumerable$1(T)]},{a:1,n:"IntersectWithEnumerable",t:8,pi:[{n:"other",pt:$n[3].IEnumerable$1(T),ps:0}],sn:"IntersectWithEnumerable",rt:$n[0].Void,p:[$n[3].IEnumerable$1(T)]},{a:1,n:"IntersectWithHashSetWithSameEC",t:8,pi:[{n:"other",pt:$n[3].HashSet$1(T),ps:0}],sn:"IntersectWithHashSetWithSameEC",rt:$n[0].Void,p:[$n[3].HashSet$1(T)]},{a:2,n:"IsProperSubsetOf",t:8,pi:[{n:"other",pt:$n[3].IEnumerable$1(T),ps:0}],sn:"isProperSubsetOf",rt:$n[0].Boolean,p:[$n[3].IEnumerable$1(T)],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"IsProperSupersetOf",t:8,pi:[{n:"other",pt:$n[3].IEnumerable$1(T),ps:0}],sn:"isProperSupersetOf",rt:$n[0].Boolean,p:[$n[3].IEnumerable$1(T)],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"IsSubsetOf",t:8,pi:[{n:"other",pt:$n[3].IEnumerable$1(T),ps:0}],sn:"isSubsetOf",rt:$n[0].Boolean,p:[$n[3].IEnumerable$1(T)],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"IsSubsetOfHashSetWithSameEC",t:8,pi:[{n:"other",pt:$n[3].HashSet$1(T),ps:0}],sn:"IsSubsetOfHashSetWithSameEC",rt:$n[0].Boolean,p:[$n[3].HashSet$1(T)],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"IsSupersetOf",t:8,pi:[{n:"other",pt:$n[3].IEnumerable$1(T),ps:0}],sn:"isSupersetOf",rt:$n[0].Boolean,p:[$n[3].IEnumerable$1(T)],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Overlaps",t:8,pi:[{n:"other",pt:$n[3].IEnumerable$1(T),ps:0}],sn:"overlaps",rt:$n[0].Boolean,p:[$n[3].IEnumerable$1(T)],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Remove",t:8,pi:[{n:"item",pt:T,ps:0}],sn:"remove",rt:$n[0].Boolean,p:[T],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"RemoveWhere",t:8,pi:[{n:"match",pt:Function,ps:0}],sn:"RemoveWhere",rt:$n[0].Int32,p:[Function],box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"SetCapacity",t:8,pi:[{n:"newSize",pt:$n[0].Int32,ps:0},{n:"forceNewHashCodes",pt:$n[0].Boolean,ps:1}],sn:"SetCapacity",rt:$n[0].Void,p:[$n[0].Int32,$n[0].Boolean]},{a:2,n:"SetEquals",t:8,pi:[{n:"other",pt:$n[3].IEnumerable$1(T),ps:0}],sn:"setEquals",rt:$n[0].Boolean,p:[$n[3].IEnumerable$1(T)],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"SymmetricExceptWith",t:8,pi:[{n:"other",pt:$n[3].IEnumerable$1(T),ps:0}],sn:"symmetricExceptWith",rt:$n[0].Void,p:[$n[3].IEnumerable$1(T)]},{a:1,n:"SymmetricExceptWithEnumerable",t:8,pi:[{n:"other",pt:$n[3].IEnumerable$1(T),ps:0}],sn:"SymmetricExceptWithEnumerable",rt:$n[0].Void,p:[$n[3].IEnumerable$1(T)]},{a:1,n:"SymmetricExceptWithUniqueHashSet",t:8,pi:[{n:"other",pt:$n[3].HashSet$1(T),ps:0}],sn:"SymmetricExceptWithUniqueHashSet",rt:$n[0].Void,p:[$n[3].HashSet$1(T)]},{a:4,n:"ToArray",t:8,sn:"ToArray",rt:System.Array.type(T)},{a:2,n:"TrimExcess",t:8,sn:"TrimExcess",rt:$n[0].Void},{a:2,n:"UnionWith",t:8,pi:[{n:"other",pt:$n[3].IEnumerable$1(T),ps:0}],sn:"unionWith",rt:$n[0].Void,p:[$n[3].IEnumerable$1(T)]},{a:2,n:"Comparer",t:16,rt:$n[3].IEqualityComparer$1(T),g:{a:2,n:"get_Comparer",t:8,rt:$n[3].IEqualityComparer$1(T),fg:"Comparer"},fn:"Comparer"},{a:2,n:"Count",t:16,rt:$n[0].Int32,g:{a:2,n:"get_Count",t:8,rt:$n[0].Int32,fg:"Count",box:function($v){return H5.box($v,System.Int32)}},fn:"Count"},{a:2,n:"IsReadOnly",t:16,rt:$n[0].Boolean,g:{a:2,n:"get_IsReadOnly",t:8,rt:$n[0].Boolean,fg:"IsReadOnly",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},fn:"IsReadOnly"},{a:1,n:"Lower31BitMask",is:!0,t:4,rt:$n[0].Int32,sn:"Lower31BitMask",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"ShrinkThreshold",is:!0,t:4,rt:$n[0].Int32,sn:"ShrinkThreshold",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"_buckets",t:4,rt:$n[0].Array.type(System.Int32),sn:"_buckets"},{a:1,n:"_comparer",t:4,rt:$n[3].IEqualityComparer$1(T),sn:"_comparer"},{a:1,n:"_count",t:4,rt:$n[0].Int32,sn:"_count",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"_freeList",t:4,rt:$n[0].Int32,sn:"_freeList",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"_lastIndex",t:4,rt:$n[0].Int32,sn:"_lastIndex",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"_slots",t:4,rt:System.Array.type(System.Collections.Generic.HashSet$1.Slot(T)),sn:"_slots"},{a:1,n:"_version",t:4,rt:$n[0].Int32,sn:"_version",box:function($v){return H5.box($v,System.Int32)}}]}},$n);$m("System.Collections.Generic.HashSet$1.ElementCount",function(T){return{td:$n[3].HashSet$1(T),att:1048845,a:4,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:4,n:"unfoundCount",t:4,rt:$n[0].Int32,sn:"unfoundCount",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"uniqueCount",t:4,rt:$n[0].Int32,sn:"uniqueCount",box:function($v){return H5.box($v,System.Int32)}}]}},$n);$m("System.Collections.Generic.HashSet$1.Slot",function(T){return{td:$n[3].HashSet$1(T),att:1048845,a:4,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:4,n:"hashCode",t:4,rt:$n[0].Int32,sn:"hashCode",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"next",t:4,rt:$n[0].Int32,sn:"next",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"value",t:4,rt:T,sn:"value"}]}},$n);$m("System.Collections.Generic.HashSet$1.Enumerator",function(T){return{td:$n[3].HashSet$1(T),att:1048842,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:4,n:".ctor",t:1,p:[$n[3].HashSet$1(T)],pi:[{n:"set",pt:$n[3].HashSet$1(T),ps:0}],sn:"$ctor1"},{a:2,n:"Dispose",t:8,sn:"Dispose",rt:$n[0].Void},{a:2,n:"MoveNext",t:8,sn:"moveNext",rt:$n[0].Boolean,box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Current",t:16,rt:T,g:{a:2,n:"get_Current",t:8,rt:T,fg:"Current"},fn:"Current"},{a:1,n:"_current",t:4,rt:T,sn:"_current"},{a:1,n:"_index",t:4,rt:$n[0].Int32,sn:"_index",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"_set",t:4,rt:$n[3].HashSet$1(T),sn:"_set"},{a:1,n:"_version",t:4,rt:$n[0].Int32,sn:"_version",box:function($v){return H5.box($v,System.Int32)}}]}},$n);$m("System.Collections.Generic.ICollectionDebugView$1",function(T){return{att:1048832,a:4,m:[{a:2,n:".ctor",t:1,p:[$n[3].ICollection$1(T)],pi:[{n:"collection",pt:$n[3].ICollection$1(T),ps:0}],sn:"ctor"},{a:2,n:"Items",t:16,rt:System.Array.type(T),g:{a:2,n:"get_Items",t:8,rt:System.Array.type(T),fg:"Items"},fn:"Items"},{a:1,n:"_collection",t:4,rt:$n[3].ICollection$1(T),sn:"_collection",ro:!0}]}},$n);$m("System.Collections.Generic.IComparer$1",function(T){return{att:1048737,a:2,m:[{ab:!0,a:2,n:"Compare",t:8,pi:[{n:"x",pt:T,ps:0},{n:"y",pt:T,ps:1}],sn:"System$Collections$Generic$IComparer$1$"+H5.getTypeAlias(T)+"$compare",rt:$n[0].Int32,p:[T,T],box:function($v){return H5.box($v,System.Int32)}}]}},$n);$m("System.Collections.Generic.IDictionaryDebugView$2",function(K,V){return{att:1048832,a:4,m:[{a:2,n:".ctor",t:1,p:[$n[3].IDictionary$2(K,V)],pi:[{n:"dictionary",pt:$n[3].IDictionary$2(K,V),ps:0}],sn:"ctor"},{a:2,n:"Items",t:16,rt:System.Array.type(System.Collections.Generic.KeyValuePair$2(K,V)),g:{a:2,n:"get_Items",t:8,rt:System.Array.type(System.Collections.Generic.KeyValuePair$2(K,V)),fg:"Items"},fn:"Items"},{a:1,n:"_dict",t:4,rt:$n[3].IDictionary$2(K,V),sn:"_dict",ro:!0}]}},$n);$m("System.Collections.Generic.DictionaryKeyCollectionDebugView$2",function(TKey,TValue){return{att:1048832,a:4,m:[{a:2,n:".ctor",t:1,p:[$n[3].ICollection$1(TKey)],pi:[{n:"collection",pt:$n[3].ICollection$1(TKey),ps:0}],sn:"ctor"},{a:2,n:"Items",t:16,rt:System.Array.type(TKey),g:{a:2,n:"get_Items",t:8,rt:System.Array.type(TKey),fg:"Items"},fn:"Items"},{a:1,n:"_collection",t:4,rt:$n[3].ICollection$1(TKey),sn:"_collection",ro:!0}]}},$n);$m("System.Collections.Generic.DictionaryValueCollectionDebugView$2",function(TKey,TValue){return{att:1048832,a:4,m:[{a:2,n:".ctor",t:1,p:[$n[3].ICollection$1(TValue)],pi:[{n:"collection",pt:$n[3].ICollection$1(TValue),ps:0}],sn:"ctor"},{a:2,n:"Items",t:16,rt:System.Array.type(TValue),g:{a:2,n:"get_Items",t:8,rt:System.Array.type(TValue),fg:"Items"},fn:"Items"},{a:1,n:"_collection",t:4,rt:$n[3].ICollection$1(TValue),sn:"_collection",ro:!0}]}},$n);$m("System.Collections.Generic.IEnumerator$1",function(T){return{att:1048737,a:2,m:[{ab:!0,a:2,n:"Current",t:16,rt:T,g:{ab:!0,a:2,n:"get_Current",t:8,rt:T,fg:'"System$Collections$Generic$IEnumerator$1$" + H5.getTypeAlias(T) + "$Current$1"'},fn:'"System$Collections$Generic$IEnumerator$1$" + H5.getTypeAlias(T) + "$Current$1"'},{a:1,backing:!0,n:"k__BackingField",t:4,rt:T,sn:'"System$Collections$Generic$IEnumerator$1$" + H5.getTypeAlias(T) + "$Current$1"'}]}},$n);$m("System.Collections.Generic.KeyNotFoundException",function(){return{att:1056769,a:2,at:[new System.SerializableAttribute],m:[{a:2,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[0].String],pi:[{n:"message",pt:$n[0].String,ps:0}],sn:"$ctor1"},{a:2,n:".ctor",t:1,p:[$n[0].String,$n[0].Exception],pi:[{n:"message",pt:$n[0].String,ps:0},{n:"innerException",pt:$n[0].Exception,ps:1}],sn:"$ctor2"}]}},$n);$m("System.Collections.Generic.KeyValuePair$2",function(TKey,TValue){return{att:1057033,a:2,at:[new System.SerializableAttribute],m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[TKey,TValue],pi:[{n:"key",pt:TKey,ps:0},{n:"value",pt:TValue,ps:1}],sn:"$ctor1"},{a:2,n:"Deconstruct",t:8,pi:[{n:"key",out:!0,pt:TKey,ps:0},{n:"value",out:!0,pt:TValue,ps:1}],sn:"Deconstruct",rt:$n[0].Void,p:[TKey,TValue]},{ov:!0,a:2,n:"ToString",t:8,sn:"toString",rt:$n[0].String},{a:2,n:"Key",t:16,rt:TKey,g:{a:2,n:"get_Key",t:8,rt:TKey,fg:"key"},fn:"key"},{a:2,n:"Value",t:16,rt:TValue,g:{a:2,n:"get_Value",t:8,rt:TValue,fg:"value"},fn:"value"},{a:1,n:"key",t:4,rt:TKey,sn:"key$1"},{a:1,n:"value",t:4,rt:TValue,sn:"value$1"}]}},$n);$m("System.Collections.Generic.List$1",function(T){return{nested:[$n[3].List$1.Enumerator],att:1048577,a:2,m:[{a:2,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[3].IEnumerable$1(T)],pi:[{n:"collection",pt:$n[3].IEnumerable$1(T),ps:0}],sn:"$ctor1"},{a:2,n:".ctor",t:1,p:[$n[0].Int32],pi:[{n:"capacity",pt:$n[0].Int32,ps:0}],sn:"$ctor2"},{a:2,n:"Add",t:8,pi:[{n:"item",pt:T,ps:0}],sn:"add",rt:$n[0].Void,p:[T]},{a:2,n:"AddRange",t:8,pi:[{n:"collection",pt:$n[3].IEnumerable$1(T),ps:0}],sn:"AddRange",rt:$n[0].Void,p:[$n[3].IEnumerable$1(T)]},{a:2,n:"AsReadOnly",t:8,sn:"AsReadOnly",rt:$n[5].ReadOnlyCollection$1(T)},{a:2,n:"BinarySearch",t:8,pi:[{n:"item",pt:T,ps:0}],sn:"BinarySearch",rt:$n[0].Int32,p:[T],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"BinarySearch",t:8,pi:[{n:"item",pt:T,ps:0},{n:"comparer",pt:$n[3].IComparer$1(T),ps:1}],sn:"BinarySearch$1",rt:$n[0].Int32,p:[T,$n[3].IComparer$1(T)],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"BinarySearch",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0},{n:"count",pt:$n[0].Int32,ps:1},{n:"item",pt:T,ps:2},{n:"comparer",pt:$n[3].IComparer$1(T),ps:3}],sn:"BinarySearch$2",rt:$n[0].Int32,p:[$n[0].Int32,$n[0].Int32,T,$n[3].IComparer$1(T)],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"Clear",t:8,sn:"clear",rt:$n[0].Void},{a:2,n:"Contains",t:8,pi:[{n:"item",pt:T,ps:0}],sn:"contains",rt:$n[0].Boolean,p:[T],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"ConvertAll",t:8,pi:[{n:"converter",pt:Function,ps:0}],tpc:1,tprm:["TOutput"],sn:"ConvertAll",rt:$n[3].List$1(System.Object),p:[Function]},{a:2,n:"CopyTo",t:8,pi:[{n:"array",pt:System.Array.type(T),ps:0}],sn:"CopyTo",rt:$n[0].Void,p:[System.Array.type(T)]},{a:2,n:"CopyTo",t:8,pi:[{n:"array",pt:System.Array.type(T),ps:0},{n:"arrayIndex",pt:$n[0].Int32,ps:1}],sn:"copyTo",rt:$n[0].Void,p:[System.Array.type(T),$n[0].Int32]},{a:2,n:"CopyTo",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0},{n:"array",pt:System.Array.type(T),ps:1},{n:"arrayIndex",pt:$n[0].Int32,ps:2},{n:"count",pt:$n[0].Int32,ps:3}],sn:"CopyTo$1",rt:$n[0].Void,p:[$n[0].Int32,System.Array.type(T),$n[0].Int32,$n[0].Int32]},{a:1,n:"EnsureCapacity",t:8,pi:[{n:"min",pt:$n[0].Int32,ps:0}],sn:"EnsureCapacity",rt:$n[0].Void,p:[$n[0].Int32]},{a:2,n:"Exists",t:8,pi:[{n:"match",pt:Function,ps:0}],sn:"Exists",rt:$n[0].Boolean,p:[Function],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Find",t:8,pi:[{n:"match",pt:Function,ps:0}],sn:"Find",rt:T,p:[Function]},{a:2,n:"FindAll",t:8,pi:[{n:"match",pt:Function,ps:0}],sn:"FindAll",rt:$n[3].List$1(T),p:[Function]},{a:2,n:"FindIndex",t:8,pi:[{n:"match",pt:Function,ps:0}],sn:"FindIndex$2",rt:$n[0].Int32,p:[Function],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"FindIndex",t:8,pi:[{n:"startIndex",pt:$n[0].Int32,ps:0},{n:"match",pt:Function,ps:1}],sn:"FindIndex$1",rt:$n[0].Int32,p:[$n[0].Int32,Function],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"FindIndex",t:8,pi:[{n:"startIndex",pt:$n[0].Int32,ps:0},{n:"count",pt:$n[0].Int32,ps:1},{n:"match",pt:Function,ps:2}],sn:"FindIndex",rt:$n[0].Int32,p:[$n[0].Int32,$n[0].Int32,Function],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"FindLast",t:8,pi:[{n:"match",pt:Function,ps:0}],sn:"FindLast",rt:T,p:[Function]},{a:2,n:"FindLastIndex",t:8,pi:[{n:"match",pt:Function,ps:0}],sn:"FindLastIndex$2",rt:$n[0].Int32,p:[Function],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"FindLastIndex",t:8,pi:[{n:"startIndex",pt:$n[0].Int32,ps:0},{n:"match",pt:Function,ps:1}],sn:"FindLastIndex$1",rt:$n[0].Int32,p:[$n[0].Int32,Function],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"FindLastIndex",t:8,pi:[{n:"startIndex",pt:$n[0].Int32,ps:0},{n:"count",pt:$n[0].Int32,ps:1},{n:"match",pt:Function,ps:2}],sn:"FindLastIndex",rt:$n[0].Int32,p:[$n[0].Int32,$n[0].Int32,Function],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"ForEach",t:8,pi:[{n:"action",pt:Function,ps:0}],sn:"ForEach",rt:$n[0].Void,p:[Function]},{a:2,n:"GetEnumerator",t:8,sn:"GetEnumerator",rt:$n[3].List$1.Enumerator(T)},{a:2,n:"GetRange",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0},{n:"count",pt:$n[0].Int32,ps:1}],sn:"GetRange",rt:$n[3].List$1(T),p:[$n[0].Int32,$n[0].Int32]},{a:2,n:"IndexOf",t:8,pi:[{n:"item",pt:T,ps:0}],sn:"indexOf",rt:$n[0].Int32,p:[T],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"IndexOf",t:8,pi:[{n:"item",pt:T,ps:0},{n:"index",pt:$n[0].Int32,ps:1}],sn:"IndexOf",rt:$n[0].Int32,p:[T,$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"IndexOf",t:8,pi:[{n:"item",pt:T,ps:0},{n:"index",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2}],sn:"IndexOf$1",rt:$n[0].Int32,p:[T,$n[0].Int32,$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"Insert",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0},{n:"item",pt:T,ps:1}],sn:"insert",rt:$n[0].Void,p:[$n[0].Int32,T]},{a:2,n:"InsertRange",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0},{n:"collection",pt:$n[3].IEnumerable$1(T),ps:1}],sn:"InsertRange",rt:$n[0].Void,p:[$n[0].Int32,$n[3].IEnumerable$1(T)]},{a:1,n:"IsCompatibleObject",is:!0,t:8,pi:[{n:"value",pt:$n[0].Object,ps:0}],sn:"IsCompatibleObject",rt:$n[0].Boolean,p:[$n[0].Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"LastIndexOf",t:8,pi:[{n:"item",pt:T,ps:0}],sn:"LastIndexOf",rt:$n[0].Int32,p:[T],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"LastIndexOf",t:8,pi:[{n:"item",pt:T,ps:0},{n:"index",pt:$n[0].Int32,ps:1}],sn:"LastIndexOf$1",rt:$n[0].Int32,p:[T,$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"LastIndexOf",t:8,pi:[{n:"item",pt:T,ps:0},{n:"index",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2}],sn:"LastIndexOf$2",rt:$n[0].Int32,p:[T,$n[0].Int32,$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"Remove",t:8,pi:[{n:"item",pt:T,ps:0}],sn:"remove",rt:$n[0].Boolean,p:[T],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"RemoveAll",t:8,pi:[{n:"match",pt:Function,ps:0}],sn:"RemoveAll",rt:$n[0].Int32,p:[Function],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"RemoveAt",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0}],sn:"removeAt",rt:$n[0].Void,p:[$n[0].Int32]},{a:2,n:"RemoveRange",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0},{n:"count",pt:$n[0].Int32,ps:1}],sn:"RemoveRange",rt:$n[0].Void,p:[$n[0].Int32,$n[0].Int32]},{a:2,n:"Reverse",t:8,sn:"Reverse",rt:$n[0].Void},{a:2,n:"Reverse",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0},{n:"count",pt:$n[0].Int32,ps:1}],sn:"Reverse$1",rt:$n[0].Void,p:[$n[0].Int32,$n[0].Int32]},{a:2,n:"Sort",t:8,sn:"Sort",rt:$n[0].Void},{a:2,n:"Sort",t:8,pi:[{n:"comparer",pt:$n[3].IComparer$1(T),ps:0}],sn:"Sort$1",rt:$n[0].Void,p:[$n[3].IComparer$1(T)]},{a:2,n:"Sort",t:8,pi:[{n:"comparison",pt:Function,ps:0}],sn:"Sort$2",rt:$n[0].Void,p:[Function]},{a:2,n:"Sort",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0},{n:"count",pt:$n[0].Int32,ps:1},{n:"comparer",pt:$n[3].IComparer$1(T),ps:2}],sn:"Sort$3",rt:$n[0].Void,p:[$n[0].Int32,$n[0].Int32,$n[3].IComparer$1(T)]},{a:2,n:"ToArray",t:8,sn:"ToArray",rt:System.Array.type(T)},{a:2,n:"TrimExcess",t:8,sn:"TrimExcess",rt:$n[0].Void},{a:2,n:"TrueForAll",t:8,pi:[{n:"match",pt:Function,ps:0}],sn:"TrueForAll",rt:$n[0].Boolean,p:[Function],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"toJSON",t:8,sn:"toJSON",rt:$n[0].Object},{a:2,n:"Capacity",t:16,rt:$n[0].Int32,g:{a:2,n:"get_Capacity",t:8,rt:$n[0].Int32,fg:"Capacity",box:function($v){return H5.box($v,System.Int32)}},s:{a:2,n:"set_Capacity",t:8,p:[$n[0].Int32],rt:$n[0].Void,fs:"Capacity"},fn:"Capacity"},{a:2,n:"Count",t:16,rt:$n[0].Int32,g:{a:2,n:"get_Count",t:8,rt:$n[0].Int32,fg:"Count",box:function($v){return H5.box($v,System.Int32)}},fn:"Count"},{a:2,n:"Item",t:16,rt:T,p:[$n[0].Int32],i:!0,ipi:[{n:"index",pt:$n[0].Int32,ps:0}],g:{a:2,n:"get_Item",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0}],sn:"getItem",rt:T,p:[$n[0].Int32]},s:{a:2,n:"set_Item",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0},{n:"value",pt:T,ps:1}],sn:"setItem",rt:$n[0].Void,p:[$n[0].Int32,T]}},{a:1,n:"_defaultCapacity",is:!0,t:4,rt:$n[0].Int32,sn:"_defaultCapacity",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"_emptyArray",is:!0,t:4,rt:System.Array.type(T),sn:"_emptyArray",ro:!0},{a:1,n:"_items",t:4,rt:System.Array.type(T),sn:"_items"},{a:1,n:"_size",t:4,rt:$n[0].Int32,sn:"_size",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"_version",t:4,rt:$n[0].Int32,sn:"_version",box:function($v){return H5.box($v,System.Int32)}}]}},$n);$m("System.Collections.Generic.List$1.Enumerator",function(T){return{td:$n[3].List$1(T),att:1057034,a:2,at:[new System.SerializableAttribute],m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:4,n:".ctor",t:1,p:[$n[3].List$1(T)],pi:[{n:"list",pt:$n[3].List$1(T),ps:0}],sn:"$ctor1"},{a:2,n:"Dispose",t:8,sn:"Dispose",rt:$n[0].Void},{a:2,n:"MoveNext",t:8,sn:"moveNext",rt:$n[0].Boolean,box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"MoveNextRare",t:8,sn:"MoveNextRare",rt:$n[0].Boolean,box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Current",t:16,rt:T,g:{a:2,n:"get_Current",t:8,rt:T,fg:"Current"},fn:"Current"},{a:1,n:"current",t:4,rt:T,sn:"current"},{a:1,n:"index",t:4,rt:$n[0].Int32,sn:"index",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"list",t:4,rt:$n[3].List$1(T),sn:"list"},{a:1,n:"version",t:4,rt:$n[0].Int32,sn:"version",box:function($v){return H5.box($v,System.Int32)}}]}},$n);$m("System.Collections.Generic.Queue$1",function(T){return{nested:[$n[3].Queue$1.Enumerator],att:1048577,a:2,m:[{a:2,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[3].IEnumerable$1(T)],pi:[{n:"collection",pt:$n[3].IEnumerable$1(T),ps:0}],sn:"$ctor1"},{a:2,n:".ctor",t:1,p:[$n[0].Int32],pi:[{n:"capacity",pt:$n[0].Int32,ps:0}],sn:"$ctor2"},{a:2,n:"Clear",t:8,sn:"Clear",rt:$n[0].Void},{a:2,n:"Contains",t:8,pi:[{n:"item",pt:T,ps:0}],sn:"Contains",rt:$n[0].Boolean,p:[T],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{v:!0,a:2,n:"CopyTo",t:8,pi:[{n:"array",pt:Array,ps:0},{n:"index",pt:$n[0].Int32,ps:1}],sn:"copyTo",rt:$n[0].Void,p:[Array,$n[0].Int32]},{a:2,n:"CopyTo",t:8,pi:[{n:"array",pt:System.Array.type(T),ps:0},{n:"arrayIndex",pt:$n[0].Int32,ps:1}],sn:"CopyTo",rt:$n[0].Void,p:[System.Array.type(T),$n[0].Int32]},{a:2,n:"Dequeue",t:8,sn:"Dequeue",rt:T},{a:2,n:"Enqueue",t:8,pi:[{n:"item",pt:T,ps:0}],sn:"Enqueue",rt:$n[0].Void,p:[T]},{a:1,n:"GetElement",t:8,pi:[{n:"i",pt:$n[0].Int32,ps:0}],sn:"GetElement",rt:T,p:[$n[0].Int32]},{a:2,n:"GetEnumerator",t:8,sn:"GetEnumerator",rt:$n[3].Queue$1.Enumerator(T)},{a:1,n:"MoveNext",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0}],sn:"MoveNext",rt:$n[0].Int32,p:[$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"Peek",t:8,sn:"Peek",rt:T},{a:1,n:"SetCapacity",t:8,pi:[{n:"capacity",pt:$n[0].Int32,ps:0}],sn:"SetCapacity",rt:$n[0].Void,p:[$n[0].Int32]},{a:2,n:"ToArray",t:8,sn:"ToArray",rt:System.Array.type(T)},{a:2,n:"TrimExcess",t:8,sn:"TrimExcess",rt:$n[0].Void},{a:2,n:"Count",t:16,rt:$n[0].Int32,g:{a:2,n:"get_Count",t:8,rt:$n[0].Int32,fg:"Count",box:function($v){return H5.box($v,System.Int32)}},fn:"Count"},{a:2,n:"IsReadOnly",t:16,rt:$n[0].Boolean,g:{a:2,n:"get_IsReadOnly",t:8,rt:$n[0].Boolean,fg:"IsReadOnly",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},fn:"IsReadOnly"},{a:1,n:"DefaultCapacity",is:!0,t:4,rt:$n[0].Int32,sn:"DefaultCapacity",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"GrowFactor",is:!0,t:4,rt:$n[0].Int32,sn:"GrowFactor",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"MinimumGrow",is:!0,t:4,rt:$n[0].Int32,sn:"MinimumGrow",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"_array",t:4,rt:System.Array.type(T),sn:"_array"},{a:1,n:"_head",t:4,rt:$n[0].Int32,sn:"_head",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"_size",t:4,rt:$n[0].Int32,sn:"_size",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"_tail",t:4,rt:$n[0].Int32,sn:"_tail",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"_version",t:4,rt:$n[0].Int32,sn:"_version",box:function($v){return H5.box($v,System.Int32)}}]}},$n);$m("System.Collections.Generic.Queue$1.Enumerator",function(T){return{td:$n[3].Queue$1(T),att:1048842,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:4,n:".ctor",t:1,p:[$n[3].Queue$1(T)],pi:[{n:"q",pt:$n[3].Queue$1(T),ps:0}],sn:"$ctor1"},{a:2,n:"Dispose",t:8,sn:"Dispose",rt:$n[0].Void},{a:2,n:"MoveNext",t:8,sn:"moveNext",rt:$n[0].Boolean,box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Current",t:16,rt:T,g:{a:2,n:"get_Current",t:8,rt:T,fg:"Current"},fn:"Current"},{a:1,n:"_currentElement",t:4,rt:T,sn:"_currentElement"},{a:1,n:"_index",t:4,rt:$n[0].Int32,sn:"_index",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"_q",t:4,rt:$n[3].Queue$1(T),sn:"_q"},{a:1,n:"_version",t:4,rt:$n[0].Int32,sn:"_version",box:function($v){return H5.box($v,System.Int32)}}]}},$n);$m("System.Collections.Generic.Stack$1",function(T){return{nested:[$n[3].Stack$1.Enumerator],att:1048577,a:2,m:[{a:2,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[3].IEnumerable$1(T)],pi:[{n:"collection",pt:$n[3].IEnumerable$1(T),ps:0}],sn:"$ctor1"},{a:2,n:".ctor",t:1,p:[$n[0].Int32],pi:[{n:"capacity",pt:$n[0].Int32,ps:0}],sn:"$ctor2"},{a:2,n:"Clear",t:8,sn:"Clear",rt:$n[0].Void},{a:2,n:"Contains",t:8,pi:[{n:"item",pt:T,ps:0}],sn:"Contains",rt:$n[0].Boolean,p:[T],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"CopyTo",t:8,pi:[{n:"array",pt:Array,ps:0},{n:"arrayIndex",pt:$n[0].Int32,ps:1}],sn:"copyTo",rt:$n[0].Void,p:[Array,$n[0].Int32]},{a:2,n:"CopyTo",t:8,pi:[{n:"array",pt:System.Array.type(T),ps:0},{n:"arrayIndex",pt:$n[0].Int32,ps:1}],sn:"CopyTo",rt:$n[0].Void,p:[System.Array.type(T),$n[0].Int32]},{a:2,n:"GetEnumerator",t:8,sn:"GetEnumerator",rt:$n[3].Stack$1.Enumerator(T)},{a:2,n:"Peek",t:8,sn:"Peek",rt:T},{a:2,n:"Pop",t:8,sn:"Pop",rt:T},{a:2,n:"Push",t:8,pi:[{n:"item",pt:T,ps:0}],sn:"Push",rt:$n[0].Void,p:[T]},{a:2,n:"ToArray",t:8,sn:"ToArray",rt:System.Array.type(T)},{a:2,n:"TrimExcess",t:8,sn:"TrimExcess",rt:$n[0].Void},{a:2,n:"Count",t:16,rt:$n[0].Int32,g:{a:2,n:"get_Count",t:8,rt:$n[0].Int32,fg:"Count",box:function($v){return H5.box($v,System.Int32)}},fn:"Count"},{a:2,n:"IsReadOnly",t:16,rt:$n[0].Boolean,g:{a:2,n:"get_IsReadOnly",t:8,rt:$n[0].Boolean,fg:"IsReadOnly",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},fn:"IsReadOnly"},{a:1,n:"DefaultCapacity",is:!0,t:4,rt:$n[0].Int32,sn:"DefaultCapacity",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"_array",t:4,rt:System.Array.type(T),sn:"_array"},{a:1,n:"_size",t:4,rt:$n[0].Int32,sn:"_size",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"_version",t:4,rt:$n[0].Int32,sn:"_version",box:function($v){return H5.box($v,System.Int32)}}]}},$n);$m("System.Collections.Generic.Stack$1.Enumerator",function(T){return{td:$n[3].Stack$1(T),att:1048842,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:4,n:".ctor",t:1,p:[$n[3].Stack$1(T)],pi:[{n:"stack",pt:$n[3].Stack$1(T),ps:0}],sn:"$ctor1"},{a:2,n:"Dispose",t:8,sn:"Dispose",rt:$n[0].Void},{a:2,n:"MoveNext",t:8,sn:"moveNext",rt:$n[0].Boolean,box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Current",t:16,rt:T,g:{a:2,n:"get_Current",t:8,rt:T,fg:"Current"},fn:"Current"},{a:1,n:"_currentElement",t:4,rt:T,sn:"_currentElement"},{a:1,n:"_index",t:4,rt:$n[0].Int32,sn:"_index",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"_stack",t:4,rt:$n[3].Stack$1(T),sn:"_stack"},{a:1,n:"_version",t:4,rt:$n[0].Int32,sn:"_version",box:function($v){return H5.box($v,System.Int32)}}]}},$n);$m("System.Collections.Generic.Dictionary$2",function(TKey,TValue){return{nested:[$n[3].Dictionary$2.Entry,$n[3].Dictionary$2.Enumerator,$n[3].Dictionary$2.KeyCollection,$n[3].Dictionary$2.ValueCollection],att:1048577,a:2,m:[{a:2,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[3].IDictionary$2(TKey,TValue)],pi:[{n:"dictionary",pt:$n[3].IDictionary$2(TKey,TValue),ps:0}],sn:"$ctor1"},{a:2,n:".ctor",t:1,p:[$n[3].IEqualityComparer$1(TKey)],pi:[{n:"comparer",pt:$n[3].IEqualityComparer$1(TKey),ps:0}],sn:"$ctor3"},{a:2,n:".ctor",t:1,p:[$n[0].Int32],pi:[{n:"capacity",pt:$n[0].Int32,ps:0}],sn:"$ctor4"},{a:2,n:".ctor",t:1,p:[$n[3].IDictionary$2(TKey,TValue),$n[3].IEqualityComparer$1(TKey)],pi:[{n:"dictionary",pt:$n[3].IDictionary$2(TKey,TValue),ps:0},{n:"comparer",pt:$n[3].IEqualityComparer$1(TKey),ps:1}],sn:"$ctor2"},{a:2,n:".ctor",t:1,p:[$n[0].Int32,$n[3].IEqualityComparer$1(TKey)],pi:[{n:"capacity",pt:$n[0].Int32,ps:0},{n:"comparer",pt:$n[3].IEqualityComparer$1(TKey),ps:1}],sn:"$ctor5"},{a:2,n:"Add",t:8,pi:[{n:"key",pt:TKey,ps:0},{n:"value",pt:TValue,ps:1}],sn:"add",rt:$n[0].Void,p:[TKey,TValue]},{a:2,n:"Clear",t:8,sn:"clear",rt:$n[0].Void},{a:2,n:"ContainsKey",t:8,pi:[{n:"key",pt:TKey,ps:0}],sn:"containsKey",rt:$n[0].Boolean,p:[TKey],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"ContainsValue",t:8,pi:[{n:"value",pt:TValue,ps:0}],sn:"ContainsValue",rt:$n[0].Boolean,p:[TValue],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"CopyTo",t:8,pi:[{n:"array",pt:System.Array.type(System.Collections.Generic.KeyValuePair$2(TKey,TValue)),ps:0},{n:"index",pt:$n[0].Int32,ps:1}],sn:"CopyTo",rt:$n[0].Void,p:[System.Array.type(System.Collections.Generic.KeyValuePair$2(TKey,TValue)),$n[0].Int32]},{a:1,n:"FindEntry",t:8,pi:[{n:"key",pt:TKey,ps:0}],sn:"FindEntry",rt:$n[0].Int32,p:[TKey],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"GetBucket",is:!0,t:8,pi:[{n:"obj",pt:$n[0].Object,ps:0},{n:"key",pt:TKey,ps:1}],tpc:0,def:function(obj,key){return obj[key]},rt:$n[0].Int32,p:[$n[0].Object,TKey],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"GetEnumerator",t:8,sn:"GetEnumerator",rt:$n[3].Dictionary$2.Enumerator(TKey,TValue)},{a:4,n:"GetValueOrDefault",t:8,pi:[{n:"key",pt:TKey,ps:0}],sn:"GetValueOrDefault",rt:TValue,p:[TKey]},{a:1,n:"Initialize",t:8,pi:[{n:"capacity",pt:$n[0].Int32,ps:0}],sn:"Initialize",rt:$n[0].Void,p:[$n[0].Int32]},{a:1,n:"Insert",t:8,pi:[{n:"key",pt:TKey,ps:0},{n:"value",pt:TValue,ps:1},{n:"add",pt:$n[0].Boolean,ps:2}],sn:"Insert",rt:$n[0].Void,p:[TKey,TValue,$n[0].Boolean]},{a:1,n:"IsCompatibleKey",is:!0,t:8,pi:[{n:"key",pt:$n[0].Object,ps:0}],sn:"IsCompatibleKey",rt:$n[0].Boolean,p:[$n[0].Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Remove",t:8,pi:[{n:"key",pt:TKey,ps:0}],sn:"remove",rt:$n[0].Boolean,p:[TKey],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"Resize",t:8,sn:"Resize",rt:$n[0].Void},{a:1,n:"Resize",t:8,pi:[{n:"newSize",pt:$n[0].Int32,ps:0},{n:"forceNewHashCodes",pt:$n[0].Boolean,ps:1}],sn:"Resize$1",rt:$n[0].Void,p:[$n[0].Int32,$n[0].Boolean]},{a:2,n:"SetBucket",is:!0,t:8,pi:[{n:"obj",pt:$n[0].Object,ps:0},{n:"key",pt:TKey,ps:1},{n:"value",pt:$n[0].Int32,ps:2}],tpc:0,def:function(obj,key,value){return obj[key]=value},rt:$n[0].Void,p:[$n[0].Object,TKey,$n[0].Int32]},{a:2,n:"TryGetValue",t:8,pi:[{n:"key",pt:TKey,ps:0},{n:"value",out:!0,pt:TValue,ps:1}],sn:"tryGetValue",rt:$n[0].Boolean,p:[TKey,TValue],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Comparer",t:16,rt:$n[3].IEqualityComparer$1(TKey),g:{a:2,n:"get_Comparer",t:8,rt:$n[3].IEqualityComparer$1(TKey),fg:"Comparer"},fn:"Comparer"},{a:2,n:"Count",t:16,rt:$n[0].Int32,g:{a:2,n:"get_Count",t:8,rt:$n[0].Int32,fg:"Count",box:function($v){return H5.box($v,System.Int32)}},fn:"Count"},{a:2,n:"Item",t:16,rt:TValue,p:[TKey],i:!0,ipi:[{n:"key",pt:TKey,ps:0}],g:{a:2,n:"get_Item",t:8,pi:[{n:"key",pt:TKey,ps:0}],sn:"getItem",rt:TValue,p:[TKey]},s:{a:2,n:"set_Item",t:8,pi:[{n:"key",pt:TKey,ps:0},{n:"value",pt:TValue,ps:1}],sn:"setItem",rt:$n[0].Void,p:[TKey,TValue]}},{a:2,n:"Keys",t:16,rt:$n[3].Dictionary$2.KeyCollection(TKey,TValue),g:{a:2,n:"get_Keys",t:8,rt:$n[3].Dictionary$2.KeyCollection(TKey,TValue),fg:"Keys"},fn:"Keys"},{a:2,n:"Values",t:16,rt:$n[3].Dictionary$2.ValueCollection(TKey,TValue),g:{a:2,n:"get_Values",t:8,rt:$n[3].Dictionary$2.ValueCollection(TKey,TValue),fg:"Values"},fn:"Values"},{a:1,n:"ComparerName",is:!0,t:4,rt:$n[0].String,sn:"ComparerName"},{a:1,n:"HashSizeName",is:!0,t:4,rt:$n[0].String,sn:"HashSizeName"},{a:1,n:"KeyValuePairsName",is:!0,t:4,rt:$n[0].String,sn:"KeyValuePairsName"},{a:1,n:"VersionName",is:!0,t:4,rt:$n[0].String,sn:"VersionName"},{a:1,n:"buckets",t:4,rt:$n[0].Array.type(System.Int32),sn:"buckets"},{a:1,n:"comparer",t:4,rt:$n[3].IEqualityComparer$1(TKey),sn:"comparer"},{a:1,n:"count",t:4,rt:$n[0].Int32,sn:"count",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"entries",t:4,rt:System.Array.type(System.Collections.Generic.Dictionary$2.Entry(TKey,TValue)),sn:"entries"},{a:1,n:"freeCount",t:4,rt:$n[0].Int32,sn:"freeCount",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"freeList",t:4,rt:$n[0].Int32,sn:"freeList",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"isSimpleKey",t:4,rt:$n[0].Boolean,sn:"isSimpleKey",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"keys",t:4,rt:$n[3].Dictionary$2.KeyCollection(TKey,TValue),sn:"keys"},{a:1,n:"simpleBuckets",t:4,rt:$n[0].Object,sn:"simpleBuckets"},{a:1,n:"values",t:4,rt:$n[3].Dictionary$2.ValueCollection(TKey,TValue),sn:"values"},{a:1,n:"version",t:4,rt:$n[0].Int32,sn:"version",box:function($v){return H5.box($v,System.Int32)}}]}},$n);$m("System.Collections.Generic.Dictionary$2.Entry",function(TKey,TValue){return{td:$n[3].Dictionary$2(TKey,TValue),att:1048843,a:1,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:"hashCode",t:4,rt:$n[0].Int32,sn:"hashCode",box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"key",t:4,rt:TKey,sn:"key"},{a:2,n:"next",t:4,rt:$n[0].Int32,sn:"next",box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"value",t:4,rt:TValue,sn:"value"}]}},$n);$m("System.Collections.Generic.Dictionary$2.Enumerator",function(TKey,TValue){return{td:$n[3].Dictionary$2(TKey,TValue),att:1057034,a:2,at:[new System.SerializableAttribute],m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:4,n:".ctor",t:1,p:[$n[3].Dictionary$2(TKey,TValue),$n[0].Int32],pi:[{n:"dictionary",pt:$n[3].Dictionary$2(TKey,TValue),ps:0},{n:"getEnumeratorRetType",pt:$n[0].Int32,ps:1}],sn:"$ctor1"},{a:2,n:"Dispose",t:8,sn:"Dispose",rt:$n[0].Void},{a:2,n:"MoveNext",t:8,sn:"moveNext",rt:$n[0].Boolean,box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Current",t:16,rt:$n[3].KeyValuePair$2(TKey,TValue),g:{a:2,n:"get_Current",t:8,rt:$n[3].KeyValuePair$2(TKey,TValue),fg:"Current"},fn:"Current"},{a:4,n:"DictEntry",is:!0,t:4,rt:$n[0].Int32,sn:"DictEntry",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"KeyValuePair",is:!0,t:4,rt:$n[0].Int32,sn:"KeyValuePair",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"current",t:4,rt:$n[3].KeyValuePair$2(TKey,TValue),sn:"current"},{a:1,n:"dictionary",t:4,rt:$n[3].Dictionary$2(TKey,TValue),sn:"dictionary"},{a:1,n:"getEnumeratorRetType",t:4,rt:$n[0].Int32,sn:"getEnumeratorRetType",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"index",t:4,rt:$n[0].Int32,sn:"index",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"version",t:4,rt:$n[0].Int32,sn:"version",box:function($v){return H5.box($v,System.Int32)}}]}},$n);$m("System.Collections.Generic.Dictionary$2.KeyCollection",function(TKey,TValue){return{td:$n[3].Dictionary$2(TKey,TValue),nested:[$n[3].Dictionary$2.KeyCollection.Enumerator],att:1057026,a:2,at:[new System.SerializableAttribute],m:[{a:2,n:".ctor",t:1,p:[$n[3].Dictionary$2(TKey,TValue)],pi:[{n:"dictionary",pt:$n[3].Dictionary$2(TKey,TValue),ps:0}],sn:"ctor"},{a:2,n:"CopyTo",t:8,pi:[{n:"array",pt:System.Array.type(TKey),ps:0},{n:"index",pt:$n[0].Int32,ps:1}],sn:"copyTo",rt:$n[0].Void,p:[System.Array.type(TKey),$n[0].Int32]},{a:2,n:"GetEnumerator",t:8,sn:"GetEnumerator",rt:$n[3].Dictionary$2.KeyCollection.Enumerator(TKey,TValue)},{a:2,n:"Count",t:16,rt:$n[0].Int32,g:{a:2,n:"get_Count",t:8,rt:$n[0].Int32,fg:"Count",box:function($v){return H5.box($v,System.Int32)}},fn:"Count"},{a:1,n:"dictionary",t:4,rt:$n[3].Dictionary$2(TKey,TValue),sn:"dictionary"}]}},$n);$m("System.Collections.Generic.Dictionary$2.KeyCollection.Enumerator",function(TKey,TValue){return{td:$n[3].Dictionary$2.KeyCollection(TKey,TValue),att:1057034,a:2,at:[new System.SerializableAttribute],m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:4,n:".ctor",t:1,p:[$n[3].Dictionary$2(TKey,TValue)],pi:[{n:"dictionary",pt:$n[3].Dictionary$2(TKey,TValue),ps:0}],sn:"$ctor1"},{a:2,n:"Dispose",t:8,sn:"Dispose",rt:$n[0].Void},{a:2,n:"MoveNext",t:8,sn:"moveNext",rt:$n[0].Boolean,box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Current",t:16,rt:TKey,g:{a:2,n:"get_Current",t:8,rt:TKey,fg:"Current"},fn:"Current"},{a:1,n:"currentKey",t:4,rt:TKey,sn:"currentKey"},{a:1,n:"dictionary",t:4,rt:$n[3].Dictionary$2(TKey,TValue),sn:"dictionary"},{a:1,n:"index",t:4,rt:$n[0].Int32,sn:"index",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"version",t:4,rt:$n[0].Int32,sn:"version",box:function($v){return H5.box($v,System.Int32)}}]}},$n);$m("System.Collections.Generic.Dictionary$2.ValueCollection",function(TKey,TValue){return{td:$n[3].Dictionary$2(TKey,TValue),nested:[$n[3].Dictionary$2.ValueCollection.Enumerator],att:1057026,a:2,at:[new System.SerializableAttribute],m:[{a:2,n:".ctor",t:1,p:[$n[3].Dictionary$2(TKey,TValue)],pi:[{n:"dictionary",pt:$n[3].Dictionary$2(TKey,TValue),ps:0}],sn:"ctor"},{a:2,n:"CopyTo",t:8,pi:[{n:"array",pt:System.Array.type(TValue),ps:0},{n:"index",pt:$n[0].Int32,ps:1}],sn:"copyTo",rt:$n[0].Void,p:[System.Array.type(TValue),$n[0].Int32]},{a:2,n:"GetEnumerator",t:8,sn:"GetEnumerator",rt:$n[3].Dictionary$2.ValueCollection.Enumerator(TKey,TValue)},{a:2,n:"Count",t:16,rt:$n[0].Int32,g:{a:2,n:"get_Count",t:8,rt:$n[0].Int32,fg:"Count",box:function($v){return H5.box($v,System.Int32)}},fn:"Count"},{a:1,n:"dictionary",t:4,rt:$n[3].Dictionary$2(TKey,TValue),sn:"dictionary"}]}},$n);$m("System.Collections.Generic.Dictionary$2.ValueCollection.Enumerator",function(TKey,TValue){return{td:$n[3].Dictionary$2.ValueCollection(TKey,TValue),att:1057034,a:2,at:[new System.SerializableAttribute],m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:4,n:".ctor",t:1,p:[$n[3].Dictionary$2(TKey,TValue)],pi:[{n:"dictionary",pt:$n[3].Dictionary$2(TKey,TValue),ps:0}],sn:"$ctor1"},{a:2,n:"Dispose",t:8,sn:"Dispose",rt:$n[0].Void},{a:2,n:"MoveNext",t:8,sn:"moveNext",rt:$n[0].Boolean,box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Current",t:16,rt:TValue,g:{a:2,n:"get_Current",t:8,rt:TValue,fg:"Current"},fn:"Current"},{a:1,n:"currentValue",t:4,rt:TValue,sn:"currentValue"},{a:1,n:"dictionary",t:4,rt:$n[3].Dictionary$2(TKey,TValue),sn:"dictionary"},{a:1,n:"index",t:4,rt:$n[0].Int32,sn:"index",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"version",t:4,rt:$n[0].Int32,sn:"version",box:function($v){return H5.box($v,System.Int32)}}]}},$n);$m("System.Collections.Generic.CollectionExtensions",function(){return{att:1048961,a:2,s:!0,m:[{a:2,n:"GetValueOrDefault",is:!0,t:8,pi:[{n:"dictionary",pt:$n[3].IReadOnlyDictionary$2(System.Object,System.Object),ps:0},{n:"key",pt:System.Object,ps:1}],tpc:2,tprm:["TKey","TValue"],sn:"GetValueOrDefault$1",rt:System.Object,p:[$n[3].IReadOnlyDictionary$2(System.Object,System.Object),System.Object]},{a:2,n:"GetValueOrDefault",is:!0,t:8,pi:[{n:"dictionary",pt:$n[3].IReadOnlyDictionary$2(System.Object,System.Object),ps:0},{n:"key",pt:System.Object,ps:1},{n:"defaultValue",pt:System.Object,ps:2}],tpc:2,tprm:["TKey","TValue"],sn:"GetValueOrDefault",rt:System.Object,p:[$n[3].IReadOnlyDictionary$2(System.Object,System.Object),System.Object,System.Object]},{a:2,n:"Remove",is:!0,t:8,pi:[{n:"dictionary",pt:$n[3].IDictionary$2(System.Object,System.Object),ps:0},{n:"key",pt:System.Object,ps:1},{n:"value",out:!0,pt:System.Object,ps:2}],tpc:2,tprm:["TKey","TValue"],sn:"Remove",rt:$n[0].Boolean,p:[$n[3].IDictionary$2(System.Object,System.Object),System.Object,System.Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"TryAdd",is:!0,t:8,pi:[{n:"dictionary",pt:$n[3].IDictionary$2(System.Object,System.Object),ps:0},{n:"key",pt:System.Object,ps:1},{n:"value",pt:System.Object,ps:2}],tpc:2,tprm:["TKey","TValue"],sn:"TryAdd",rt:$n[0].Boolean,p:[$n[3].IDictionary$2(System.Object,System.Object),System.Object,System.Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}}]}},$n);$m("H5.Collections.EnumerableHelpers",function(){return{att:1048960,a:4,s:!0,m:[{a:4,n:"ToArray",is:!0,t:8,pi:[{n:"source",pt:$n[3].IEnumerable$1(System.Object),ps:0}],tpc:1,tprm:["T"],sn:"ToArray",rt:System.Array.type(System.Object),p:[$n[3].IEnumerable$1(System.Object)]},{a:4,n:"ToArray",is:!0,t:8,pi:[{n:"source",pt:$n[3].IEnumerable$1(System.Object),ps:0},{n:"length",out:!0,pt:$n[0].Int32,ps:1}],tpc:1,tprm:["T"],sn:"ToArray$1",rt:System.Array.type(System.Object),p:[$n[3].IEnumerable$1(System.Object),$n[0].Int32]}]}},$n);$m("System.Collections.Generic.ICollection$1",function(T){return{att:1048737,a:2,m:[{ab:!0,a:2,n:"Add",t:8,pi:[{n:"item",pt:T,ps:0}],tpc:0,def:function(item){return System.Array.add(this,item,T)},rt:$n[0].Void,p:[T]},{ab:!0,a:2,n:"Clear",t:8,tpc:0,def:function(){return System.Array.clear(this,T)},rt:$n[0].Void},{ab:!0,a:2,n:"Contains",t:8,pi:[{n:"item",pt:T,ps:0}],tpc:0,def:function(item){return System.Array.contains(this,item,T)},rt:$n[0].Boolean,p:[T],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ab:!0,a:2,n:"CopyTo",t:8,pi:[{n:"array",pt:System.Array.type(T),ps:0},{n:"arrayIndex",pt:$n[0].Int32,ps:1}],tpc:0,def:function(array,arrayIndex){return System.Array.copyTo(this,array,arrayIndex,T)},rt:$n[0].Void,p:[System.Array.type(T),$n[0].Int32]},{ab:!0,a:2,n:"Remove",t:8,pi:[{n:"item",pt:T,ps:0}],tpc:0,def:function(item){return System.Array.remove(this,item,T)},rt:$n[0].Boolean,p:[T],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ab:!0,a:2,n:"Count",t:16,rt:$n[0].Int32,g:{ab:!0,a:2,n:"get_Count",t:8,tpc:0,def:function(){return System.Array.getCount(this,T)},rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}}},{ab:!0,a:2,n:"IsReadOnly",t:16,rt:$n[0].Boolean,g:{ab:!0,a:2,n:"get_IsReadOnly",t:8,tpc:0,def:function(){return System.Array.getIsReadOnly(this,T)},rt:$n[0].Boolean,box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Int32,sn:'"System$Collections$Generic$ICollection$1$" + H5.getTypeAlias(T) + "$Count"',box:function($v){return H5.box($v,System.Int32)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Boolean,sn:'"System$Collections$Generic$ICollection$1$" + H5.getTypeAlias(T) + "$IsReadOnly"',box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}}]}},$n);$m("System.Collections.Generic.IDictionary$2",function(TKey,TValue){return{att:1048737,a:2,m:[{ab:!0,a:2,n:"Add",t:8,pi:[{n:"key",pt:TKey,ps:0},{n:"value",pt:TValue,ps:1}],sn:"System$Collections$Generic$IDictionary$2$"+H5.getTypeAlias(TKey)+"$"+H5.getTypeAlias(TValue)+"$add",rt:$n[0].Void,p:[TKey,TValue]},{ab:!0,a:2,n:"ContainsKey",t:8,pi:[{n:"key",pt:TKey,ps:0}],sn:"System$Collections$Generic$IDictionary$2$"+H5.getTypeAlias(TKey)+"$"+H5.getTypeAlias(TValue)+"$containsKey",rt:$n[0].Boolean,p:[TKey],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ab:!0,a:2,n:"Remove",t:8,pi:[{n:"key",pt:TKey,ps:0}],sn:"System$Collections$Generic$IDictionary$2$"+H5.getTypeAlias(TKey)+"$"+H5.getTypeAlias(TValue)+"$remove",rt:$n[0].Boolean,p:[TKey],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ab:!0,a:2,n:"TryGetValue",t:8,pi:[{n:"key",pt:TKey,ps:0},{n:"value",out:!0,pt:TValue,ps:1}],sn:"System$Collections$Generic$IDictionary$2$"+H5.getTypeAlias(TKey)+"$"+H5.getTypeAlias(TValue)+"$tryGetValue",rt:$n[0].Boolean,p:[TKey,TValue],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ab:!0,a:2,n:"Item",t:16,rt:TValue,p:[TKey],i:!0,ipi:[{n:"key",pt:TKey,ps:0}],g:{ab:!0,a:2,n:"get_Item",t:8,pi:[{n:"key",pt:TKey,ps:0}],sn:"System$Collections$Generic$IDictionary$2$"+H5.getTypeAlias(TKey)+"$"+H5.getTypeAlias(TValue)+"$getItem",rt:TValue,p:[TKey]},s:{ab:!0,a:2,n:"set_Item",t:8,pi:[{n:"key",pt:TKey,ps:0},{n:"value",pt:TValue,ps:1}],sn:"System$Collections$Generic$IDictionary$2$"+H5.getTypeAlias(TKey)+"$"+H5.getTypeAlias(TValue)+"$setItem",rt:$n[0].Void,p:[TKey,TValue]}},{ab:!0,a:2,n:"Keys",t:16,rt:$n[3].ICollection$1(TKey),g:{ab:!0,a:2,n:"get_Keys",t:8,rt:$n[3].ICollection$1(TKey),fg:'"System$Collections$Generic$IDictionary$2$" + H5.getTypeAlias(TKey) + "$" + H5.getTypeAlias(TValue) + "$Keys"'},fn:'"System$Collections$Generic$IDictionary$2$" + H5.getTypeAlias(TKey) + "$" + H5.getTypeAlias(TValue) + "$Keys"'},{ab:!0,a:2,n:"Values",t:16,rt:$n[3].ICollection$1(TValue),g:{ab:!0,a:2,n:"get_Values",t:8,rt:$n[3].ICollection$1(TValue),fg:'"System$Collections$Generic$IDictionary$2$" + H5.getTypeAlias(TKey) + "$" + H5.getTypeAlias(TValue) + "$Values"'},fn:'"System$Collections$Generic$IDictionary$2$" + H5.getTypeAlias(TKey) + "$" + H5.getTypeAlias(TValue) + "$Values"'},{a:1,backing:!0,n:"k__BackingField",t:4,rt:TValue,sn:'"System$Collections$Generic$IDictionary$2$" + H5.getTypeAlias(TKey) + "$" + H5.getTypeAlias(TValue) + "$Item"'},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[3].ICollection$1(TKey),sn:'"System$Collections$Generic$IDictionary$2$" + H5.getTypeAlias(TKey) + "$" + H5.getTypeAlias(TValue) + "$Keys"'},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[3].ICollection$1(TValue),sn:'"System$Collections$Generic$IDictionary$2$" + H5.getTypeAlias(TKey) + "$" + H5.getTypeAlias(TValue) + "$Values"'}]}},$n);$m("System.Collections.Generic.IEnumerable$1",function(T){return{att:1048737,a:2,m:[{ab:!0,a:2,n:"GetEnumerator",t:8,tpc:0,def:function(){return H5.getEnumerator(this,T)},rt:$n[3].IEnumerator$1(T)}]}},$n);$m("System.Collections.Generic.IEqualityComparer$1",function(T){return{att:1048737,a:2,m:[{ab:!0,a:2,n:"Equals",t:8,pi:[{n:"x",pt:T,ps:0},{n:"y",pt:T,ps:1}],sn:"System$Collections$Generic$IEqualityComparer$1$"+H5.getTypeAlias(T)+"$equals2",rt:$n[0].Boolean,p:[T,T],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ab:!0,a:2,n:"GetHashCode",t:8,pi:[{n:"obj",pt:T,ps:0}],sn:"System$Collections$Generic$IEqualityComparer$1$"+H5.getTypeAlias(T)+"$getHashCode2",rt:$n[0].Int32,p:[T],box:function($v){return H5.box($v,System.Int32)}}]}},$n);$m("System.Collections.Generic.EqualityComparer$1",function(T){return{att:1048705,a:2,m:[{a:3,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{v:!0,a:2,n:"Equals",t:8,pi:[{n:"x",pt:T,ps:0},{n:"y",pt:T,ps:1}],sn:"equals2",rt:$n[0].Boolean,p:[T,T],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{v:!0,a:2,n:"GetHashCode",t:8,pi:[{n:"obj",pt:T,ps:0}],sn:"getHashCode2",rt:$n[0].Int32,p:[T],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"Default",is:!0,t:16,rt:$n[3].EqualityComparer$1(T),g:{a:2,n:"get_Default",is:!0,t:8,tpc:0,def:function(){return System.Collections.Generic.EqualityComparer$1(T).def},rt:$n[3].EqualityComparer$1(T)}},{a:1,backing:!0,n:"k__BackingField",is:!0,t:4,rt:$n[3].EqualityComparer$1(T),sn:"Default"}]}},$n);$m("System.Collections.Generic.IList$1",function(T){return{att:1048737,a:2,m:[{ab:!0,a:2,n:"IndexOf",t:8,pi:[{n:"item",pt:T,ps:0}],tpc:0,def:function(item){return System.Array.indexOf(this,item,0,null,T)},rt:$n[0].Int32,p:[T],box:function($v){return H5.box($v,System.Int32)}},{ab:!0,a:2,n:"Insert",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0},{n:"item",pt:T,ps:1}],tpc:0,def:function(index,item){return System.Array.insert(this,index,item,T)},rt:$n[0].Void,p:[$n[0].Int32,T]},{ab:!0,a:2,n:"RemoveAt",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0}],tpc:0,def:function(index){return System.Array.removeAt(this,index,T)},rt:$n[0].Void,p:[$n[0].Int32]},{ab:!0,a:2,n:"Item",t:16,rt:T,p:[$n[0].Int32],i:!0,ipi:[{n:"index",pt:$n[0].Int32,ps:0}],g:{ab:!0,a:2,n:"get_Item",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0}],tpc:0,def:function(index){return System.Array.getItem(this,index,T)},rt:T,p:[$n[0].Int32]},s:{ab:!0,a:2,n:"set_Item",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0},{n:"value",pt:T,ps:1}],tpc:0,def:function(index,value){return System.Array.setItem(this,index,value,T)},rt:$n[0].Void,p:[$n[0].Int32,T]}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:T,sn:'"System$Collections$Generic$IList$1$" + H5.getTypeAlias(T) + "$Item"'}]}},$n);$m("System.Collections.Generic.IReadOnlyCollection$1",function(T){return{att:1048737,a:2,m:[{ab:!0,a:2,n:"Count",t:16,rt:$n[0].Int32,g:{ab:!0,a:2,n:"get_Count",t:8,tpc:0,def:function(){return System.Array.getCount(this,T)},rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Int32,sn:'"System$Collections$Generic$IReadOnlyCollection$1$" + H5.getTypeAlias(T) + "$Count"',box:function($v){return H5.box($v,System.Int32)}}]}},$n);$m("System.Collections.Generic.IReadOnlyDictionary$2",function(TKey,TValue){return{att:1048737,a:2,m:[{ab:!0,a:2,n:"ContainsKey",t:8,pi:[{n:"key",pt:TKey,ps:0}],sn:"System$Collections$Generic$IReadOnlyDictionary$2$"+H5.getTypeAlias(TKey)+"$"+H5.getTypeAlias(TValue)+"$containsKey",rt:$n[0].Boolean,p:[TKey],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ab:!0,a:2,n:"TryGetValue",t:8,pi:[{n:"key",pt:TKey,ps:0},{n:"value",out:!0,pt:TValue,ps:1}],sn:"System$Collections$Generic$IReadOnlyDictionary$2$"+H5.getTypeAlias(TKey)+"$"+H5.getTypeAlias(TValue)+"$tryGetValue",rt:$n[0].Boolean,p:[TKey,TValue],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ab:!0,a:2,n:"Item",t:16,rt:TValue,p:[TKey],i:!0,ipi:[{n:"key",pt:TKey,ps:0}],g:{ab:!0,a:2,n:"get_Item",t:8,pi:[{n:"key",pt:TKey,ps:0}],sn:"System$Collections$Generic$IReadOnlyDictionary$2$"+H5.getTypeAlias(TKey)+"$"+H5.getTypeAlias(TValue)+"$getItem",rt:TValue,p:[TKey]}},{ab:!0,a:2,n:"Keys",t:16,rt:$n[3].IEnumerable$1(TKey),g:{ab:!0,a:2,n:"get_Keys",t:8,rt:$n[3].IEnumerable$1(TKey),fg:'"System$Collections$Generic$IReadOnlyDictionary$2$" + H5.getTypeAlias(TKey) + "$" + H5.getTypeAlias(TValue) + "$Keys"'},fn:'"System$Collections$Generic$IReadOnlyDictionary$2$" + H5.getTypeAlias(TKey) + "$" + H5.getTypeAlias(TValue) + "$Keys"'},{ab:!0,a:2,n:"Values",t:16,rt:$n[3].IEnumerable$1(TValue),g:{ab:!0,a:2,n:"get_Values",t:8,rt:$n[3].IEnumerable$1(TValue),fg:'"System$Collections$Generic$IReadOnlyDictionary$2$" + H5.getTypeAlias(TKey) + "$" + H5.getTypeAlias(TValue) + "$Values"'},fn:'"System$Collections$Generic$IReadOnlyDictionary$2$" + H5.getTypeAlias(TKey) + "$" + H5.getTypeAlias(TValue) + "$Values"'},{a:1,backing:!0,n:"k__BackingField",t:4,rt:TValue,sn:'"System$Collections$Generic$IReadOnlyDictionary$2$" + H5.getTypeAlias(TKey) + "$" + H5.getTypeAlias(TValue) + "$getItem"'},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[3].IEnumerable$1(TKey),sn:'"System$Collections$Generic$IReadOnlyDictionary$2$" + H5.getTypeAlias(TKey) + "$" + H5.getTypeAlias(TValue) + "$Keys"'},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[3].IEnumerable$1(TValue),sn:'"System$Collections$Generic$IReadOnlyDictionary$2$" + H5.getTypeAlias(TKey) + "$" + H5.getTypeAlias(TValue) + "$Values"'}]}},$n);$m("System.Collections.Generic.IReadOnlyList$1",function(T){return{att:1048737,a:2,m:[{ab:!0,a:2,n:"Item",t:16,rt:T,p:[$n[0].Int32],i:!0,ipi:[{n:"index",pt:$n[0].Int32,ps:0}],g:{ab:!0,a:2,n:"get_Item",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0}],tpc:0,def:function(index){return System.Array.getItem(this,index,T)},rt:T,p:[$n[0].Int32]}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:T,sn:'"System$Collections$Generic$IReadOnlyList$1$" + H5.getTypeAlias(T) + "$Item"'}]}},$n);$m("System.Collections.Generic.ISet$1",function(T){return{att:1048737,a:2,m:[{ab:!0,a:2,n:"Add",t:8,pi:[{n:"item",pt:T,ps:0}],sn:"System$Collections$Generic$ISet$1$"+H5.getTypeAlias(T)+"$add",rt:$n[0].Boolean,p:[T],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ab:!0,a:2,n:"ExceptWith",t:8,pi:[{n:"other",pt:$n[3].IEnumerable$1(T),ps:0}],sn:"System$Collections$Generic$ISet$1$"+H5.getTypeAlias(T)+"$exceptWith",rt:$n[0].Void,p:[$n[3].IEnumerable$1(T)]},{ab:!0,a:2,n:"IntersectWith",t:8,pi:[{n:"other",pt:$n[3].IEnumerable$1(T),ps:0}],sn:"System$Collections$Generic$ISet$1$"+H5.getTypeAlias(T)+"$intersectWith",rt:$n[0].Void,p:[$n[3].IEnumerable$1(T)]},{ab:!0,a:2,n:"IsProperSubsetOf",t:8,pi:[{n:"other",pt:$n[3].IEnumerable$1(T),ps:0}],sn:"System$Collections$Generic$ISet$1$"+H5.getTypeAlias(T)+"$isProperSubsetOf",rt:$n[0].Boolean,p:[$n[3].IEnumerable$1(T)],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ab:!0,a:2,n:"IsProperSupersetOf",t:8,pi:[{n:"other",pt:$n[3].IEnumerable$1(T),ps:0}],sn:"System$Collections$Generic$ISet$1$"+H5.getTypeAlias(T)+"$isProperSupersetOf",rt:$n[0].Boolean,p:[$n[3].IEnumerable$1(T)],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ab:!0,a:2,n:"IsSubsetOf",t:8,pi:[{n:"other",pt:$n[3].IEnumerable$1(T),ps:0}],sn:"System$Collections$Generic$ISet$1$"+H5.getTypeAlias(T)+"$isSubsetOf",rt:$n[0].Boolean,p:[$n[3].IEnumerable$1(T)],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ab:!0,a:2,n:"IsSupersetOf",t:8,pi:[{n:"other",pt:$n[3].IEnumerable$1(T),ps:0}],sn:"System$Collections$Generic$ISet$1$"+H5.getTypeAlias(T)+"$isSupersetOf",rt:$n[0].Boolean,p:[$n[3].IEnumerable$1(T)],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ab:!0,a:2,n:"Overlaps",t:8,pi:[{n:"other",pt:$n[3].IEnumerable$1(T),ps:0}],sn:"System$Collections$Generic$ISet$1$"+H5.getTypeAlias(T)+"$overlaps",rt:$n[0].Boolean,p:[$n[3].IEnumerable$1(T)],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ab:!0,a:2,n:"SetEquals",t:8,pi:[{n:"other",pt:$n[3].IEnumerable$1(T),ps:0}],sn:"System$Collections$Generic$ISet$1$"+H5.getTypeAlias(T)+"$setEquals",rt:$n[0].Boolean,p:[$n[3].IEnumerable$1(T)],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ab:!0,a:2,n:"SymmetricExceptWith",t:8,pi:[{n:"other",pt:$n[3].IEnumerable$1(T),ps:0}],sn:"System$Collections$Generic$ISet$1$"+H5.getTypeAlias(T)+"$symmetricExceptWith",rt:$n[0].Void,p:[$n[3].IEnumerable$1(T)]},{ab:!0,a:2,n:"UnionWith",t:8,pi:[{n:"other",pt:$n[3].IEnumerable$1(T),ps:0}],sn:"System$Collections$Generic$ISet$1$"+H5.getTypeAlias(T)+"$unionWith",rt:$n[0].Void,p:[$n[3].IEnumerable$1(T)]}]}},$n);$m("System.Collections.Generic.LinkedList$1",function(T){return{nested:[$n[3].LinkedList$1.Enumerator],att:1048577,a:2,m:[{a:2,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[3].IEnumerable$1(T)],pi:[{n:"collection",pt:$n[3].IEnumerable$1(T),ps:0}],sn:"$ctor1"},{a:2,n:"AddAfter",t:8,pi:[{n:"node",pt:$n[3].LinkedListNode$1(T),ps:0},{n:"newNode",pt:$n[3].LinkedListNode$1(T),ps:1}],sn:"AddAfter$1",rt:$n[0].Void,p:[$n[3].LinkedListNode$1(T),$n[3].LinkedListNode$1(T)]},{a:2,n:"AddAfter",t:8,pi:[{n:"node",pt:$n[3].LinkedListNode$1(T),ps:0},{n:"value",pt:T,ps:1}],sn:"AddAfter",rt:$n[3].LinkedListNode$1(T),p:[$n[3].LinkedListNode$1(T),T]},{a:2,n:"AddBefore",t:8,pi:[{n:"node",pt:$n[3].LinkedListNode$1(T),ps:0},{n:"newNode",pt:$n[3].LinkedListNode$1(T),ps:1}],sn:"AddBefore$1",rt:$n[0].Void,p:[$n[3].LinkedListNode$1(T),$n[3].LinkedListNode$1(T)]},{a:2,n:"AddBefore",t:8,pi:[{n:"node",pt:$n[3].LinkedListNode$1(T),ps:0},{n:"value",pt:T,ps:1}],sn:"AddBefore",rt:$n[3].LinkedListNode$1(T),p:[$n[3].LinkedListNode$1(T),T]},{a:2,n:"AddFirst",t:8,pi:[{n:"node",pt:$n[3].LinkedListNode$1(T),ps:0}],sn:"AddFirst$1",rt:$n[0].Void,p:[$n[3].LinkedListNode$1(T)]},{a:2,n:"AddFirst",t:8,pi:[{n:"value",pt:T,ps:0}],sn:"AddFirst",rt:$n[3].LinkedListNode$1(T),p:[T]},{a:2,n:"AddLast",t:8,pi:[{n:"node",pt:$n[3].LinkedListNode$1(T),ps:0}],sn:"AddLast$1",rt:$n[0].Void,p:[$n[3].LinkedListNode$1(T)]},{a:2,n:"AddLast",t:8,pi:[{n:"value",pt:T,ps:0}],sn:"AddLast",rt:$n[3].LinkedListNode$1(T),p:[T]},{a:2,n:"Clear",t:8,sn:"clear",rt:$n[0].Void},{a:2,n:"Contains",t:8,pi:[{n:"value",pt:T,ps:0}],sn:"contains",rt:$n[0].Boolean,p:[T],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"CopyTo",t:8,pi:[{n:"array",pt:System.Array.type(T),ps:0},{n:"index",pt:$n[0].Int32,ps:1}],sn:"copyTo",rt:$n[0].Void,p:[System.Array.type(T),$n[0].Int32]},{a:2,n:"Find",t:8,pi:[{n:"value",pt:T,ps:0}],sn:"Find",rt:$n[3].LinkedListNode$1(T),p:[T]},{a:2,n:"FindLast",t:8,pi:[{n:"value",pt:T,ps:0}],sn:"FindLast",rt:$n[3].LinkedListNode$1(T),p:[T]},{a:2,n:"GetEnumerator",t:8,sn:"GetEnumerator",rt:$n[3].LinkedList$1.Enumerator(T)},{a:1,n:"InternalInsertNodeBefore",t:8,pi:[{n:"node",pt:$n[3].LinkedListNode$1(T),ps:0},{n:"newNode",pt:$n[3].LinkedListNode$1(T),ps:1}],sn:"InternalInsertNodeBefore",rt:$n[0].Void,p:[$n[3].LinkedListNode$1(T),$n[3].LinkedListNode$1(T)]},{a:1,n:"InternalInsertNodeToEmptyList",t:8,pi:[{n:"newNode",pt:$n[3].LinkedListNode$1(T),ps:0}],sn:"InternalInsertNodeToEmptyList",rt:$n[0].Void,p:[$n[3].LinkedListNode$1(T)]},{a:4,n:"InternalRemoveNode",t:8,pi:[{n:"node",pt:$n[3].LinkedListNode$1(T),ps:0}],sn:"InternalRemoveNode",rt:$n[0].Void,p:[$n[3].LinkedListNode$1(T)]},{a:2,n:"Remove",t:8,pi:[{n:"node",pt:$n[3].LinkedListNode$1(T),ps:0}],sn:"Remove",rt:$n[0].Void,p:[$n[3].LinkedListNode$1(T)]},{a:2,n:"Remove",t:8,pi:[{n:"value",pt:T,ps:0}],sn:"remove",rt:$n[0].Boolean,p:[T],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"RemoveFirst",t:8,sn:"RemoveFirst",rt:$n[0].Void},{a:2,n:"RemoveLast",t:8,sn:"RemoveLast",rt:$n[0].Void},{a:4,n:"ValidateNewNode",t:8,pi:[{n:"node",pt:$n[3].LinkedListNode$1(T),ps:0}],sn:"ValidateNewNode",rt:$n[0].Void,p:[$n[3].LinkedListNode$1(T)]},{a:4,n:"ValidateNode",t:8,pi:[{n:"node",pt:$n[3].LinkedListNode$1(T),ps:0}],sn:"ValidateNode",rt:$n[0].Void,p:[$n[3].LinkedListNode$1(T)]},{a:2,n:"Count",t:16,rt:$n[0].Int32,g:{a:2,n:"get_Count",t:8,rt:$n[0].Int32,fg:"Count",box:function($v){return H5.box($v,System.Int32)}},fn:"Count"},{a:2,n:"First",t:16,rt:$n[3].LinkedListNode$1(T),g:{a:2,n:"get_First",t:8,rt:$n[3].LinkedListNode$1(T),fg:"First"},fn:"First"},{a:2,n:"Last",t:16,rt:$n[3].LinkedListNode$1(T),g:{a:2,n:"get_Last",t:8,rt:$n[3].LinkedListNode$1(T),fg:"Last"},fn:"Last"},{a:1,n:"CountName",is:!0,t:4,rt:$n[0].String,sn:"CountName"},{a:1,n:"ValuesName",is:!0,t:4,rt:$n[0].String,sn:"ValuesName"},{a:1,n:"VersionName",is:!0,t:4,rt:$n[0].String,sn:"VersionName"},{a:4,n:"count",t:4,rt:$n[0].Int32,sn:"count",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"head",t:4,rt:$n[3].LinkedListNode$1(T),sn:"head"},{a:4,n:"version",t:4,rt:$n[0].Int32,sn:"version",box:function($v){return H5.box($v,System.Int32)}}]}},$n);$m("System.Collections.Generic.LinkedList$1.Enumerator",function(T){return{td:$n[3].LinkedList$1(T),att:1048842,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:4,n:".ctor",t:1,p:[$n[3].LinkedList$1(T)],pi:[{n:"list",pt:$n[3].LinkedList$1(T),ps:0}],sn:"$ctor1"},{a:2,n:"Dispose",t:8,sn:"Dispose",rt:$n[0].Void},{a:2,n:"MoveNext",t:8,sn:"moveNext",rt:$n[0].Boolean,box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Current",t:16,rt:T,g:{a:2,n:"get_Current",t:8,rt:T,fg:"Current"},fn:"Current"},{a:1,n:"CurrentValueName",is:!0,t:4,rt:$n[0].String,sn:"CurrentValueName"},{a:1,n:"IndexName",is:!0,t:4,rt:$n[0].String,sn:"IndexName"},{a:1,n:"LinkedListName",is:!0,t:4,rt:$n[0].String,sn:"LinkedListName"},{a:1,n:"VersionName",is:!0,t:4,rt:$n[0].String,sn:"VersionName"},{a:1,n:"current",t:4,rt:T,sn:"current"},{a:1,n:"index",t:4,rt:$n[0].Int32,sn:"index",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"list",t:4,rt:$n[3].LinkedList$1(T),sn:"list"},{a:1,n:"node",t:4,rt:$n[3].LinkedListNode$1(T),sn:"node"},{a:1,n:"version",t:4,rt:$n[0].Int32,sn:"version",box:function($v){return H5.box($v,System.Int32)}}]}},$n);$m("System.Collections.Generic.LinkedListNode$1",function(T){return{att:1048833,a:2,m:[{a:2,n:".ctor",t:1,p:[T],pi:[{n:"value",pt:T,ps:0}],sn:"ctor"},{a:4,n:".ctor",t:1,p:[$n[3].LinkedList$1(T),T],pi:[{n:"list",pt:$n[3].LinkedList$1(T),ps:0},{n:"value",pt:T,ps:1}],sn:"$ctor1"},{a:4,n:"Invalidate",t:8,sn:"Invalidate",rt:$n[0].Void},{a:2,n:"List",t:16,rt:$n[3].LinkedList$1(T),g:{a:2,n:"get_List",t:8,rt:$n[3].LinkedList$1(T),fg:"List"},fn:"List"},{a:2,n:"Next",t:16,rt:$n[3].LinkedListNode$1(T),g:{a:2,n:"get_Next",t:8,rt:$n[3].LinkedListNode$1(T),fg:"Next"},fn:"Next"},{a:2,n:"Previous",t:16,rt:$n[3].LinkedListNode$1(T),g:{a:2,n:"get_Previous",t:8,rt:$n[3].LinkedListNode$1(T),fg:"Previous"},fn:"Previous"},{a:2,n:"Value",t:16,rt:T,g:{a:2,n:"get_Value",t:8,rt:T,fg:"Value"},s:{a:2,n:"set_Value",t:8,p:[T],rt:$n[0].Void,fs:"Value"},fn:"Value"},{a:4,n:"item",t:4,rt:T,sn:"item"},{a:4,n:"list",t:4,rt:$n[3].LinkedList$1(T),sn:"list"},{a:4,n:"next",t:4,rt:$n[3].LinkedListNode$1(T),sn:"next"},{a:4,n:"prev",t:4,rt:$n[3].LinkedListNode$1(T),sn:"prev"}]}},$n);$m("System.Collections.Generic.SortedList$2",function(TKey,TValue){return{nested:[$n[3].SortedList$2.Enumerator,$n[3].SortedList$2.SortedListKeyEnumerator,$n[3].SortedList$2.SortedListValueEnumerator,$n[3].SortedList$2.KeyList,$n[3].SortedList$2.ValueList],att:1048577,a:2,m:[{a:2,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[3].IComparer$1(TKey)],pi:[{n:"comparer",pt:$n[3].IComparer$1(TKey),ps:0}],sn:"$ctor1"},{a:2,n:".ctor",t:1,p:[$n[3].IDictionary$2(TKey,TValue)],pi:[{n:"dictionary",pt:$n[3].IDictionary$2(TKey,TValue),ps:0}],sn:"$ctor2"},{a:2,n:".ctor",t:1,p:[$n[0].Int32],pi:[{n:"capacity",pt:$n[0].Int32,ps:0}],sn:"$ctor4"},{a:2,n:".ctor",t:1,p:[$n[3].IDictionary$2(TKey,TValue),$n[3].IComparer$1(TKey)],pi:[{n:"dictionary",pt:$n[3].IDictionary$2(TKey,TValue),ps:0},{n:"comparer",pt:$n[3].IComparer$1(TKey),ps:1}],sn:"$ctor3"},{a:2,n:".ctor",t:1,p:[$n[0].Int32,$n[3].IComparer$1(TKey)],pi:[{n:"capacity",pt:$n[0].Int32,ps:0},{n:"comparer",pt:$n[3].IComparer$1(TKey),ps:1}],sn:"$ctor5"},{a:2,n:"Add",t:8,pi:[{n:"key",pt:TKey,ps:0},{n:"value",pt:TValue,ps:1}],sn:"add",rt:$n[0].Void,p:[TKey,TValue]},{a:2,n:"Clear",t:8,sn:"clear",rt:$n[0].Void},{a:2,n:"ContainsKey",t:8,pi:[{n:"key",pt:TKey,ps:0}],sn:"containsKey",rt:$n[0].Boolean,p:[TKey],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"ContainsValue",t:8,pi:[{n:"value",pt:TValue,ps:0}],sn:"ContainsValue",rt:$n[0].Boolean,p:[TValue],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"EnsureCapacity",t:8,pi:[{n:"min",pt:$n[0].Int32,ps:0}],sn:"EnsureCapacity",rt:$n[0].Void,p:[$n[0].Int32]},{a:1,n:"GetByIndex",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0}],sn:"GetByIndex",rt:TValue,p:[$n[0].Int32]},{a:2,n:"GetEnumerator",t:8,sn:"GetEnumerator",rt:$n[3].IEnumerator$1(System.Collections.Generic.KeyValuePair$2(TKey,TValue))},{a:1,n:"GetKey",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0}],sn:"GetKey",rt:TKey,p:[$n[0].Int32]},{a:1,n:"GetKeyListHelper",t:8,sn:"GetKeyListHelper",rt:$n[3].SortedList$2.KeyList(TKey,TValue)},{a:1,n:"GetValueListHelper",t:8,sn:"GetValueListHelper",rt:$n[3].SortedList$2.ValueList(TKey,TValue)},{a:2,n:"IndexOfKey",t:8,pi:[{n:"key",pt:TKey,ps:0}],sn:"IndexOfKey",rt:$n[0].Int32,p:[TKey],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"IndexOfValue",t:8,pi:[{n:"value",pt:TValue,ps:0}],sn:"IndexOfValue",rt:$n[0].Int32,p:[TValue],box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"Insert",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0},{n:"key",pt:TKey,ps:1},{n:"value",pt:TValue,ps:2}],sn:"Insert",rt:$n[0].Void,p:[$n[0].Int32,TKey,TValue]},{a:1,n:"IsCompatibleKey",is:!0,t:8,pi:[{n:"key",pt:$n[0].Object,ps:0}],sn:"IsCompatibleKey",rt:$n[0].Boolean,p:[$n[0].Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Remove",t:8,pi:[{n:"key",pt:TKey,ps:0}],sn:"remove",rt:$n[0].Boolean,p:[TKey],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"RemoveAt",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0}],sn:"RemoveAt",rt:$n[0].Void,p:[$n[0].Int32]},{a:2,n:"TrimExcess",t:8,sn:"TrimExcess",rt:$n[0].Void},{a:2,n:"TryGetValue",t:8,pi:[{n:"key",pt:TKey,ps:0},{n:"value",out:!0,pt:TValue,ps:1}],sn:"tryGetValue",rt:$n[0].Boolean,p:[TKey,TValue],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Capacity",t:16,rt:$n[0].Int32,g:{a:2,n:"get_Capacity",t:8,rt:$n[0].Int32,fg:"Capacity",box:function($v){return H5.box($v,System.Int32)}},s:{a:2,n:"set_Capacity",t:8,p:[$n[0].Int32],rt:$n[0].Void,fs:"Capacity"},fn:"Capacity"},{a:2,n:"Comparer",t:16,rt:$n[3].IComparer$1(TKey),g:{a:2,n:"get_Comparer",t:8,rt:$n[3].IComparer$1(TKey),fg:"Comparer"},fn:"Comparer"},{a:2,n:"Count",t:16,rt:$n[0].Int32,g:{a:2,n:"get_Count",t:8,rt:$n[0].Int32,fg:"Count",box:function($v){return H5.box($v,System.Int32)}},fn:"Count"},{a:2,n:"Item",t:16,rt:TValue,p:[TKey],i:!0,ipi:[{n:"key",pt:TKey,ps:0}],g:{a:2,n:"get_Item",t:8,pi:[{n:"key",pt:TKey,ps:0}],sn:"getItem",rt:TValue,p:[TKey]},s:{a:2,n:"set_Item",t:8,pi:[{n:"key",pt:TKey,ps:0},{n:"value",pt:TValue,ps:1}],sn:"setItem",rt:$n[0].Void,p:[TKey,TValue]}},{v:!0,a:2,n:"Item",t:16,rt:$n[0].Object,p:[$n[0].Object],i:!0,ipi:[{n:"key",pt:$n[0].Object,ps:0}],g:{v:!0,a:2,n:"get_Item",t:8,pi:[{n:"key",pt:$n[0].Object,ps:0}],sn:"getItem$1",rt:$n[0].Object,p:[$n[0].Object]},s:{v:!0,a:2,n:"set_Item",t:8,pi:[{n:"key",pt:$n[0].Object,ps:0},{n:"value",pt:$n[0].Object,ps:1}],sn:"setItem$1",rt:$n[0].Void,p:[$n[0].Object,$n[0].Object]}},{a:2,n:"Keys",t:16,rt:$n[3].IList$1(TKey),g:{a:2,n:"get_Keys",t:8,rt:$n[3].IList$1(TKey),fg:"Keys"},fn:"Keys"},{a:2,n:"Values",t:16,rt:$n[3].IList$1(TValue),g:{a:2,n:"get_Values",t:8,rt:$n[3].IList$1(TValue),fg:"Values"},fn:"Values"},{a:1,n:"MaxArrayLength",is:!0,t:4,rt:$n[0].Int32,sn:"MaxArrayLength",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"_defaultCapacity",is:!0,t:4,rt:$n[0].Int32,sn:"_defaultCapacity",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"_size",t:4,rt:$n[0].Int32,sn:"_size",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"comparer",t:4,rt:$n[3].IComparer$1(TKey),sn:"comparer"},{a:1,n:"emptyKeys",is:!0,t:4,rt:System.Array.type(TKey),sn:"emptyKeys"},{a:1,n:"emptyValues",is:!0,t:4,rt:System.Array.type(TValue),sn:"emptyValues"},{a:1,n:"keyList",t:4,rt:$n[3].SortedList$2.KeyList(TKey,TValue),sn:"keyList"},{a:1,n:"keys",t:4,rt:System.Array.type(TKey),sn:"keys"},{a:1,n:"valueList",t:4,rt:$n[3].SortedList$2.ValueList(TKey,TValue),sn:"valueList"},{a:1,n:"values",t:4,rt:System.Array.type(TValue),sn:"values"},{a:1,n:"version",t:4,rt:$n[0].Int32,sn:"version",box:function($v){return H5.box($v,System.Int32)}}]}},$n);$m("System.Collections.Generic.SortedList$2.Enumerator",function(TKey,TValue){return{td:$n[3].SortedList$2(TKey,TValue),att:1048843,a:1,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:4,n:".ctor",t:1,p:[$n[3].SortedList$2(TKey,TValue),$n[0].Int32],pi:[{n:"sortedList",pt:$n[3].SortedList$2(TKey,TValue),ps:0},{n:"getEnumeratorRetType",pt:$n[0].Int32,ps:1}],sn:"$ctor1"},{a:2,n:"Dispose",t:8,sn:"Dispose",rt:$n[0].Void},{a:2,n:"MoveNext",t:8,sn:"moveNext",rt:$n[0].Boolean,box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Current",t:16,rt:$n[3].KeyValuePair$2(TKey,TValue),g:{a:2,n:"get_Current",t:8,rt:$n[3].KeyValuePair$2(TKey,TValue),fg:"Current"},fn:"Current"},{a:4,n:"DictEntry",is:!0,t:4,rt:$n[0].Int32,sn:"DictEntry",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"KeyValuePair",is:!0,t:4,rt:$n[0].Int32,sn:"KeyValuePair",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"_sortedList",t:4,rt:$n[3].SortedList$2(TKey,TValue),sn:"_sortedList"},{a:1,n:"getEnumeratorRetType",t:4,rt:$n[0].Int32,sn:"getEnumeratorRetType",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"index",t:4,rt:$n[0].Int32,sn:"index",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"key",t:4,rt:TKey,sn:"key"},{a:1,n:"value",t:4,rt:TValue,sn:"value"},{a:1,n:"version",t:4,rt:$n[0].Int32,sn:"version",box:function($v){return H5.box($v,System.Int32)}}]}},$n);$m("System.Collections.Generic.SortedList$2.SortedListKeyEnumerator",function(TKey,TValue){return{td:$n[3].SortedList$2(TKey,TValue),att:1048835,a:1,m:[{a:4,n:".ctor",t:1,p:[$n[3].SortedList$2(TKey,TValue)],pi:[{n:"sortedList",pt:$n[3].SortedList$2(TKey,TValue),ps:0}],sn:"ctor"},{a:2,n:"Dispose",t:8,sn:"Dispose",rt:$n[0].Void},{a:2,n:"MoveNext",t:8,sn:"moveNext",rt:$n[0].Boolean,box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Current",t:16,rt:TKey,g:{a:2,n:"get_Current",t:8,rt:TKey,fg:"Current"},fn:"Current"},{a:1,n:"_sortedList",t:4,rt:$n[3].SortedList$2(TKey,TValue),sn:"_sortedList"},{a:1,n:"currentKey",t:4,rt:TKey,sn:"currentKey"},{a:1,n:"index",t:4,rt:$n[0].Int32,sn:"index",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"version",t:4,rt:$n[0].Int32,sn:"version",box:function($v){return H5.box($v,System.Int32)}}]}},$n);$m("System.Collections.Generic.SortedList$2.SortedListValueEnumerator",function(TKey,TValue){return{td:$n[3].SortedList$2(TKey,TValue),att:1048835,a:1,m:[{a:4,n:".ctor",t:1,p:[$n[3].SortedList$2(TKey,TValue)],pi:[{n:"sortedList",pt:$n[3].SortedList$2(TKey,TValue),ps:0}],sn:"ctor"},{a:2,n:"Dispose",t:8,sn:"Dispose",rt:$n[0].Void},{a:2,n:"MoveNext",t:8,sn:"moveNext",rt:$n[0].Boolean,box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Current",t:16,rt:TValue,g:{a:2,n:"get_Current",t:8,rt:TValue,fg:"Current"},fn:"Current"},{a:1,n:"_sortedList",t:4,rt:$n[3].SortedList$2(TKey,TValue),sn:"_sortedList"},{a:1,n:"currentValue",t:4,rt:TValue,sn:"currentValue"},{a:1,n:"index",t:4,rt:$n[0].Int32,sn:"index",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"version",t:4,rt:$n[0].Int32,sn:"version",box:function($v){return H5.box($v,System.Int32)}}]}},$n);$m("System.Collections.Generic.SortedList$2.KeyList",function(TKey,TValue){return{td:$n[3].SortedList$2(TKey,TValue),att:1048835,a:1,m:[{a:4,n:".ctor",t:1,p:[$n[3].SortedList$2(TKey,TValue)],pi:[{n:"dictionary",pt:$n[3].SortedList$2(TKey,TValue),ps:0}],sn:"ctor"},{a:2,n:"Add",t:8,pi:[{n:"key",pt:TKey,ps:0}],sn:"add",rt:$n[0].Void,p:[TKey]},{a:2,n:"Clear",t:8,sn:"clear",rt:$n[0].Void},{a:2,n:"Contains",t:8,pi:[{n:"key",pt:TKey,ps:0}],sn:"contains",rt:$n[0].Boolean,p:[TKey],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"CopyTo",t:8,pi:[{n:"array",pt:System.Array.type(TKey),ps:0},{n:"arrayIndex",pt:$n[0].Int32,ps:1}],sn:"copyTo",rt:$n[0].Void,p:[System.Array.type(TKey),$n[0].Int32]},{a:2,n:"GetEnumerator",t:8,sn:"GetEnumerator",rt:$n[3].IEnumerator$1(TKey)},{a:2,n:"IndexOf",t:8,pi:[{n:"key",pt:TKey,ps:0}],sn:"indexOf",rt:$n[0].Int32,p:[TKey],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"Insert",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0},{n:"value",pt:TKey,ps:1}],sn:"insert",rt:$n[0].Void,p:[$n[0].Int32,TKey]},{a:2,n:"Remove",t:8,pi:[{n:"key",pt:TKey,ps:0}],sn:"remove",rt:$n[0].Boolean,p:[TKey],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"RemoveAt",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0}],sn:"removeAt",rt:$n[0].Void,p:[$n[0].Int32]},{a:2,n:"Count",t:16,rt:$n[0].Int32,g:{a:2,n:"get_Count",t:8,rt:$n[0].Int32,fg:"Count",box:function($v){return H5.box($v,System.Int32)}},fn:"Count"},{a:2,n:"IsReadOnly",t:16,rt:$n[0].Boolean,g:{a:2,n:"get_IsReadOnly",t:8,rt:$n[0].Boolean,fg:"IsReadOnly",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},fn:"IsReadOnly"},{a:2,n:"Item",t:16,rt:TKey,p:[$n[0].Int32],i:!0,ipi:[{n:"index",pt:$n[0].Int32,ps:0}],g:{a:2,n:"get_Item",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0}],sn:"getItem",rt:TKey,p:[$n[0].Int32]},s:{a:2,n:"set_Item",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0},{n:"value",pt:TKey,ps:1}],sn:"setItem",rt:$n[0].Void,p:[$n[0].Int32,TKey]}},{a:1,n:"_dict",t:4,rt:$n[3].SortedList$2(TKey,TValue),sn:"_dict"}]}},$n);$m("System.Collections.Generic.SortedList$2.ValueList",function(TKey,TValue){return{td:$n[3].SortedList$2(TKey,TValue),att:1048835,a:1,m:[{a:4,n:".ctor",t:1,p:[$n[3].SortedList$2(TKey,TValue)],pi:[{n:"dictionary",pt:$n[3].SortedList$2(TKey,TValue),ps:0}],sn:"ctor"},{a:2,n:"Add",t:8,pi:[{n:"key",pt:TValue,ps:0}],sn:"add",rt:$n[0].Void,p:[TValue]},{a:2,n:"Clear",t:8,sn:"clear",rt:$n[0].Void},{a:2,n:"Contains",t:8,pi:[{n:"value",pt:TValue,ps:0}],sn:"contains",rt:$n[0].Boolean,p:[TValue],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"CopyTo",t:8,pi:[{n:"array",pt:System.Array.type(TValue),ps:0},{n:"arrayIndex",pt:$n[0].Int32,ps:1}],sn:"copyTo",rt:$n[0].Void,p:[System.Array.type(TValue),$n[0].Int32]},{a:2,n:"GetEnumerator",t:8,sn:"GetEnumerator",rt:$n[3].IEnumerator$1(TValue)},{a:2,n:"IndexOf",t:8,pi:[{n:"value",pt:TValue,ps:0}],sn:"indexOf",rt:$n[0].Int32,p:[TValue],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"Insert",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0},{n:"value",pt:TValue,ps:1}],sn:"insert",rt:$n[0].Void,p:[$n[0].Int32,TValue]},{a:2,n:"Remove",t:8,pi:[{n:"value",pt:TValue,ps:0}],sn:"remove",rt:$n[0].Boolean,p:[TValue],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"RemoveAt",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0}],sn:"removeAt",rt:$n[0].Void,p:[$n[0].Int32]},{a:2,n:"Count",t:16,rt:$n[0].Int32,g:{a:2,n:"get_Count",t:8,rt:$n[0].Int32,fg:"Count",box:function($v){return H5.box($v,System.Int32)}},fn:"Count"},{a:2,n:"IsReadOnly",t:16,rt:$n[0].Boolean,g:{a:2,n:"get_IsReadOnly",t:8,rt:$n[0].Boolean,fg:"IsReadOnly",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},fn:"IsReadOnly"},{a:2,n:"Item",t:16,rt:TValue,p:[$n[0].Int32],i:!0,ipi:[{n:"index",pt:$n[0].Int32,ps:0}],g:{a:2,n:"get_Item",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0}],sn:"getItem",rt:TValue,p:[$n[0].Int32]},s:{a:2,n:"set_Item",t:8,pi:[{n:"index",pt:$n[0].Int32,ps:0},{n:"value",pt:TValue,ps:1}],sn:"setItem",rt:$n[0].Void,p:[$n[0].Int32,TValue]}},{a:1,n:"_dict",t:4,rt:$n[3].SortedList$2(TKey,TValue),sn:"_dict"}]}},$n);$m("System.Collections.Generic.TreeRotation",function(){return{att:256,a:4,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:"LeftRightRotation",is:!0,t:4,rt:$n[3].TreeRotation,sn:"LeftRightRotation",box:function($v){return H5.box($v,System.Collections.Generic.TreeRotation,System.Enum.toStringFn(System.Collections.Generic.TreeRotation))}},{a:2,n:"LeftRotation",is:!0,t:4,rt:$n[3].TreeRotation,sn:"LeftRotation",box:function($v){return H5.box($v,System.Collections.Generic.TreeRotation,System.Enum.toStringFn(System.Collections.Generic.TreeRotation))}},{a:2,n:"RightLeftRotation",is:!0,t:4,rt:$n[3].TreeRotation,sn:"RightLeftRotation",box:function($v){return H5.box($v,System.Collections.Generic.TreeRotation,System.Enum.toStringFn(System.Collections.Generic.TreeRotation))}},{a:2,n:"RightRotation",is:!0,t:4,rt:$n[3].TreeRotation,sn:"RightRotation",box:function($v){return H5.box($v,System.Collections.Generic.TreeRotation,System.Enum.toStringFn(System.Collections.Generic.TreeRotation))}}]}},$n);$m("System.Collections.Generic.SortedSet$1",function(T){return{nested:[$n[3].SortedSet$1.TreeSubSet,$n[3].SortedSet$1.Node,$n[3].SortedSet$1.Enumerator,$n[3].SortedSet$1.ElementCount],att:1048577,a:2,m:[{a:2,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[3].IComparer$1(T)],pi:[{n:"comparer",pt:$n[3].IComparer$1(T),ps:0}],sn:"$ctor1"},{a:2,n:".ctor",t:1,p:[$n[3].IEnumerable$1(T)],pi:[{n:"collection",pt:$n[3].IEnumerable$1(T),ps:0}],sn:"$ctor2"},{a:2,n:".ctor",t:1,p:[$n[3].IEnumerable$1(T),$n[3].IComparer$1(T)],pi:[{n:"collection",pt:$n[3].IEnumerable$1(T),ps:0},{n:"comparer",pt:$n[3].IComparer$1(T),ps:1}],sn:"$ctor3"},{a:2,n:"Add",t:8,pi:[{n:"item",pt:T,ps:0}],sn:"add",rt:$n[0].Boolean,p:[T],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"AddAllElements",t:8,pi:[{n:"collection",pt:$n[3].IEnumerable$1(T),ps:0}],sn:"AddAllElements",rt:$n[0].Void,p:[$n[3].IEnumerable$1(T)]},{v:!0,a:4,n:"AddIfNotPresent",t:8,pi:[{n:"item",pt:T,ps:0}],sn:"AddIfNotPresent",rt:$n[0].Boolean,p:[T],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"AreComparersEqual",is:!0,t:8,pi:[{n:"set1",pt:$n[3].SortedSet$1(T),ps:0},{n:"set2",pt:$n[3].SortedSet$1(T),ps:1}],sn:"AreComparersEqual",rt:$n[0].Boolean,p:[$n[3].SortedSet$1(T),$n[3].SortedSet$1(T)],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{v:!0,a:4,n:"BreadthFirstTreeWalk",t:8,pi:[{n:"action",pt:Function,ps:0}],sn:"BreadthFirstTreeWalk",rt:$n[0].Boolean,p:[Function],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"CheckUniqueAndUnfoundElements",t:8,pi:[{n:"other",pt:$n[3].IEnumerable$1(T),ps:0},{n:"returnIfUnfound",pt:$n[0].Boolean,ps:1}],sn:"CheckUniqueAndUnfoundElements",rt:$n[3].SortedSet$1.ElementCount(T),p:[$n[3].IEnumerable$1(T),$n[0].Boolean]},{v:!0,a:2,n:"Clear",t:8,sn:"clear",rt:$n[0].Void},{a:1,n:"ConstructRootFromSortedArray",is:!0,t:8,pi:[{n:"arr",pt:System.Array.type(T),ps:0},{n:"startIndex",pt:$n[0].Int32,ps:1},{n:"endIndex",pt:$n[0].Int32,ps:2},{n:"redNode",pt:$n[3].SortedSet$1.Node(T),ps:3}],sn:"ConstructRootFromSortedArray",rt:$n[3].SortedSet$1.Node(T),p:[System.Array.type(T),$n[0].Int32,$n[0].Int32,$n[3].SortedSet$1.Node(T)]},{v:!0,a:2,n:"Contains",t:8,pi:[{n:"item",pt:T,ps:0}],sn:"contains",rt:$n[0].Boolean,p:[T],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"ContainsAllElements",t:8,pi:[{n:"collection",pt:$n[3].IEnumerable$1(T),ps:0}],sn:"ContainsAllElements",rt:$n[0].Boolean,p:[$n[3].IEnumerable$1(T)],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"CopyTo",t:8,pi:[{n:"array",pt:System.Array.type(T),ps:0}],sn:"CopyTo",rt:$n[0].Void,p:[System.Array.type(T)]},{a:2,n:"CopyTo",t:8,pi:[{n:"array",pt:System.Array.type(T),ps:0},{n:"index",pt:$n[0].Int32,ps:1}],sn:"copyTo",rt:$n[0].Void,p:[System.Array.type(T),$n[0].Int32]},{a:2,n:"CopyTo",t:8,pi:[{n:"array",pt:System.Array.type(T),ps:0},{n:"index",pt:$n[0].Int32,ps:1},{n:"count",pt:$n[0].Int32,ps:2}],sn:"CopyTo$1",rt:$n[0].Void,p:[System.Array.type(T),$n[0].Int32,$n[0].Int32]},{a:2,n:"CreateSetComparer",is:!0,t:8,sn:"CreateSetComparer",rt:$n[3].IEqualityComparer$1(System.Collections.Generic.SortedSet$1(T))},{a:2,n:"CreateSetComparer",is:!0,t:8,pi:[{n:"memberEqualityComparer",pt:$n[3].IEqualityComparer$1(T),ps:0}],sn:"CreateSetComparer$1",rt:$n[3].IEqualityComparer$1(System.Collections.Generic.SortedSet$1(T)),p:[$n[3].IEqualityComparer$1(T)]},{v:!0,a:4,n:"DoRemove",t:8,pi:[{n:"item",pt:T,ps:0}],sn:"DoRemove",rt:$n[0].Boolean,p:[T],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"ExceptWith",t:8,pi:[{n:"other",pt:$n[3].IEnumerable$1(T),ps:0}],sn:"exceptWith",rt:$n[0].Void,p:[$n[3].IEnumerable$1(T)]},{v:!0,a:4,n:"FindNode",t:8,pi:[{n:"item",pt:T,ps:0}],sn:"FindNode",rt:$n[3].SortedSet$1.Node(T),p:[T]},{a:4,n:"FindRange",t:8,pi:[{n:"from",pt:T,ps:0},{n:"to",pt:T,ps:1}],sn:"FindRange",rt:$n[3].SortedSet$1.Node(T),p:[T,T]},{a:4,n:"FindRange",t:8,pi:[{n:"from",pt:T,ps:0},{n:"to",pt:T,ps:1},{n:"lowerBoundActive",pt:$n[0].Boolean,ps:2},{n:"upperBoundActive",pt:$n[0].Boolean,ps:3}],sn:"FindRange$1",rt:$n[3].SortedSet$1.Node(T),p:[T,T,$n[0].Boolean,$n[0].Boolean]},{a:2,n:"GetEnumerator",t:8,sn:"GetEnumerator",rt:$n[3].SortedSet$1.Enumerator(T)},{a:1,n:"GetSibling",is:!0,t:8,pi:[{n:"node",pt:$n[3].SortedSet$1.Node(T),ps:0},{n:"parent",pt:$n[3].SortedSet$1.Node(T),ps:1}],sn:"GetSibling",rt:$n[3].SortedSet$1.Node(T),p:[$n[3].SortedSet$1.Node(T),$n[3].SortedSet$1.Node(T)]},{v:!0,a:2,n:"GetViewBetween",t:8,pi:[{n:"lowerValue",pt:T,ps:0},{n:"upperValue",pt:T,ps:1}],sn:"GetViewBetween",rt:$n[3].SortedSet$1(T),p:[T,T]},{a:4,n:"InOrderTreeWalk",t:8,pi:[{n:"action",pt:Function,ps:0}],sn:"InOrderTreeWalk",rt:$n[0].Boolean,p:[Function],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{v:!0,a:4,n:"InOrderTreeWalk",t:8,pi:[{n:"action",pt:Function,ps:0},{n:"reverse",pt:$n[0].Boolean,ps:1}],sn:"InOrderTreeWalk$1",rt:$n[0].Boolean,p:[Function,$n[0].Boolean],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"InsertionBalance",t:8,pi:[{n:"current",pt:$n[3].SortedSet$1.Node(T),ps:0},{n:"parent",ref:!0,pt:$n[3].SortedSet$1.Node(T),ps:1},{n:"grandParent",pt:$n[3].SortedSet$1.Node(T),ps:2},{n:"greatGrandParent",pt:$n[3].SortedSet$1.Node(T),ps:3}],sn:"InsertionBalance",rt:$n[0].Void,p:[$n[3].SortedSet$1.Node(T),$n[3].SortedSet$1.Node(T),$n[3].SortedSet$1.Node(T),$n[3].SortedSet$1.Node(T)]},{v:!0,a:4,n:"InternalIndexOf",t:8,pi:[{n:"item",pt:T,ps:0}],sn:"InternalIndexOf",rt:$n[0].Int32,p:[T],box:function($v){return H5.box($v,System.Int32)}},{v:!0,a:2,n:"IntersectWith",t:8,pi:[{n:"other",pt:$n[3].IEnumerable$1(T),ps:0}],sn:"intersectWith",rt:$n[0].Void,p:[$n[3].IEnumerable$1(T)]},{v:!0,a:4,n:"IntersectWithEnumerable",t:8,pi:[{n:"other",pt:$n[3].IEnumerable$1(T),ps:0}],sn:"IntersectWithEnumerable",rt:$n[0].Void,p:[$n[3].IEnumerable$1(T)]},{a:1,n:"Is2Node",is:!0,t:8,pi:[{n:"node",pt:$n[3].SortedSet$1.Node(T),ps:0}],sn:"Is2Node",rt:$n[0].Boolean,p:[$n[3].SortedSet$1.Node(T)],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"Is4Node",is:!0,t:8,pi:[{n:"node",pt:$n[3].SortedSet$1.Node(T),ps:0}],sn:"Is4Node",rt:$n[0].Boolean,p:[$n[3].SortedSet$1.Node(T)],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"IsBlack",is:!0,t:8,pi:[{n:"node",pt:$n[3].SortedSet$1.Node(T),ps:0}],sn:"IsBlack",rt:$n[0].Boolean,p:[$n[3].SortedSet$1.Node(T)],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"IsNullOrBlack",is:!0,t:8,pi:[{n:"node",pt:$n[3].SortedSet$1.Node(T),ps:0}],sn:"IsNullOrBlack",rt:$n[0].Boolean,p:[$n[3].SortedSet$1.Node(T)],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"IsProperSubsetOf",t:8,pi:[{n:"other",pt:$n[3].IEnumerable$1(T),ps:0}],sn:"isProperSubsetOf",rt:$n[0].Boolean,p:[$n[3].IEnumerable$1(T)],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"IsProperSupersetOf",t:8,pi:[{n:"other",pt:$n[3].IEnumerable$1(T),ps:0}],sn:"isProperSupersetOf",rt:$n[0].Boolean,p:[$n[3].IEnumerable$1(T)],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"IsRed",is:!0,t:8,pi:[{n:"node",pt:$n[3].SortedSet$1.Node(T),ps:0}],sn:"IsRed",rt:$n[0].Boolean,p:[$n[3].SortedSet$1.Node(T)],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"IsSubsetOf",t:8,pi:[{n:"other",pt:$n[3].IEnumerable$1(T),ps:0}],sn:"isSubsetOf",rt:$n[0].Boolean,p:[$n[3].IEnumerable$1(T)],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"IsSubsetOfSortedSetWithSameEC",t:8,pi:[{n:"asSorted",pt:$n[3].SortedSet$1(T),ps:0}],sn:"IsSubsetOfSortedSetWithSameEC",rt:$n[0].Boolean,p:[$n[3].SortedSet$1(T)],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"IsSupersetOf",t:8,pi:[{n:"other",pt:$n[3].IEnumerable$1(T),ps:0}],sn:"isSupersetOf",rt:$n[0].Boolean,p:[$n[3].IEnumerable$1(T)],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{v:!0,a:4,n:"IsWithinRange",t:8,pi:[{n:"item",pt:T,ps:0}],sn:"IsWithinRange",rt:$n[0].Boolean,p:[T],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"Merge2Nodes",is:!0,t:8,pi:[{n:"parent",pt:$n[3].SortedSet$1.Node(T),ps:0},{n:"child1",pt:$n[3].SortedSet$1.Node(T),ps:1},{n:"child2",pt:$n[3].SortedSet$1.Node(T),ps:2}],sn:"Merge2Nodes",rt:$n[0].Void,p:[$n[3].SortedSet$1.Node(T),$n[3].SortedSet$1.Node(T),$n[3].SortedSet$1.Node(T)]},{a:2,n:"Overlaps",t:8,pi:[{n:"other",pt:$n[3].IEnumerable$1(T),ps:0}],sn:"overlaps",rt:$n[0].Boolean,p:[$n[3].IEnumerable$1(T)],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Remove",t:8,pi:[{n:"item",pt:T,ps:0}],sn:"remove",rt:$n[0].Boolean,p:[T],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"RemoveAllElements",t:8,pi:[{n:"collection",pt:$n[3].IEnumerable$1(T),ps:0}],sn:"RemoveAllElements",rt:$n[0].Void,p:[$n[3].IEnumerable$1(T)]},{a:2,n:"RemoveWhere",t:8,pi:[{n:"match",pt:Function,ps:0}],sn:"RemoveWhere",rt:$n[0].Int32,p:[Function],box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"ReplaceChildOfNodeOrRoot",t:8,pi:[{n:"parent",pt:$n[3].SortedSet$1.Node(T),ps:0},{n:"child",pt:$n[3].SortedSet$1.Node(T),ps:1},{n:"newChild",pt:$n[3].SortedSet$1.Node(T),ps:2}],sn:"ReplaceChildOfNodeOrRoot",rt:$n[0].Void,p:[$n[3].SortedSet$1.Node(T),$n[3].SortedSet$1.Node(T),$n[3].SortedSet$1.Node(T)]},{a:1,n:"ReplaceNode",t:8,pi:[{n:"match",pt:$n[3].SortedSet$1.Node(T),ps:0},{n:"parentOfMatch",pt:$n[3].SortedSet$1.Node(T),ps:1},{n:"succesor",pt:$n[3].SortedSet$1.Node(T),ps:2},{n:"parentOfSuccesor",pt:$n[3].SortedSet$1.Node(T),ps:3}],sn:"ReplaceNode",rt:$n[0].Void,p:[$n[3].SortedSet$1.Node(T),$n[3].SortedSet$1.Node(T),$n[3].SortedSet$1.Node(T),$n[3].SortedSet$1.Node(T)]},{a:2,n:"Reverse",t:8,sn:"Reverse",rt:$n[3].IEnumerable$1(T)},{a:1,n:"RotateLeft",is:!0,t:8,pi:[{n:"node",pt:$n[3].SortedSet$1.Node(T),ps:0}],sn:"RotateLeft",rt:$n[3].SortedSet$1.Node(T),p:[$n[3].SortedSet$1.Node(T)]},{a:1,n:"RotateLeftRight",is:!0,t:8,pi:[{n:"node",pt:$n[3].SortedSet$1.Node(T),ps:0}],sn:"RotateLeftRight",rt:$n[3].SortedSet$1.Node(T),p:[$n[3].SortedSet$1.Node(T)]},{a:1,n:"RotateRight",is:!0,t:8,pi:[{n:"node",pt:$n[3].SortedSet$1.Node(T),ps:0}],sn:"RotateRight",rt:$n[3].SortedSet$1.Node(T),p:[$n[3].SortedSet$1.Node(T)]},{a:1,n:"RotateRightLeft",is:!0,t:8,pi:[{n:"node",pt:$n[3].SortedSet$1.Node(T),ps:0}],sn:"RotateRightLeft",rt:$n[3].SortedSet$1.Node(T),p:[$n[3].SortedSet$1.Node(T)]},{a:1,n:"RotationNeeded",is:!0,t:8,pi:[{n:"parent",pt:$n[3].SortedSet$1.Node(T),ps:0},{n:"current",pt:$n[3].SortedSet$1.Node(T),ps:1},{n:"sibling",pt:$n[3].SortedSet$1.Node(T),ps:2}],sn:"RotationNeeded",rt:$n[3].TreeRotation,p:[$n[3].SortedSet$1.Node(T),$n[3].SortedSet$1.Node(T),$n[3].SortedSet$1.Node(T)],box:function($v){return H5.box($v,System.Collections.Generic.TreeRotation,System.Enum.toStringFn(System.Collections.Generic.TreeRotation))}},{a:2,n:"SetEquals",t:8,pi:[{n:"other",pt:$n[3].IEnumerable$1(T),ps:0}],sn:"setEquals",rt:$n[0].Boolean,p:[$n[3].IEnumerable$1(T)],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:4,n:"SortedSetEquals",is:!0,t:8,pi:[{n:"set1",pt:$n[3].SortedSet$1(T),ps:0},{n:"set2",pt:$n[3].SortedSet$1(T),ps:1},{n:"comparer",pt:$n[3].IComparer$1(T),ps:2}],sn:"SortedSetEquals",rt:$n[0].Boolean,p:[$n[3].SortedSet$1(T),$n[3].SortedSet$1(T),$n[3].IComparer$1(T)],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"Split4Node",is:!0,t:8,pi:[{n:"node",pt:$n[3].SortedSet$1.Node(T),ps:0}],sn:"Split4Node",rt:$n[0].Void,p:[$n[3].SortedSet$1.Node(T)]},{a:2,n:"SymmetricExceptWith",t:8,pi:[{n:"other",pt:$n[3].IEnumerable$1(T),ps:0}],sn:"symmetricExceptWith",rt:$n[0].Void,p:[$n[3].IEnumerable$1(T)]},{a:4,n:"SymmetricExceptWithSameEC",t:8,pi:[{n:"other",pt:$n[3].ISet$1(T),ps:0}],sn:"SymmetricExceptWithSameEC$1",rt:$n[0].Void,p:[$n[3].ISet$1(T)]},{a:4,n:"SymmetricExceptWithSameEC",t:8,pi:[{n:"other",pt:System.Array.type(T),ps:0}],sn:"SymmetricExceptWithSameEC",rt:$n[0].Void,p:[System.Array.type(T)]},{a:4,n:"ToArray",t:8,sn:"ToArray",rt:System.Array.type(T)},{a:2,n:"TryGetValue",t:8,pi:[{n:"equalValue",pt:T,ps:0},{n:"actualValue",out:!0,pt:T,ps:1}],sn:"TryGetValue",rt:$n[0].Boolean,p:[T,T],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"UnionWith",t:8,pi:[{n:"other",pt:$n[3].IEnumerable$1(T),ps:0}],sn:"unionWith",rt:$n[0].Void,p:[$n[3].IEnumerable$1(T)]},{a:4,n:"UpdateVersion",t:8,sn:"UpdateVersion",rt:$n[0].Void},{v:!0,a:4,n:"VersionCheck",t:8,sn:"VersionCheck",rt:$n[0].Void},{a:1,n:"log2",is:!0,t:8,pi:[{n:"value",pt:$n[0].Int32,ps:0}],sn:"log2",rt:$n[0].Int32,p:[$n[0].Int32],box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"Comparer",t:16,rt:$n[3].IComparer$1(T),g:{a:2,n:"get_Comparer",t:8,rt:$n[3].IComparer$1(T),fg:"Comparer"},fn:"Comparer"},{a:2,n:"Count",t:16,rt:$n[0].Int32,g:{a:2,n:"get_Count",t:8,rt:$n[0].Int32,fg:"Count",box:function($v){return H5.box($v,System.Int32)}},fn:"Count"},{a:2,n:"Max",t:16,rt:T,g:{a:2,n:"get_Max",t:8,rt:T,fg:"Max"},fn:"Max"},{a:2,n:"Min",t:16,rt:T,g:{a:2,n:"get_Min",t:8,rt:T,fg:"Min"},fn:"Min"},{a:1,n:"ComparerName",is:!0,t:4,rt:$n[0].String,sn:"ComparerName"},{a:1,n:"CountName",is:!0,t:4,rt:$n[0].String,sn:"CountName"},{a:1,n:"EnumStartName",is:!0,t:4,rt:$n[0].String,sn:"EnumStartName"},{a:1,n:"EnumVersionName",is:!0,t:4,rt:$n[0].String,sn:"EnumVersionName"},{a:1,n:"ItemsName",is:!0,t:4,rt:$n[0].String,sn:"ItemsName"},{a:1,n:"NodeValueName",is:!0,t:4,rt:$n[0].String,sn:"NodeValueName"},{a:1,n:"ReverseName",is:!0,t:4,rt:$n[0].String,sn:"ReverseName"},{a:4,n:"StackAllocThreshold",is:!0,t:4,rt:$n[0].Int32,sn:"StackAllocThreshold",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"TreeName",is:!0,t:4,rt:$n[0].String,sn:"TreeName"},{a:1,n:"VersionName",is:!0,t:4,rt:$n[0].String,sn:"VersionName"},{a:1,n:"comparer",t:4,rt:$n[3].IComparer$1(T),sn:"comparer"},{a:1,n:"count",t:4,rt:$n[0].Int32,sn:"count",box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"lBoundActiveName",is:!0,t:4,rt:$n[0].String,sn:"lBoundActiveName"},{a:1,n:"maxName",is:!0,t:4,rt:$n[0].String,sn:"maxName"},{a:1,n:"minName",is:!0,t:4,rt:$n[0].String,sn:"minName"},{a:1,n:"root",t:4,rt:$n[3].SortedSet$1.Node(T),sn:"root"},{a:1,n:"uBoundActiveName",is:!0,t:4,rt:$n[0].String,sn:"uBoundActiveName"},{a:1,n:"version",t:4,rt:$n[0].Int32,sn:"version",box:function($v){return H5.box($v,System.Int32)}}]}},$n);$m("System.Collections.Generic.SortedSet$1.TreeSubSet",function(T){return{td:$n[3].SortedSet$1(T),att:1048837,a:4,m:[{a:1,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[3].SortedSet$1(T),T,T,$n[0].Boolean,$n[0].Boolean],pi:[{n:"Underlying",pt:$n[3].SortedSet$1(T),ps:0},{n:"Min",pt:T,ps:1},{n:"Max",pt:T,ps:2},{n:"lowerBoundActive",pt:$n[0].Boolean,ps:3},{n:"upperBoundActive",pt:$n[0].Boolean,ps:4}],sn:"$ctor1"},{ov:!0,a:4,n:"AddIfNotPresent",t:8,pi:[{n:"item",pt:T,ps:0}],sn:"AddIfNotPresent",rt:$n[0].Boolean,p:[T],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ov:!0,a:4,n:"BreadthFirstTreeWalk",t:8,pi:[{n:"action",pt:Function,ps:0}],sn:"BreadthFirstTreeWalk",rt:$n[0].Boolean,p:[Function],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ov:!0,a:2,n:"Clear",t:8,sn:"clear",rt:$n[0].Void},{ov:!0,a:2,n:"Contains",t:8,pi:[{n:"item",pt:T,ps:0}],sn:"contains",rt:$n[0].Boolean,p:[T],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ov:!0,a:4,n:"DoRemove",t:8,pi:[{n:"item",pt:T,ps:0}],sn:"DoRemove",rt:$n[0].Boolean,p:[T],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ov:!0,a:4,n:"FindNode",t:8,pi:[{n:"item",pt:T,ps:0}],sn:"FindNode",rt:$n[3].SortedSet$1.Node(T),p:[T]},{ov:!0,a:2,n:"GetViewBetween",t:8,pi:[{n:"lowerValue",pt:T,ps:0},{n:"upperValue",pt:T,ps:1}],sn:"GetViewBetween",rt:$n[3].SortedSet$1(T),p:[T,T]},{ov:!0,a:4,n:"InOrderTreeWalk",t:8,pi:[{n:"action",pt:Function,ps:0},{n:"reverse",pt:$n[0].Boolean,ps:1}],sn:"InOrderTreeWalk$1",rt:$n[0].Boolean,p:[Function,$n[0].Boolean],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ov:!0,a:4,n:"InternalIndexOf",t:8,pi:[{n:"item",pt:T,ps:0}],sn:"InternalIndexOf",rt:$n[0].Int32,p:[T],box:function($v){return H5.box($v,System.Int32)}},{ov:!0,a:4,n:"IntersectWithEnumerable",t:8,pi:[{n:"other",pt:$n[3].IEnumerable$1(T),ps:0}],sn:"IntersectWithEnumerable",rt:$n[0].Void,p:[$n[3].IEnumerable$1(T)]},{ov:!0,a:4,n:"IsWithinRange",t:8,pi:[{n:"item",pt:T,ps:0}],sn:"IsWithinRange",rt:$n[0].Boolean,p:[T],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ov:!0,a:4,n:"VersionCheck",t:8,sn:"VersionCheck",rt:$n[0].Void},{a:1,n:"VersionCheckImpl",t:8,sn:"VersionCheckImpl",rt:$n[0].Void},{a:1,n:"lBoundActive",t:4,rt:$n[0].Boolean,sn:"lBoundActive",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"max",t:4,rt:T,sn:"max"},{a:1,n:"min",t:4,rt:T,sn:"min"},{a:1,n:"uBoundActive",t:4,rt:$n[0].Boolean,sn:"uBoundActive",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"underlying",t:4,rt:$n[3].SortedSet$1(T),sn:"underlying"}]}},$n);$m("System.Collections.Generic.SortedSet$1.Node",function(T){return{td:$n[3].SortedSet$1(T),att:1048581,a:4,m:[{a:2,n:".ctor",t:1,p:[T],pi:[{n:"item",pt:T,ps:0}],sn:"ctor"},{a:2,n:".ctor",t:1,p:[T,$n[0].Boolean],pi:[{n:"item",pt:T,ps:0},{n:"isRed",pt:$n[0].Boolean,ps:1}],sn:"$ctor1"},{a:2,n:"IsRed",t:4,rt:$n[0].Boolean,sn:"IsRed",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Item",t:4,rt:T,sn:"Item"},{a:2,n:"Left",t:4,rt:$n[3].SortedSet$1.Node(T),sn:"Left"},{a:2,n:"Right",t:4,rt:$n[3].SortedSet$1.Node(T),sn:"Right"}]}},$n);$m("System.Collections.Generic.SortedSet$1.Enumerator",function(T){return{td:$n[3].SortedSet$1(T),att:1048842,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:4,n:".ctor",t:1,p:[$n[3].SortedSet$1(T)],pi:[{n:"set",pt:$n[3].SortedSet$1(T),ps:0}],sn:"$ctor1"},{a:4,n:".ctor",t:1,p:[$n[3].SortedSet$1(T),$n[0].Boolean],pi:[{n:"set",pt:$n[3].SortedSet$1(T),ps:0},{n:"reverse",pt:$n[0].Boolean,ps:1}],sn:"$ctor2"},{a:2,n:"Dispose",t:8,sn:"Dispose",rt:$n[0].Void},{a:1,n:"Intialize",t:8,sn:"Intialize",rt:$n[0].Void},{a:2,n:"MoveNext",t:8,sn:"moveNext",rt:$n[0].Boolean,box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:4,n:"Reset",t:8,sn:"Reset",rt:$n[0].Void},{a:2,n:"Current",t:16,rt:T,g:{a:2,n:"get_Current",t:8,rt:T,fg:"Current"},fn:"Current"},{a:4,n:"NotStartedOrEnded",t:16,rt:$n[0].Boolean,g:{a:4,n:"get_NotStartedOrEnded",t:8,rt:$n[0].Boolean,fg:"NotStartedOrEnded",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},fn:"NotStartedOrEnded"},{a:1,n:"current",t:4,rt:$n[3].SortedSet$1.Node(T),sn:"current"},{a:1,n:"dummyNode",is:!0,t:4,rt:$n[3].SortedSet$1.Node(T),sn:"dummyNode"},{a:1,n:"reverse",t:4,rt:$n[0].Boolean,sn:"reverse",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,n:"stack",t:4,rt:$n[3].Stack$1(System.Collections.Generic.SortedSet$1.Node(T)),sn:"stack"},{a:1,n:"tree",t:4,rt:$n[3].SortedSet$1(T),sn:"tree"},{a:1,n:"version",t:4,rt:$n[0].Int32,sn:"version",box:function($v){return H5.box($v,System.Int32)}}]}},$n);$m("System.Collections.Generic.SortedSet$1.ElementCount",function(T){return{td:$n[3].SortedSet$1(T),att:1048845,a:4,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:4,n:"unfoundCount",t:4,rt:$n[0].Int32,sn:"unfoundCount",box:function($v){return H5.box($v,System.Int32)}},{a:4,n:"uniqueCount",t:4,rt:$n[0].Int32,sn:"uniqueCount",box:function($v){return H5.box($v,System.Int32)}}]}},$n);$m("System.Collections.Generic.SortedSetEqualityComparer$1",function(T){return{att:1048576,a:4,m:[{a:2,n:".ctor",t:1,sn:"ctor"},{a:2,n:".ctor",t:1,p:[$n[3].IComparer$1(T)],pi:[{n:"comparer",pt:$n[3].IComparer$1(T),ps:0}],sn:"$ctor1"},{a:2,n:".ctor",t:1,p:[$n[3].IEqualityComparer$1(T)],pi:[{n:"memberEqualityComparer",pt:$n[3].IEqualityComparer$1(T),ps:0}],sn:"$ctor3"},{a:2,n:".ctor",t:1,p:[$n[3].IComparer$1(T),$n[3].IEqualityComparer$1(T)],pi:[{n:"comparer",pt:$n[3].IComparer$1(T),ps:0},{n:"memberEqualityComparer",pt:$n[3].IEqualityComparer$1(T),ps:1}],sn:"$ctor2"},{ov:!0,a:2,n:"Equals",t:8,pi:[{n:"obj",pt:$n[0].Object,ps:0}],sn:"equals",rt:$n[0].Boolean,p:[$n[0].Object],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:2,n:"Equals",t:8,pi:[{n:"x",pt:$n[3].SortedSet$1(T),ps:0},{n:"y",pt:$n[3].SortedSet$1(T),ps:1}],sn:"equals2",rt:$n[0].Boolean,p:[$n[3].SortedSet$1(T),$n[3].SortedSet$1(T)],box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{ov:!0,a:2,n:"GetHashCode",t:8,sn:"getHashCode",rt:$n[0].Int32,box:function($v){return H5.box($v,System.Int32)}},{a:2,n:"GetHashCode",t:8,pi:[{n:"obj",pt:$n[3].SortedSet$1(T),ps:0}],sn:"getHashCode2",rt:$n[0].Int32,p:[$n[3].SortedSet$1(T)],box:function($v){return H5.box($v,System.Int32)}},{a:1,n:"comparer",t:4,rt:$n[3].IComparer$1(T),sn:"comparer"},{a:1,n:"e_comparer",t:4,rt:$n[3].IEqualityComparer$1(T),sn:"e_comparer"}]}},$n);$m("System.Diagnostics.CodeAnalysis.ExperimentalAttribute",function(){return{att:1048833,a:2,m:[{a:2,n:".ctor",t:1,p:[$n[0].String],pi:[{n:"diagnosticId",pt:$n[0].String,ps:0}],sn:"ctor"},{a:2,n:"DiagnosticId",t:16,rt:$n[0].String,g:{a:2,n:"get_DiagnosticId",t:8,rt:$n[0].String,fg:"DiagnosticId"},fn:"DiagnosticId"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"DiagnosticId"}],ni:!0}},$n);$m("H5.Ref$1",function(T){return{att:1048577,a:2,m:[{a:2,n:".ctor",t:1,p:[Function,Function],pi:[{n:"getter",pt:Function,ps:0},{n:"setter",pt:Function,ps:1}],sn:"ctor"},{a:2,n:"CreateIn",is:!0,t:8,pi:[{n:"value",pt:T,ps:0}],sn:"CreateIn",rt:$n[7].Ref$1(T),p:[T]},{ov:!0,a:2,n:"ToString",t:8,sn:"toString",rt:$n[0].String},{ov:!0,a:2,n:"ValueOf",t:8,sn:"valueOf",rt:$n[0].Object},{a:2,n:"op_Implicit",is:!0,t:8,pi:[{n:"reference",pt:$n[7].Ref$1(T),ps:0}],sn:"op_Implicit",rt:T,p:[$n[7].Ref$1(T)]},{a:2,n:"Value",t:16,rt:T,g:{a:2,n:"get_Value",t:8,rt:T,fg:"Value"},s:{a:2,n:"set_Value",t:8,p:[T],rt:$n[0].Void,fs:"Value"},fn:"Value"},{a:1,n:"v",t:16,rt:T,g:{a:1,n:"get_v",t:8,rt:T,fg:"v"},s:{a:1,n:"set_v",t:8,p:[T],rt:$n[0].Void,fs:"v"},fn:"v"},{a:1,n:"getter",t:4,rt:Function,sn:"getter"},{a:1,n:"setter",t:4,rt:Function,sn:"setter"}]}},$n);$m("H5.Utils.SystemAssemblyVersion",function(){return{att:1048576,a:4,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:"Version",is:!0,t:8,sn:"Version",rt:$n[0].Void}]}},$n);H5.assemblyVersion("Dashboard.Web","1.0.0.0");H5.assembly("Dashboard.Web",function($asm,globals){"use strict";H5.define("Dashboard.Api.ApiClient",{statics:{fields:{_clinicalBaseUrl:null,_schedulingBaseUrl:null,_icd10BaseUrl:null,_clinicalToken:null,_schedulingToken:null,_icd10Token:null},ctors:{init:function(){this._clinicalBaseUrl="http://localhost:5080";this._schedulingBaseUrl="http://localhost:5001";this._icd10BaseUrl="http://localhost:5090";this._clinicalToken="";this._schedulingToken="";this._icd10Token=""}},methods:{Configure:function(clinicalUrl,schedulingUrl){Dashboard.Api.ApiClient._clinicalBaseUrl=clinicalUrl;Dashboard.Api.ApiClient._schedulingBaseUrl=schedulingUrl},ConfigureIcd10:function(icd10Url){Dashboard.Api.ApiClient._icd10BaseUrl=icd10Url},SetTokens:function(clinicalToken,schedulingToken){Dashboard.Api.ApiClient._clinicalToken=clinicalToken;Dashboard.Api.ApiClient._schedulingToken=schedulingToken},SetIcd10Token:function(icd10Token){Dashboard.Api.ApiClient._icd10Token=icd10Token},GetPatientsAsync:function(){var $tcs=new System.Threading.Tasks.TaskCompletionSource;return(async()=>{var response=await H5.toPromise(Dashboard.Api.ApiClient.FetchClinicalAsync((Dashboard.Api.ApiClient._clinicalBaseUrl||"")+"/fhir/Patient"));return Dashboard.Api.ApiClient.ParseJson(System.Array.type(Object),response)})().then(function($r){$tcs.setResult($r)},function($e){$tcs.setException(System.Exception.create($e))}),$tcs.task},GetPatientAsync:function(id){var $tcs=new System.Threading.Tasks.TaskCompletionSource;return(async()=>{var response=await H5.toPromise(Dashboard.Api.ApiClient.FetchClinicalAsync((Dashboard.Api.ApiClient._clinicalBaseUrl||"")+"/fhir/Patient/"+(id||"")));return Dashboard.Api.ApiClient.ParseJson(Object,response)})().then(function($r){$tcs.setResult($r)},function($e){$tcs.setException(System.Exception.create($e))}),$tcs.task},SearchPatientsAsync:function(query){var $tcs=new System.Threading.Tasks.TaskCompletionSource;return(async()=>{var response=await H5.toPromise(Dashboard.Api.ApiClient.FetchClinicalAsync((Dashboard.Api.ApiClient._clinicalBaseUrl||"")+"/fhir/Patient/_search?q="+(Dashboard.Api.ApiClient.EncodeUri(query)||"")));return Dashboard.Api.ApiClient.ParseJson(System.Array.type(Object),response)})().then(function($r){$tcs.setResult($r)},function($e){$tcs.setException(System.Exception.create($e))}),$tcs.task},GetEncountersAsync:function(patientId){var $tcs=new System.Threading.Tasks.TaskCompletionSource;return(async()=>{var response=await H5.toPromise(Dashboard.Api.ApiClient.FetchClinicalAsync((Dashboard.Api.ApiClient._clinicalBaseUrl||"")+"/fhir/Patient/"+(patientId||"")+"/Encounter"));return Dashboard.Api.ApiClient.ParseJson(System.Array.type(Object),response)})().then(function($r){$tcs.setResult($r)},function($e){$tcs.setException(System.Exception.create($e))}),$tcs.task},GetConditionsAsync:function(patientId){var $tcs=new System.Threading.Tasks.TaskCompletionSource;return(async()=>{var response=await H5.toPromise(Dashboard.Api.ApiClient.FetchClinicalAsync((Dashboard.Api.ApiClient._clinicalBaseUrl||"")+"/fhir/Patient/"+(patientId||"")+"/Condition"));return Dashboard.Api.ApiClient.ParseJson(System.Array.type(Object),response)})().then(function($r){$tcs.setResult($r)},function($e){$tcs.setException(System.Exception.create($e))}),$tcs.task},GetMedicationsAsync:function(patientId){var $tcs=new System.Threading.Tasks.TaskCompletionSource;return(async()=>{var response=await H5.toPromise(Dashboard.Api.ApiClient.FetchClinicalAsync((Dashboard.Api.ApiClient._clinicalBaseUrl||"")+"/fhir/Patient/"+(patientId||"")+"/MedicationRequest"));return Dashboard.Api.ApiClient.ParseJson(System.Array.type(Object),response)})().then(function($r){$tcs.setResult($r)},function($e){$tcs.setException(System.Exception.create($e))}),$tcs.task},CreatePatientAsync:function(patient){var $tcs=new System.Threading.Tasks.TaskCompletionSource;return(async()=>{var response=await H5.toPromise(Dashboard.Api.ApiClient.PostClinicalAsync((Dashboard.Api.ApiClient._clinicalBaseUrl||"")+"/fhir/Patient/",patient));return Dashboard.Api.ApiClient.ParseJson(Object,response)})().then(function($r){$tcs.setResult($r)},function($e){$tcs.setException(System.Exception.create($e))}),$tcs.task},UpdatePatientAsync:function(id,patient){var $tcs=new System.Threading.Tasks.TaskCompletionSource;return(async()=>{var response=await H5.toPromise(Dashboard.Api.ApiClient.PutClinicalAsync((Dashboard.Api.ApiClient._clinicalBaseUrl||"")+"/fhir/Patient/"+(id||""),patient));return Dashboard.Api.ApiClient.ParseJson(Object,response)})().then(function($r){$tcs.setResult($r)},function($e){$tcs.setException(System.Exception.create($e))}),$tcs.task},GetPractitionersAsync:function(){var $tcs=new System.Threading.Tasks.TaskCompletionSource;return(async()=>{var response=await H5.toPromise(Dashboard.Api.ApiClient.FetchSchedulingAsync((Dashboard.Api.ApiClient._schedulingBaseUrl||"")+"/Practitioner"));return Dashboard.Api.ApiClient.ParseJson(System.Array.type(Object),response)})().then(function($r){$tcs.setResult($r)},function($e){$tcs.setException(System.Exception.create($e))}),$tcs.task},GetPractitionerAsync:function(id){var $tcs=new System.Threading.Tasks.TaskCompletionSource;return(async()=>{var response=await H5.toPromise(Dashboard.Api.ApiClient.FetchSchedulingAsync((Dashboard.Api.ApiClient._schedulingBaseUrl||"")+"/Practitioner/"+(id||"")));return Dashboard.Api.ApiClient.ParseJson(Object,response)})().then(function($r){$tcs.setResult($r)},function($e){$tcs.setException(System.Exception.create($e))}),$tcs.task},SearchPractitionersAsync:function(specialty){var $tcs=new System.Threading.Tasks.TaskCompletionSource;return(async()=>{var response=await H5.toPromise(Dashboard.Api.ApiClient.FetchSchedulingAsync((Dashboard.Api.ApiClient._schedulingBaseUrl||"")+"/Practitioner/_search?specialty="+(Dashboard.Api.ApiClient.EncodeUri(specialty)||"")));return Dashboard.Api.ApiClient.ParseJson(System.Array.type(Object),response)})().then(function($r){$tcs.setResult($r)},function($e){$tcs.setException(System.Exception.create($e))}),$tcs.task},GetAppointmentsAsync:function(){var $tcs=new System.Threading.Tasks.TaskCompletionSource;return(async()=>{var response=await H5.toPromise(Dashboard.Api.ApiClient.FetchSchedulingAsync((Dashboard.Api.ApiClient._schedulingBaseUrl||"")+"/Appointment"));return Dashboard.Api.ApiClient.ParseJson(System.Array.type(Object),response)})().then(function($r){$tcs.setResult($r)},function($e){$tcs.setException(System.Exception.create($e))}),$tcs.task},GetAppointmentAsync:function(id){var $tcs=new System.Threading.Tasks.TaskCompletionSource;return(async()=>{var response=await H5.toPromise(Dashboard.Api.ApiClient.FetchSchedulingAsync((Dashboard.Api.ApiClient._schedulingBaseUrl||"")+"/Appointment/"+(id||"")));return Dashboard.Api.ApiClient.ParseJson(Object,response)})().then(function($r){$tcs.setResult($r)},function($e){$tcs.setException(System.Exception.create($e))}),$tcs.task},UpdateAppointmentAsync:function(id,appointment){var $tcs=new System.Threading.Tasks.TaskCompletionSource;return(async()=>{var response=await H5.toPromise(Dashboard.Api.ApiClient.PutSchedulingAsync((Dashboard.Api.ApiClient._schedulingBaseUrl||"")+"/Appointment/"+(id||""),appointment));return Dashboard.Api.ApiClient.ParseJson(Object,response)})().then(function($r){$tcs.setResult($r)},function($e){$tcs.setException(System.Exception.create($e))}),$tcs.task},GetPatientAppointmentsAsync:function(patientId){var $tcs=new System.Threading.Tasks.TaskCompletionSource;return(async()=>{var response=await H5.toPromise(Dashboard.Api.ApiClient.FetchSchedulingAsync((Dashboard.Api.ApiClient._schedulingBaseUrl||"")+"/Patient/"+(patientId||"")+"/Appointment"));return Dashboard.Api.ApiClient.ParseJson(System.Array.type(Object),response)})().then(function($r){$tcs.setResult($r)},function($e){$tcs.setException(System.Exception.create($e))}),$tcs.task},GetPractitionerAppointmentsAsync:function(practitionerId){var $tcs=new System.Threading.Tasks.TaskCompletionSource;return(async()=>{var response=await H5.toPromise(Dashboard.Api.ApiClient.FetchSchedulingAsync((Dashboard.Api.ApiClient._schedulingBaseUrl||"")+"/Practitioner/"+(practitionerId||"")+"/Appointment"));return Dashboard.Api.ApiClient.ParseJson(System.Array.type(Object),response)})().then(function($r){$tcs.setResult($r)},function($e){$tcs.setException(System.Exception.create($e))}),$tcs.task},GetIcd10ChaptersAsync:function(){var $tcs=new System.Threading.Tasks.TaskCompletionSource;return(async()=>{var response=await H5.toPromise(Dashboard.Api.ApiClient.FetchIcd10Async((Dashboard.Api.ApiClient._icd10BaseUrl||"")+"/api/icd10/chapters"));return Dashboard.Api.ApiClient.ParseJson(System.Array.type(Object),response)})().then(function($r){$tcs.setResult($r)},function($e){$tcs.setException(System.Exception.create($e))}),$tcs.task},GetIcd10BlocksAsync:function(chapterId){var $tcs=new System.Threading.Tasks.TaskCompletionSource;return(async()=>{var response=await H5.toPromise(Dashboard.Api.ApiClient.FetchIcd10Async((Dashboard.Api.ApiClient._icd10BaseUrl||"")+"/api/icd10/chapters/"+(chapterId||"")+"/blocks"));return Dashboard.Api.ApiClient.ParseJson(System.Array.type(Object),response)})().then(function($r){$tcs.setResult($r)},function($e){$tcs.setException(System.Exception.create($e))}),$tcs.task},GetIcd10CategoriesAsync:function(blockId){var $tcs=new System.Threading.Tasks.TaskCompletionSource;return(async()=>{var response=await H5.toPromise(Dashboard.Api.ApiClient.FetchIcd10Async((Dashboard.Api.ApiClient._icd10BaseUrl||"")+"/api/icd10/blocks/"+(blockId||"")+"/categories"));return Dashboard.Api.ApiClient.ParseJson(System.Array.type(Object),response)})().then(function($r){$tcs.setResult($r)},function($e){$tcs.setException(System.Exception.create($e))}),$tcs.task},GetIcd10CodesAsync:function(categoryId){var $tcs=new System.Threading.Tasks.TaskCompletionSource;return(async()=>{var response=await H5.toPromise(Dashboard.Api.ApiClient.FetchIcd10Async((Dashboard.Api.ApiClient._icd10BaseUrl||"")+"/api/icd10/categories/"+(categoryId||"")+"/codes"));return Dashboard.Api.ApiClient.ParseJson(System.Array.type(Object),response)})().then(function($r){$tcs.setResult($r)},function($e){$tcs.setException(System.Exception.create($e))}),$tcs.task},GetIcd10CodeAsync:function(code){var $tcs=new System.Threading.Tasks.TaskCompletionSource;return(async()=>{var response=await H5.toPromise(Dashboard.Api.ApiClient.FetchIcd10Async((Dashboard.Api.ApiClient._icd10BaseUrl||"")+"/api/icd10/codes/"+(Dashboard.Api.ApiClient.EncodeUri(code)||"")));return Dashboard.Api.ApiClient.ParseJson(Object,response)})().then(function($r){$tcs.setResult($r)},function($e){$tcs.setException(System.Exception.create($e))}),$tcs.task},SearchIcd10CodesAsync:function(query,limit){var $tcs=new System.Threading.Tasks.TaskCompletionSource;return(async()=>{limit===void 0&&(limit=20);var response=await H5.toPromise(Dashboard.Api.ApiClient.FetchIcd10Async((Dashboard.Api.ApiClient._icd10BaseUrl||"")+"/api/icd10/codes?q="+(Dashboard.Api.ApiClient.EncodeUri(query)||"")+"&limit="+limit));return Dashboard.Api.ApiClient.ParseJson(System.Array.type(Object),response)})().then(function($r){$tcs.setResult($r)},function($e){$tcs.setException(System.Exception.create($e))}),$tcs.task},SearchAchiCodesAsync:function(query,limit){var $tcs=new System.Threading.Tasks.TaskCompletionSource;return(async()=>{limit===void 0&&(limit=20);var response=await H5.toPromise(Dashboard.Api.ApiClient.FetchIcd10Async((Dashboard.Api.ApiClient._icd10BaseUrl||"")+"/api/achi/codes?q="+(Dashboard.Api.ApiClient.EncodeUri(query)||"")+"&limit="+limit));return Dashboard.Api.ApiClient.ParseJson(System.Array.type(Object),response)})().then(function($r){$tcs.setResult($r)},function($e){$tcs.setException(System.Exception.create($e))}),$tcs.task},SemanticSearchAsync:function(query,limit,includeAchi){var $tcs=new System.Threading.Tasks.TaskCompletionSource;return(async()=>{var $t;limit===void 0&&(limit=10);includeAchi===void 0&&(includeAchi=!1);var request=($t=new Dashboard.Models.SemanticSearchRequest,$t.Query=query,$t.Limit=limit,$t.IncludeAchi=includeAchi,$t),response=await H5.toPromise(Dashboard.Api.ApiClient.PostIcd10Async((Dashboard.Api.ApiClient._icd10BaseUrl||"")+"/api/search",request)),parsed=Dashboard.Api.ApiClient.ParseJson(Object,response);return parsed.Results||System.Array.init(0,null,Object)})().then(function($r){$tcs.setResult($r)},function($e){$tcs.setException(System.Exception.create($e))}),$tcs.task},FetchIcd10Async:function(url){var $tcs=new System.Threading.Tasks.TaskCompletionSource;return(async()=>{var response=await H5.toPromise(fetch(url,{method:"GET",headers:{Accept:"application/json",Authorization:"Bearer "+(Dashboard.Api.ApiClient._icd10Token||"")}}));if(!response.Ok)throw new System.Exception("HTTP "+response.Status);return await H5.toPromise(response.Text())})().then(function($r){$tcs.setResult($r)},function($e){$tcs.setException(System.Exception.create($e))}),$tcs.task},PostIcd10Async:function(url,data){var $tcs=new System.Threading.Tasks.TaskCompletionSource;return(async()=>{var response=await H5.toPromise(fetch(url,{method:"POST",headers:{Accept:"application/json",ContentType:"application/json",Authorization:"Bearer "+(Dashboard.Api.ApiClient._icd10Token||"")},body:JSON.stringify(H5.unbox(data))}));if(!response.Ok)throw new System.Exception("HTTP "+response.Status);return await H5.toPromise(response.Text())})().then(function($r){$tcs.setResult($r)},function($e){$tcs.setException(System.Exception.create($e))}),$tcs.task},FetchClinicalAsync:function(url){var $tcs=new System.Threading.Tasks.TaskCompletionSource;return(async()=>{var response=await H5.toPromise(fetch(url,{method:"GET",headers:{Accept:"application/json",Authorization:"Bearer "+(Dashboard.Api.ApiClient._clinicalToken||"")}}));if(!response.Ok)throw new System.Exception("HTTP "+response.Status);return await H5.toPromise(response.Text())})().then(function($r){$tcs.setResult($r)},function($e){$tcs.setException(System.Exception.create($e))}),$tcs.task},FetchSchedulingAsync:function(url){var $tcs=new System.Threading.Tasks.TaskCompletionSource;return(async()=>{var response=await H5.toPromise(fetch(url,{method:"GET",headers:{Accept:"application/json",Authorization:"Bearer "+(Dashboard.Api.ApiClient._schedulingToken||"")}}));if(!response.Ok)throw new System.Exception("HTTP "+response.Status);return await H5.toPromise(response.Text())})().then(function($r){$tcs.setResult($r)},function($e){$tcs.setException(System.Exception.create($e))}),$tcs.task},PostClinicalAsync:function(url,data){var $tcs=new System.Threading.Tasks.TaskCompletionSource;return(async()=>{var response=await H5.toPromise(fetch(url,{method:"POST",headers:{Accept:"application/json",ContentType:"application/json",Authorization:"Bearer "+(Dashboard.Api.ApiClient._clinicalToken||"")},body:JSON.stringify(H5.unbox(data))}));if(!response.Ok)throw new System.Exception("HTTP "+response.Status);return await H5.toPromise(response.Text())})().then(function($r){$tcs.setResult($r)},function($e){$tcs.setException(System.Exception.create($e))}),$tcs.task},PutClinicalAsync:function(url,data){var $tcs=new System.Threading.Tasks.TaskCompletionSource;return(async()=>{var response=await H5.toPromise(fetch(url,{method:"PUT",headers:{Accept:"application/json",ContentType:"application/json",Authorization:"Bearer "+(Dashboard.Api.ApiClient._clinicalToken||"")},body:JSON.stringify(H5.unbox(data))}));if(!response.Ok)throw new System.Exception("HTTP "+response.Status);return await H5.toPromise(response.Text())})().then(function($r){$tcs.setResult($r)},function($e){$tcs.setException(System.Exception.create($e))}),$tcs.task},PutSchedulingAsync:function(url,data){var $tcs=new System.Threading.Tasks.TaskCompletionSource;return(async()=>{var response=await H5.toPromise(fetch(url,{method:"PUT",headers:{Accept:"application/json",ContentType:"application/json",Authorization:"Bearer "+(Dashboard.Api.ApiClient._schedulingToken||"")},body:JSON.stringify(H5.unbox(data))}));if(!response.Ok)throw new System.Exception("HTTP "+response.Status);return await H5.toPromise(response.Text())})().then(function($r){$tcs.setResult($r)},function($e){$tcs.setException(System.Exception.create($e))}),$tcs.task},ParseJson:function(T,json){return JSON.parse(json)},EncodeUri:function(value){return encodeURIComponent(value)}}}});H5.define("Dashboard.App",{statics:{methods:{Render:function(){var $t,stateResult=Dashboard.React.Hooks.UseState(Dashboard.AppState,($t=new Dashboard.AppState,$t.ActiveView="dashboard",$t.SidebarCollapsed=!1,$t.SearchQuery="",$t.NotificationCount=3,$t.EditingPatientId=null,$t.EditingAppointmentId=null,$t)),state=stateResult.State,setState=stateResult.SetState;return Dashboard.React.Elements.Div("app",void 0,void 0,void 0,System.Array.init([Dashboard.Components.Sidebar.Render(state.ActiveView,function(view){var $t1,newState=($t1=new Dashboard.AppState,$t1.ActiveView=view,$t1.SidebarCollapsed=state.SidebarCollapsed,$t1.SearchQuery=state.SearchQuery,$t1.NotificationCount=state.NotificationCount,$t1.EditingPatientId=null,$t1.EditingAppointmentId=null,$t1);setState(newState)},state.SidebarCollapsed,function(){var $t1,newState=($t1=new Dashboard.AppState,$t1.ActiveView=state.ActiveView,$t1.SidebarCollapsed=!state.SidebarCollapsed,$t1.SearchQuery=state.SearchQuery,$t1.NotificationCount=state.NotificationCount,$t1.EditingPatientId=state.EditingPatientId,$t1.EditingAppointmentId=state.EditingAppointmentId,$t1);setState(newState)}),Dashboard.React.Elements.Div("main-wrapper",void 0,void 0,void 0,System.Array.init([Dashboard.Components.Header.Render(Dashboard.App.GetPageTitle(state.ActiveView),state.SearchQuery,function(query){var $t1,newState=($t1=new Dashboard.AppState,$t1.ActiveView=state.ActiveView,$t1.SidebarCollapsed=state.SidebarCollapsed,$t1.SearchQuery=query,$t1.NotificationCount=state.NotificationCount,$t1.EditingPatientId=state.EditingPatientId,$t1.EditingAppointmentId=state.EditingAppointmentId,$t1);setState(newState)},state.NotificationCount),Dashboard.React.Elements.Main("main-content",System.Array.init([Dashboard.App.RenderPage(state,setState)],Object))],Object))],Object))},GetPageTitle:function(view){return H5.referenceEquals(view,"dashboard")?"Dashboard":H5.referenceEquals(view,"patients")?"Patients":H5.referenceEquals(view,"clinical-coding")?"Clinical Coding":H5.referenceEquals(view,"encounters")?"Encounters":H5.referenceEquals(view,"conditions")?"Conditions":H5.referenceEquals(view,"medications")?"Medications":H5.referenceEquals(view,"practitioners")?"Practitioners":H5.referenceEquals(view,"appointments")?"Appointments":H5.referenceEquals(view,"calendar")?"Schedule":H5.referenceEquals(view,"settings")?"Settings":"Healthcare"},RenderPage:function(state,setState){var view=state.ActiveView;return H5.referenceEquals(view,"patients")&&state.EditingPatientId!=null?Dashboard.Pages.EditPatientPage.Render(state.EditingPatientId,function(){var $t,newState=($t=new Dashboard.AppState,$t.ActiveView="patients",$t.SidebarCollapsed=state.SidebarCollapsed,$t.SearchQuery=state.SearchQuery,$t.NotificationCount=state.NotificationCount,$t.EditingPatientId=null,$t.EditingAppointmentId=null,$t);setState(newState)}):(H5.referenceEquals(view,"appointments")||H5.referenceEquals(view,"calendar"))&&state.EditingAppointmentId!=null?Dashboard.Pages.EditAppointmentPage.Render(state.EditingAppointmentId,function(){var $t,newState=($t=new Dashboard.AppState,$t.ActiveView=view,$t.SidebarCollapsed=state.SidebarCollapsed,$t.SearchQuery=state.SearchQuery,$t.NotificationCount=state.NotificationCount,$t.EditingPatientId=null,$t.EditingAppointmentId=null,$t);setState(newState)}):H5.referenceEquals(view,"dashboard")?Dashboard.Pages.DashboardPage.Render():H5.referenceEquals(view,"clinical-coding")?Dashboard.Pages.ClinicalCodingPage.Render():H5.referenceEquals(view,"patients")?Dashboard.Pages.PatientsPage.Render(function(patientId){var $t,newState=($t=new Dashboard.AppState,$t.ActiveView="patients",$t.SidebarCollapsed=state.SidebarCollapsed,$t.SearchQuery=state.SearchQuery,$t.NotificationCount=state.NotificationCount,$t.EditingPatientId=patientId,$t.EditingAppointmentId=null,$t);setState(newState)}):H5.referenceEquals(view,"practitioners")?Dashboard.Pages.PractitionersPage.Render():H5.referenceEquals(view,"appointments")?Dashboard.Pages.AppointmentsPage.Render(function(appointmentId){var $t,newState=($t=new Dashboard.AppState,$t.ActiveView="appointments",$t.SidebarCollapsed=state.SidebarCollapsed,$t.SearchQuery=state.SearchQuery,$t.NotificationCount=state.NotificationCount,$t.EditingPatientId=null,$t.EditingAppointmentId=appointmentId,$t);setState(newState)}):H5.referenceEquals(view,"calendar")?Dashboard.Pages.CalendarPage.Render(function(appointmentId){var $t,newState=($t=new Dashboard.AppState,$t.ActiveView="calendar",$t.SidebarCollapsed=state.SidebarCollapsed,$t.SearchQuery=state.SearchQuery,$t.NotificationCount=state.NotificationCount,$t.EditingPatientId=null,$t.EditingAppointmentId=appointmentId,$t);setState(newState)}):H5.referenceEquals(view,"encounters")?Dashboard.App.RenderPlaceholderPage("Encounters","Manage patient encounters and visits"):H5.referenceEquals(view,"conditions")?Dashboard.App.RenderPlaceholderPage("Conditions","View and manage patient conditions"):H5.referenceEquals(view,"medications")?Dashboard.App.RenderPlaceholderPage("Medications","Manage medication requests"):H5.referenceEquals(view,"settings")?Dashboard.App.RenderPlaceholderPage("Settings","Configure application settings"):Dashboard.App.RenderPlaceholderPage("Page Not Found","The requested page does not exist")},RenderPlaceholderPage:function(title,description){return Dashboard.React.Elements.Div("page",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Div("page-header",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.H(2,"page-title",System.Array.init([Dashboard.React.Elements.Text(title)],Object)),Dashboard.React.Elements.P("page-description",void 0,System.Array.init([Dashboard.React.Elements.Text(description)],Object))],Object)),Dashboard.React.Elements.Div("card",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Div("empty-state",void 0,void 0,void 0,System.Array.init([Dashboard.Components.Icons.Clipboard(),Dashboard.React.Elements.H(4,"empty-state-title",System.Array.init([Dashboard.React.Elements.Text("Coming Soon")],Object)),Dashboard.React.Elements.P("empty-state-description",void 0,System.Array.init([Dashboard.React.Elements.Text("This page is under development.")],Object))],Object))],Object))],Object))}}}});H5.define("Dashboard.AppState",{fields:{ActiveView:null,SidebarCollapsed:!1,SearchQuery:null,NotificationCount:0,EditingPatientId:null,EditingAppointmentId:null}});H5.define("Dashboard.Components.Column",{fields:{Key:null,Header:null,ClassName:null}});H5.define("Dashboard.Components.DataTable",{statics:{methods:{Render:function(T,columns,data,getKey,renderCell,onRowClick){return onRowClick===void 0&&(onRowClick=null),Dashboard.React.Elements.Div("table-container",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Table("table",System.Array.init([Dashboard.React.Elements.THead(System.Array.init([Dashboard.React.Elements.Tr(void 0,void 0,System.Linq.Enumerable.from(columns,Dashboard.Components.Column).select(function(col){return Dashboard.React.Elements.Th(col.ClassName,System.Array.init([Dashboard.React.Elements.Text(col.Header)],Object))}).ToArray(Object))],Object)),Dashboard.React.Elements.TBody(System.Linq.Enumerable.from(data,T).select(function(row){return Dashboard.React.Elements.Tr(H5.staticEquals(onRowClick,null)?null:"cursor-pointer",H5.staticEquals(onRowClick,null)?null:function(){onRowClick(row)},System.Linq.Enumerable.from(columns,Dashboard.Components.Column).select(function(col){return Dashboard.React.Elements.Td(col.ClassName,System.Array.init([renderCell(row,col.Key)],Object))}).ToArray(Object))}).ToArray(Object))],Object))],Object))},RenderEmpty:function(message){return message===void 0&&(message="No data available"),Dashboard.React.Elements.Div("empty-state",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Div("empty-state-icon",void 0,void 0,void 0,System.Array.init([Dashboard.Components.Icons.Clipboard()],Object)),Dashboard.React.Elements.H(4,"empty-state-title",System.Array.init([Dashboard.React.Elements.Text("No Results")],Object)),Dashboard.React.Elements.P("empty-state-description",void 0,System.Array.init([Dashboard.React.Elements.Text(message)],Object))],Object))},RenderLoading:function(rows,columns){return rows===void 0&&(rows=5),columns===void 0&&(columns=4),Dashboard.React.Elements.Div("table-container",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Table("table",System.Array.init([Dashboard.React.Elements.THead(System.Array.init([Dashboard.React.Elements.Tr(void 0,void 0,System.Linq.Enumerable.range(0,columns).select(function(i){return Dashboard.React.Elements.Th(void 0,System.Array.init([Dashboard.React.Elements.Div("skeleton",void 0,{width:"80px",height:"16px"},void 0)],Object))}).ToArray(Object))],Object)),Dashboard.React.Elements.TBody(System.Linq.Enumerable.range(0,rows).select(function(i){return Dashboard.React.Elements.Tr(void 0,void 0,System.Linq.Enumerable.range(0,columns).select(function(j){return Dashboard.React.Elements.Td(void 0,System.Array.init([Dashboard.React.Elements.Div("skeleton",void 0,{width:"100%",height:"16px"},void 0)],Object))}).ToArray(Object))}).ToArray(Object))],Object))],Object))}}}});H5.define("Dashboard.Components.Header",{statics:{methods:{Render:function(title,searchQuery,onSearchChange,notificationCount){return searchQuery===void 0&&(searchQuery=null),onSearchChange===void 0&&(onSearchChange=null),notificationCount===void 0&&(notificationCount=0),Dashboard.React.Elements.Header("header",System.Array.init([Dashboard.React.Elements.Div("header-left",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.H(1,"header-title",System.Array.init([Dashboard.React.Elements.Text(title)],Object))],Object)),Dashboard.React.Elements.Div("header-right",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Div("header-search",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Span("header-search-icon",void 0,void 0,System.Array.init([Dashboard.Components.Icons.Search()],Object)),Dashboard.React.Elements.Input("input","text",searchQuery,"Search patients, appointments...",onSearchChange,void 0,!1)],Object)),Dashboard.React.Elements.Div("header-actions",void 0,void 0,void 0,System.Array.init([Dashboard.Components.Header.RenderNotificationButton(notificationCount),Dashboard.Components.Header.RenderUserAvatar()],Object))],Object))],Object))},RenderNotificationButton:function(count){var children;return children=count>0?System.Array.init([Dashboard.Components.Icons.Bell(),Dashboard.React.Elements.Span("header-action-badge",void 0,void 0)],Object):System.Array.init([Dashboard.Components.Icons.Bell()],Object),Dashboard.React.Elements.Button("header-action-btn",function(){},!1,"button",children)},RenderUserAvatar:function(){return Dashboard.React.Elements.Div("avatar avatar-md",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Text("JD")],Object))}}}});H5.define("Dashboard.Components.Icons",{statics:{methods:{Home:function(){return Dashboard.React.Elements.Svg("icon",20,20,"0 0 24 24","none",[Dashboard.React.Elements.Path("M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z M9 22V12h6v10",void 0,"currentColor",2)])},Users:function(){return Dashboard.React.Elements.Svg("icon",20,20,"0 0 24 24","none",[Dashboard.React.Elements.Path("M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2 M9 7a4 4 0 1 0 0-8 4 4 0 0 0 0 8z M23 21v-2a4 4 0 0 0-3-3.87 M16 3.13a4 4 0 0 1 0 7.75",void 0,"currentColor",2)])},UserDoctor:function(){return Dashboard.React.Elements.Svg("icon",20,20,"0 0 24 24","none",[Dashboard.React.Elements.Path("M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2 M12 7a4 4 0 1 0 0-8 4 4 0 0 0 0 8z M12 14v7 M9 18h6",void 0,"currentColor",2)])},Calendar:function(){return Dashboard.React.Elements.Svg("icon",20,20,"0 0 24 24","none",[Dashboard.React.Elements.Path("M19 4H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2z M16 2v4 M8 2v4 M3 10h18",void 0,"currentColor",2)])},Clipboard:function(){return Dashboard.React.Elements.Svg("icon",20,20,"0 0 24 24","none",[Dashboard.React.Elements.Path("M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2 M9 2h6a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1H9a1 1 0 0 1-1-1V3a1 1 0 0 1 1-1z",void 0,"currentColor",2)])},Heart:function(){return Dashboard.React.Elements.Svg("icon",20,20,"0 0 24 24","none",[Dashboard.React.Elements.Path("M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z",void 0,"currentColor",2)])},Pill:function(){return Dashboard.React.Elements.Svg("icon",20,20,"0 0 24 24","none",[Dashboard.React.Elements.Path("M10.5 20.5L3.5 13.5a4.95 4.95 0 1 1 7-7l7 7a4.95 4.95 0 1 1-7 7z M8.5 8.5l7 7",void 0,"currentColor",2)])},Activity:function(){return Dashboard.React.Elements.Svg("icon",20,20,"0 0 24 24","none",[Dashboard.React.Elements.Path("M22 12h-4l-3 9L9 3l-3 9H2",void 0,"currentColor",2)])},Search:function(){return Dashboard.React.Elements.Svg("icon",20,20,"0 0 24 24","none",[Dashboard.React.Elements.Path("M11 19a8 8 0 1 0 0-16 8 8 0 0 0 0 16z M21 21l-4.35-4.35",void 0,"currentColor",2)])},Bell:function(){return Dashboard.React.Elements.Svg("icon",20,20,"0 0 24 24","none",[Dashboard.React.Elements.Path("M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9 M13.73 21a2 2 0 0 1-3.46 0",void 0,"currentColor",2)])},Settings:function(){return Dashboard.React.Elements.Svg("icon",20,20,"0 0 24 24","none",[Dashboard.React.Elements.Path("M12 15a3 3 0 1 0 0-6 3 3 0 0 0 0 6z M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z",void 0,"currentColor",2)])},ChevronLeft:function(){return Dashboard.React.Elements.Svg("icon",20,20,"0 0 24 24","none",[Dashboard.React.Elements.Path("M15 18l-6-6 6-6",void 0,"currentColor",2)])},ChevronRight:function(){return Dashboard.React.Elements.Svg("icon",20,20,"0 0 24 24","none",[Dashboard.React.Elements.Path("M9 18l6-6-6-6",void 0,"currentColor",2)])},Plus:function(){return Dashboard.React.Elements.Svg("icon",20,20,"0 0 24 24","none",[Dashboard.React.Elements.Path("M12 5v14 M5 12h14",void 0,"currentColor",2)])},Edit:function(){return Dashboard.React.Elements.Svg("icon",20,20,"0 0 24 24","none",[Dashboard.React.Elements.Path("M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7 M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z",void 0,"currentColor",2)])},Trash:function(){return Dashboard.React.Elements.Svg("icon",20,20,"0 0 24 24","none",[Dashboard.React.Elements.Path("M3 6h18 M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2",void 0,"currentColor",2)])},Eye:function(){return Dashboard.React.Elements.Svg("icon",20,20,"0 0 24 24","none",[Dashboard.React.Elements.Path("M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z M12 15a3 3 0 1 0 0-6 3 3 0 0 0 0 6z",void 0,"currentColor",2)])},Refresh:function(){return Dashboard.React.Elements.Svg("icon",20,20,"0 0 24 24","none",[Dashboard.React.Elements.Path("M23 4v6h-6 M1 20v-6h6 M3.51 9a9 9 0 0 1 14.85-3.36L23 10 M1 14l4.64 4.36A9 9 0 0 0 20.49 15",void 0,"currentColor",2)])},TrendUp:function(){return Dashboard.React.Elements.Svg("icon",16,16,"0 0 24 24","none",[Dashboard.React.Elements.Path("M23 6l-9.5 9.5-5-5L1 18",void 0,"currentColor",2)])},TrendDown:function(){return Dashboard.React.Elements.Svg("icon",16,16,"0 0 24 24","none",[Dashboard.React.Elements.Path("M23 18l-9.5-9.5-5 5L1 6",void 0,"currentColor",2)])},Menu:function(){return Dashboard.React.Elements.Svg("icon",20,20,"0 0 24 24","none",[Dashboard.React.Elements.Path("M3 12h18M3 6h18M3 18h18",void 0,"currentColor",2)])},X:function(){return Dashboard.React.Elements.Svg("icon",20,20,"0 0 24 24","none",[Dashboard.React.Elements.Path("M18 6L6 18M6 6l12 12",void 0,"currentColor",2)])},Code:function(){return Dashboard.React.Elements.Svg("icon",20,20,"0 0 24 24","none",[Dashboard.React.Elements.Path("M4 19.5A2.5 2.5 0 0 1 6.5 17H20 M4 4.5A2.5 2.5 0 0 1 6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15z M8 7h8 M8 11h8 M8 15h5",void 0,"currentColor",2)])},FileText:function(){return Dashboard.React.Elements.Svg("icon",20,20,"0 0 24 24","none",[Dashboard.React.Elements.Path("M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z M14 2v6h6 M16 13H8 M16 17H8 M10 9H8",void 0,"currentColor",2)])},Sparkles:function(){return Dashboard.React.Elements.Svg("icon",20,20,"0 0 24 24","none",[Dashboard.React.Elements.Path("M12 3l1.5 4.5L18 9l-4.5 1.5L12 15l-1.5-4.5L6 9l4.5-1.5L12 3z M19 13l1 3 3 1-3 1-1 3-1-3-3-1 3-1 1-3z M5 17l.5 1.5L7 19l-1.5.5L5 21l-.5-1.5L3 19l1.5-.5L5 17z",void 0,"currentColor",2)])},Check:function(){return Dashboard.React.Elements.Svg("icon",20,20,"0 0 24 24","none",[Dashboard.React.Elements.Path("M20 6L9 17l-5-5",void 0,"currentColor",2)])},Copy:function(){return Dashboard.React.Elements.Svg("icon",20,20,"0 0 24 24","none",[Dashboard.React.Elements.Path("M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2 M9 2h6a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1H9a1 1 0 0 1-1-1V3a1 1 0 0 1 1-1z",void 0,"currentColor",2)])}}}});H5.define("Dashboard.Components.MetricCard",{statics:{methods:{Render:function(props){var $t,trendElement;return trendElement=props.TrendValue!=null?Dashboard.React.Elements.Div("metric-trend "+(Dashboard.Components.MetricCard.TrendClass(props.Trend)||""),void 0,void 0,void 0,System.Array.init([Dashboard.Components.MetricCard.TrendIcon(props.Trend),Dashboard.React.Elements.Text(props.TrendValue)],Object)):Dashboard.React.Elements.Text(""),Dashboard.React.Elements.Div("metric-card",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Div("metric-icon "+(($t=props.IconColor,$t!=null?$t:"blue")||""),void 0,void 0,void 0,System.Array.init([props.Icon()],Object)),Dashboard.React.Elements.Div("metric-value",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Text(props.Value)],Object)),Dashboard.React.Elements.Div("metric-label",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Text(props.Label)],Object)),trendElement],Object))},TrendClass:function(trend){return trend===Dashboard.Components.TrendDirection.Up?"up":trend===Dashboard.Components.TrendDirection.Down?"down":"neutral"},TrendIcon:function(trend){return trend===Dashboard.Components.TrendDirection.Up?Dashboard.Components.Icons.TrendUp():trend===Dashboard.Components.TrendDirection.Down?Dashboard.Components.Icons.TrendDown():Dashboard.React.Elements.Text("")}}}});H5.define("Dashboard.Components.MetricCardProps",{fields:{Label:null,Value:null,Icon:null,IconColor:null,TrendValue:null,Trend:0}});H5.define("Dashboard.Components.NavItem",{fields:{Id:null,Label:null,Icon:null,Badge:null}});H5.define("Dashboard.Components.NavSection",{fields:{Title:null,Items:null}});H5.define("Dashboard.Components.Sidebar",{statics:{methods:{Render:function(activeView,onNavigate,collapsed,onToggle){var sections=Dashboard.Components.Sidebar.GetNavSections();return Dashboard.React.Elements.Aside("sidebar "+((collapsed?"collapsed":"")||""),System.Array.init([Dashboard.Components.Sidebar.RenderHeader(collapsed),Dashboard.React.Elements.Nav("sidebar-nav",System.Linq.Enumerable.from(sections,Dashboard.Components.NavSection).select(function(section){return Dashboard.Components.Sidebar.RenderSection(section,activeView,onNavigate)}).ToArray(Object)),Dashboard.React.Elements.Button("sidebar-toggle",onToggle,!1,"button",System.Array.init([collapsed?Dashboard.Components.Icons.ChevronRight():Dashboard.Components.Icons.ChevronLeft()],Object)),Dashboard.Components.Sidebar.RenderFooter(collapsed)],Object))},GetNavSections:function(){var $t,$t1;return System.Array.init([($t=new Dashboard.Components.NavSection,$t.Title="Overview",$t.Items=System.Array.init([($t1=new Dashboard.Components.NavItem,$t1.Id="dashboard",$t1.Label="Dashboard",$t1.Icon=Dashboard.Components.Icons.Home,$t1)],Dashboard.Components.NavItem),$t),($t=new Dashboard.Components.NavSection,$t.Title="Clinical",$t.Items=System.Array.init([($t1=new Dashboard.Components.NavItem,$t1.Id="patients",$t1.Label="Patients",$t1.Icon=Dashboard.Components.Icons.Users,$t1),($t1=new Dashboard.Components.NavItem,$t1.Id="clinical-coding",$t1.Label="Clinical Coding",$t1.Icon=Dashboard.Components.Icons.Code,$t1),($t1=new Dashboard.Components.NavItem,$t1.Id="encounters",$t1.Label="Encounters",$t1.Icon=Dashboard.Components.Icons.Clipboard,$t1),($t1=new Dashboard.Components.NavItem,$t1.Id="conditions",$t1.Label="Conditions",$t1.Icon=Dashboard.Components.Icons.Heart,$t1),($t1=new Dashboard.Components.NavItem,$t1.Id="medications",$t1.Label="Medications",$t1.Icon=Dashboard.Components.Icons.Pill,$t1)],Dashboard.Components.NavItem),$t),($t=new Dashboard.Components.NavSection,$t.Title="Scheduling",$t.Items=System.Array.init([($t1=new Dashboard.Components.NavItem,$t1.Id="practitioners",$t1.Label="Practitioners",$t1.Icon=Dashboard.Components.Icons.UserDoctor,$t1),($t1=new Dashboard.Components.NavItem,$t1.Id="appointments",$t1.Label="Appointments",$t1.Icon=Dashboard.Components.Icons.Clipboard,$t1.Badge=3,$t1),($t1=new Dashboard.Components.NavItem,$t1.Id="calendar",$t1.Label="Schedule",$t1.Icon=Dashboard.Components.Icons.Calendar,$t1)],Dashboard.Components.NavItem),$t),($t=new Dashboard.Components.NavSection,$t.Title="System",$t.Items=System.Array.init([($t1=new Dashboard.Components.NavItem,$t1.Id="settings",$t1.Label="Settings",$t1.Icon=Dashboard.Components.Icons.Settings,$t1)],Dashboard.Components.NavItem),$t)],Dashboard.Components.NavSection)},RenderHeader:function(collapsed){return Dashboard.React.Elements.Div("sidebar-header",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.A("#","sidebar-logo",void 0,void 0,System.Array.init([Dashboard.React.Elements.Div("sidebar-logo-icon",void 0,void 0,void 0,System.Array.init([Dashboard.Components.Icons.Activity()],Object)),Dashboard.React.Elements.Span("sidebar-logo-text",void 0,void 0,System.Array.init([Dashboard.React.Elements.Text("HealthCare")],Object))],Object))],Object))},RenderSection:function(section,activeView,onNavigate){var items=System.Linq.Enumerable.from(section.Items,Dashboard.Components.NavItem).select(function(item){return Dashboard.Components.Sidebar.RenderNavItem(item,activeView,onNavigate)}).ToArray(Object),allChildren=System.Array.init(items.length+1|0,null,Object),i;for(allChildren[System.Array.index(0,allChildren)]=Dashboard.React.Elements.Div("nav-section-title",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Text(section.Title)],Object)),i=0;i{var $t,appointments;try{appointments=await H5.toPromise(Dashboard.Api.ApiClient.GetAppointmentsAsync());setState(($t=new Dashboard.Pages.AppointmentsState,$t.Appointments=appointments,$t.Loading=!1,$t.Error=null,$t.StatusFilter=null,$t))}catch(ex){ex=System.Exception.create(ex);setState(($t=new Dashboard.Pages.AppointmentsState,$t.Appointments=System.Array.init(0,null,Object),$t.Loading=!1,$t.Error=ex.Message,$t.StatusFilter=null,$t))}})()},FilterByStatus:function(status,currentState,setState){var $t;setState(($t=new Dashboard.Pages.AppointmentsState,$t.Appointments=currentState.Appointments,$t.Loading=currentState.Loading,$t.Error=currentState.Error,$t.StatusFilter=status,$t))},RenderTab:function(label,status,currentFilter,onSelect){var isActive=H5.referenceEquals(status,currentFilter);return Dashboard.React.Elements.Button("tab "+((isActive?"active":"")||""),function(){onSelect(status)},!1,"button",System.Array.init([Dashboard.React.Elements.Text(label)],Object))},RenderError:function(message){return Dashboard.React.Elements.Div("card",void 0,{borderLeft:"4px solid var(--error)"},void 0,System.Array.init([Dashboard.React.Elements.Div("flex items-center gap-3 p-4",void 0,void 0,void 0,System.Array.init([Dashboard.Components.Icons.X(),Dashboard.React.Elements.Text("Error loading appointments: "+(message||""))],Object))],Object))},RenderEmpty:function(){return Dashboard.React.Elements.Div("card",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Div("empty-state",void 0,void 0,void 0,System.Array.init([Dashboard.Components.Icons.Calendar(),Dashboard.React.Elements.H(4,"empty-state-title",System.Array.init([Dashboard.React.Elements.Text("No Appointments")],Object)),Dashboard.React.Elements.P("empty-state-description",void 0,System.Array.init([Dashboard.React.Elements.Text("No appointments scheduled. Create a new appointment to get started.")],Object)),Dashboard.React.Elements.Button("btn btn-primary mt-4",void 0,!1,"button",System.Array.init([Dashboard.Components.Icons.Plus(),Dashboard.React.Elements.Text("New Appointment")],Object))],Object))],Object))},RenderLoadingList:function(){return Dashboard.React.Elements.Div("data-list",void 0,void 0,void 0,System.Linq.Enumerable.range(0,5).select(function(i){return Dashboard.React.Elements.Div("card",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Div("flex items-center gap-4",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Div("skeleton",void 0,{width:"60px",height:"60px",borderRadius:"var(--radius-lg)"},void 0),Dashboard.React.Elements.Div("flex-1",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Div("skeleton",void 0,{width:"200px",height:"20px"},void 0),Dashboard.React.Elements.Div("skeleton mt-2",void 0,{width:"150px",height:"16px"},void 0)],Object)),Dashboard.React.Elements.Div("skeleton",void 0,{width:"100px",height:"32px"},void 0)],Object))],Object))}).ToArray(Object))},RenderAppointmentList:function(appointments,statusFilter,onEditAppointment){var filtered=statusFilter==null?appointments:System.Linq.Enumerable.from(appointments,Object).where(function(a){return H5.referenceEquals(a.Status,statusFilter)}).ToArray(Object);return Dashboard.React.Elements.Div("data-list",void 0,void 0,void 0,System.Linq.Enumerable.from(filtered,Object).select(function(a){return Dashboard.Pages.AppointmentsPage.RenderAppointmentCard(a,onEditAppointment)}).ToArray(Object))},RenderAppointmentCard:function(appointment,onEditAppointment){var $t,descElement;return descElement=appointment.Description!=null?Dashboard.React.Elements.P("text-sm mt-2",void 0,System.Array.init([Dashboard.React.Elements.Text(appointment.Description)],Object)):Dashboard.React.Elements.Text(""),Dashboard.React.Elements.Div("card-glass mb-4",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Div("flex items-start gap-4",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Div("metric-icon blue",void 0,{width:"60px",height:"60px"},void 0,System.Array.init([Dashboard.React.Elements.Div("text-center",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Div("text-lg font-bold",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Text(Dashboard.Pages.AppointmentsPage.FormatTime(appointment.StartTime))],Object)),Dashboard.React.Elements.Div("text-xs",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Text(appointment.MinutesDuration+"min")],Object))],Object))],Object)),Dashboard.React.Elements.Div("flex-1",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Div("flex items-center gap-2",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.H(4,"font-semibold",System.Array.init([Dashboard.React.Elements.Text(($t=appointment.ServiceType,$t!=null?$t:"Appointment"))],Object)),Dashboard.Pages.AppointmentsPage.RenderStatusBadge(appointment.Status),Dashboard.Pages.AppointmentsPage.RenderPriorityBadge(appointment.Priority)],Object)),Dashboard.React.Elements.Div("text-sm text-gray-600 mt-1",void 0,void 0,void 0,System.Array.init([Dashboard.Components.Icons.Users(),Dashboard.React.Elements.Text(" Patient: "+(Dashboard.Pages.AppointmentsPage.FormatReference(appointment.PatientReference)||""))],Object)),Dashboard.React.Elements.Div("text-sm text-gray-600",void 0,void 0,void 0,System.Array.init([Dashboard.Components.Icons.UserDoctor(),Dashboard.React.Elements.Text(" Provider: "+(Dashboard.Pages.AppointmentsPage.FormatReference(appointment.PractitionerReference)||""))],Object)),descElement],Object)),Dashboard.React.Elements.Div("flex flex-col gap-2",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Button("btn btn-primary btn-sm",void 0,!1,"button",System.Array.init([Dashboard.React.Elements.Text("Check In")],Object)),Dashboard.React.Elements.Button("btn btn-secondary btn-sm",function(){onEditAppointment(appointment.Id)},!1,"button",System.Array.init([Dashboard.Components.Icons.Edit()],Object))],Object))],Object))],Object))},RenderStatusBadge:function(status){var badgeClass;return badgeClass=H5.referenceEquals(status,"booked")?"badge-primary":H5.referenceEquals(status,"arrived")?"badge-teal":H5.referenceEquals(status,"fulfilled")?"badge-success":H5.referenceEquals(status,"cancelled")?"badge-error":H5.referenceEquals(status,"noshow")?"badge-warning":"badge-gray",Dashboard.React.Elements.Span("badge "+(badgeClass||""),void 0,void 0,System.Array.init([Dashboard.React.Elements.Text(status)],Object))},RenderPriorityBadge:function(priority){if(H5.referenceEquals(priority,"routine"))return Dashboard.React.Elements.Text("");var badgeClass;return badgeClass=H5.referenceEquals(priority,"urgent")?"badge-warning":H5.referenceEquals(priority,"asap")?"badge-error":H5.referenceEquals(priority,"stat")?"badge-error":"badge-gray",Dashboard.React.Elements.Span("badge "+(badgeClass||""),void 0,void 0,System.Array.init([Dashboard.React.Elements.Text(priority.toUpperCase())],Object))},FormatTime:function(dateTime){return System.String.isNullOrEmpty(dateTime)?"N/A":dateTime.length>16?dateTime.substr(11,5):dateTime},FormatReference:function(reference){var parts=System.String.split(reference,[47].map(function(i){return String.fromCharCode(i)})),id,length;return parts.length>1?(id=parts[System.Array.index(1,parts)],length=Math.min(8,id.length),(id.substr(0,length)||"")+"..."):reference}}}});H5.define("Dashboard.Pages.AppointmentsState",{fields:{Appointments:null,Loading:!1,Error:null,StatusFilter:null}});H5.define("Dashboard.Pages.CalendarPage",{statics:{fields:{MonthNames:null,DayNames:null},ctors:{init:function(){this.MonthNames=System.Array.init(["January","February","March","April","May","June","July","August","September","October","November","December"],System.String);this.DayNames=System.Array.init(["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],System.String)}},methods:{Render:function(onEditAppointment){var $t,now=System.DateTime.getNow(),stateResult=Dashboard.React.Hooks.UseState(Dashboard.Pages.CalendarState,($t=new Dashboard.Pages.CalendarState,$t.Appointments=System.Array.init(0,null,Object),$t.Loading=!0,$t.Error=null,$t.Year=System.DateTime.getYear(now),$t.Month=System.DateTime.getMonth(now),$t.SelectedDay=0,$t)),state=stateResult.State,setState=stateResult.SetState;return Dashboard.React.Hooks.UseEffect$1(function(){Dashboard.Pages.CalendarPage.LoadAppointments(setState,state)},System.Array.init(0,null,System.Object)),Dashboard.React.Elements.Div("page",void 0,void 0,void 0,System.Array.init([Dashboard.Pages.CalendarPage.RenderHeader(state,setState),state.Loading?Dashboard.Pages.CalendarPage.RenderLoadingState():state.Error!=null?Dashboard.Pages.CalendarPage.RenderError(state.Error):Dashboard.Pages.CalendarPage.RenderCalendarContent(state,setState,onEditAppointment)],Object))},LoadAppointments:function(setState,currentState){(async()=>{var $t,appointments;try{appointments=await H5.toPromise(Dashboard.Api.ApiClient.GetAppointmentsAsync());setState(($t=new Dashboard.Pages.CalendarState,$t.Appointments=appointments,$t.Loading=!1,$t.Error=null,$t.Year=currentState.Year,$t.Month=currentState.Month,$t.SelectedDay=currentState.SelectedDay,$t))}catch(ex){ex=System.Exception.create(ex);setState(($t=new Dashboard.Pages.CalendarState,$t.Appointments=System.Array.init(0,null,Object),$t.Loading=!1,$t.Error=ex.Message,$t.Year=currentState.Year,$t.Month=currentState.Month,$t.SelectedDay=currentState.SelectedDay,$t))}})()},RenderHeader:function(state,setState){var monthName=Dashboard.Pages.CalendarPage.MonthNames[System.Array.index(state.Month-1|0,Dashboard.Pages.CalendarPage.MonthNames)];return Dashboard.React.Elements.Div("page-header flex justify-between items-center mb-6",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Div(void 0,void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.H(2,"page-title",System.Array.init([Dashboard.React.Elements.Text("Schedule")],Object)),Dashboard.React.Elements.P("page-description",void 0,System.Array.init([Dashboard.React.Elements.Text("View and manage appointments on the calendar")],Object))],Object)),Dashboard.React.Elements.Div("flex items-center gap-4",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Button("btn btn-secondary btn-sm",function(){Dashboard.Pages.CalendarPage.NavigateMonth(state,setState,-1)},!1,"button",System.Array.init([Dashboard.Components.Icons.ChevronLeft()],Object)),Dashboard.React.Elements.Span("text-lg font-semibold",void 0,void 0,System.Array.init([Dashboard.React.Elements.Text((monthName||"")+" "+state.Year)],Object)),Dashboard.React.Elements.Button("btn btn-secondary btn-sm",function(){Dashboard.Pages.CalendarPage.NavigateMonth(state,setState,1)},!1,"button",System.Array.init([Dashboard.Components.Icons.ChevronRight()],Object)),Dashboard.React.Elements.Button("btn btn-primary btn-sm ml-4",function(){Dashboard.Pages.CalendarPage.GoToToday(state,setState)},!1,"button",System.Array.init([Dashboard.React.Elements.Text("Today")],Object))],Object))],Object))},NavigateMonth:function(state,setState,delta){var $t,newMonth=state.Month+delta|0,newYear=state.Year;newMonth<1?(newMonth=12,newYear=newYear-1|0):newMonth>12&&(newMonth=1,newYear=newYear+1|0);setState(($t=new Dashboard.Pages.CalendarState,$t.Appointments=state.Appointments,$t.Loading=state.Loading,$t.Error=state.Error,$t.Year=newYear,$t.Month=newMonth,$t.SelectedDay=0,$t))},GoToToday:function(state,setState){var $t,now=System.DateTime.getNow();setState(($t=new Dashboard.Pages.CalendarState,$t.Appointments=state.Appointments,$t.Loading=state.Loading,$t.Error=state.Error,$t.Year=System.DateTime.getYear(now),$t.Month=System.DateTime.getMonth(now),$t.SelectedDay=System.DateTime.getDay(now),$t))},RenderLoadingState:function(){return Dashboard.React.Elements.Div("card",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Div("flex items-center justify-center p-8",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Text("Loading calendar...")],Object))],Object))},RenderError:function(message){return Dashboard.React.Elements.Div("card",void 0,{borderLeft:"4px solid var(--error)"},void 0,System.Array.init([Dashboard.React.Elements.Div("flex items-center gap-3 p-4",void 0,void 0,void 0,System.Array.init([Dashboard.Components.Icons.X(),Dashboard.React.Elements.Text("Error loading appointments: "+(message||""))],Object))],Object))},RenderCalendarContent:function(state,setState,onEditAppointment){return Dashboard.React.Elements.Div("flex gap-6",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Div("flex-1",void 0,void 0,void 0,System.Array.init([Dashboard.Pages.CalendarPage.RenderCalendarGrid(state,setState)],Object)),state.SelectedDay>0?Dashboard.Pages.CalendarPage.RenderDayDetails(state,setState,onEditAppointment):Dashboard.Pages.CalendarPage.RenderNoSelection()],Object))},RenderCalendarGrid:function(state,setState){for(var dayNum,daysInMonth=System.DateTime.getDaysInMonth(state.Year,state.Month),firstDay=System.DateTime.create(state.Year,state.Month,1),startDayOfWeek=System.DateTime.getDayOfWeek(firstDay),headerCells=System.Linq.Enumerable.from(Dashboard.Pages.CalendarPage.DayNames,System.String).select(function(day){return Dashboard.React.Elements.Div("calendar-header-cell text-center font-semibold p-2",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Text(day)],Object))}).ToArray(Object),dayCells=System.Array.init(42,null,Object),today=System.DateTime.getNow(),i=0;i<42;i=i+1|0)if(dayNum=(i-startDayOfWeek|0)+1|0,dayNum<1||dayNum>daysInMonth)dayCells[System.Array.index(i,dayCells)]=Dashboard.React.Elements.Div("calendar-cell empty",void 0,void 0,void 0,System.Array.init(0,null,Object));else{var appointments=Dashboard.Pages.CalendarPage.GetAppointmentsForDay(state.Appointments,state.Year,state.Month,dayNum),isToday=state.Year===System.DateTime.getYear(today)&&state.Month===System.DateTime.getMonth(today)&&dayNum===System.DateTime.getDay(today),isSelected=dayNum===state.SelectedDay,dayNumCaptured={v:dayNum},cellClasses="calendar-cell";isToday&&(cellClasses=(cellClasses||"")+" today");isSelected&&(cellClasses=(cellClasses||"")+" selected");appointments.length>0&&(cellClasses=(cellClasses||"")+" has-appointments");dayCells[System.Array.index(i,dayCells)]=Dashboard.React.Elements.Div(cellClasses,void 0,void 0,function($me,dayNumCaptured){return function(){Dashboard.Pages.CalendarPage.SelectDay(state,setState,dayNumCaptured.v)}}(this,dayNumCaptured),System.Array.init([Dashboard.React.Elements.Div("calendar-day-number",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Text(H5.toString(dayNum))],Object)),appointments.length>0?Dashboard.React.Elements.Div("calendar-appointments-preview",void 0,void 0,void 0,System.Linq.Enumerable.from(appointments,Object).take(3).select(function(a){return Dashboard.Pages.CalendarPage.RenderAppointmentDot(a)}).ToArray(Object)):null,appointments.length>3?Dashboard.React.Elements.Span("calendar-more-indicator",void 0,void 0,System.Array.init([Dashboard.React.Elements.Text("+"+(appointments.length-3|0))],Object)):null],Object))}return Dashboard.React.Elements.Div("card calendar-grid-container",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Div("calendar-grid-header grid grid-cols-7",void 0,void 0,void 0,headerCells),Dashboard.React.Elements.Div("calendar-grid grid grid-cols-7",void 0,void 0,void 0,dayCells)],Object))},RenderAppointmentDot:function(appointment){var dotClass="calendar-dot";return dotClass=H5.referenceEquals(appointment.Status,"booked")?(dotClass||"")+" blue":H5.referenceEquals(appointment.Status,"arrived")?(dotClass||"")+" teal":H5.referenceEquals(appointment.Status,"fulfilled")?(dotClass||"")+" green":H5.referenceEquals(appointment.Status,"cancelled")?(dotClass||"")+" red":(dotClass||"")+" gray",Dashboard.React.Elements.Span(dotClass,void 0,void 0)},SelectDay:function(state,setState,day){var $t;setState(($t=new Dashboard.Pages.CalendarState,$t.Appointments=state.Appointments,$t.Loading=state.Loading,$t.Error=state.Error,$t.Year=state.Year,$t.Month=state.Month,$t.SelectedDay=day,$t))},GetAppointmentsForDay:function(appointments,year,month,day){var targetDate=System.DateTime.format(System.DateTime.create(year,month,day),"yyyy-MM-dd");return System.Linq.Enumerable.from(appointments,Object).where(function(a){return a.StartTime!=null&&System.String.startsWith(a.StartTime,targetDate)}).orderBy(function(a){return a.StartTime}).ToArray(Object)},RenderNoSelection:function(){return Dashboard.React.Elements.Div("card calendar-details-panel",void 0,{width:"320px",minHeight:"400px"},void 0,System.Array.init([Dashboard.React.Elements.Div("empty-state p-6",void 0,void 0,void 0,System.Array.init([Dashboard.Components.Icons.Calendar(),Dashboard.React.Elements.H(4,"empty-state-title mt-4",System.Array.init([Dashboard.React.Elements.Text("Select a Day")],Object)),Dashboard.React.Elements.P("empty-state-description",void 0,System.Array.init([Dashboard.React.Elements.Text("Click on a day to view appointments")],Object))],Object))],Object))},RenderDayDetails:function(state,setState,onEditAppointment){var appointments=Dashboard.Pages.CalendarPage.GetAppointmentsForDay(state.Appointments,state.Year,state.Month,state.SelectedDay),monthName=Dashboard.Pages.CalendarPage.MonthNames[System.Array.index(state.Month-1|0,Dashboard.Pages.CalendarPage.MonthNames)],dateStr=(monthName||"")+" "+state.SelectedDay+", "+state.Year;return Dashboard.React.Elements.Div("card calendar-details-panel",void 0,{width:"320px",minHeight:"400px"},void 0,System.Array.init([Dashboard.React.Elements.Div("flex justify-between items-center mb-4 p-4 border-b",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.H(4,"font-semibold",System.Array.init([Dashboard.React.Elements.Text(dateStr)],Object)),Dashboard.React.Elements.Button("btn btn-secondary btn-sm",function(){Dashboard.Pages.CalendarPage.SelectDay(state,setState,0)},!1,"button",System.Array.init([Dashboard.Components.Icons.X()],Object))],Object)),appointments.length===0?Dashboard.React.Elements.Div("empty-state p-6",void 0,void 0,void 0,System.Array.init([Dashboard.Components.Icons.Calendar(),Dashboard.React.Elements.P("empty-state-description mt-4",void 0,System.Array.init([Dashboard.React.Elements.Text("No appointments scheduled")],Object))],Object)):Dashboard.React.Elements.Div("p-4 space-y-3",void 0,void 0,void 0,System.Linq.Enumerable.from(appointments,Object).select(function(a){return Dashboard.Pages.CalendarPage.RenderDayAppointment(a,onEditAppointment)}).ToArray(Object))],Object))},RenderDayAppointment:function(appointment,onEditAppointment){var $t,$t1,time=Dashboard.Pages.CalendarPage.FormatTime(appointment.StartTime),endTime=Dashboard.Pages.CalendarPage.FormatTime(appointment.EndTime),statusClass=Dashboard.Pages.CalendarPage.GetStatusClass(appointment.Status);return Dashboard.React.Elements.Div("calendar-appointment-item p-3 rounded-lg border",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Div("flex justify-between items-start mb-2",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Div(void 0,void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Div("font-semibold",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Text(($t=appointment.ServiceType,$t!=null?$t:"Appointment"))],Object)),Dashboard.React.Elements.Div("text-sm text-gray-500",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Text((time||"")+" - "+(endTime||""))],Object))],Object)),Dashboard.React.Elements.Span("badge "+(statusClass||""),void 0,void 0,System.Array.init([Dashboard.React.Elements.Text(($t1=appointment.Status,$t1!=null?$t1:"unknown"))],Object))],Object)),Dashboard.React.Elements.Div("text-sm text-gray-600 mb-2",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Div(void 0,void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Text("Patient: "+(Dashboard.Pages.CalendarPage.FormatReference(appointment.PatientReference)||""))],Object)),Dashboard.React.Elements.Div(void 0,void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Text("Provider: "+(Dashboard.Pages.CalendarPage.FormatReference(appointment.PractitionerReference)||""))],Object))],Object)),Dashboard.React.Elements.Div("flex gap-2",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Button("btn btn-primary btn-sm flex-1",function(){onEditAppointment(appointment.Id)},!1,"button",System.Array.init([Dashboard.Components.Icons.Edit(),Dashboard.React.Elements.Text("Edit")],Object))],Object))],Object))},FormatTime:function(dateTime){return System.String.isNullOrEmpty(dateTime)?"N/A":dateTime.length>16?dateTime.substr(11,5):dateTime},FormatReference:function(reference){var parts,id,length;return System.String.isNullOrEmpty(reference)?"N/A":(parts=System.String.split(reference,[47].map(function(i){return String.fromCharCode(i)})),parts.length>1)?(id=parts[System.Array.index(1,parts)],length=Math.min(8,id.length),(id.substr(0,length)||"")+"..."):reference},GetStatusClass:function(status){return H5.referenceEquals(status,"booked")?"badge-primary":H5.referenceEquals(status,"arrived")?"badge-teal":H5.referenceEquals(status,"fulfilled")?"badge-success":H5.referenceEquals(status,"cancelled")?"badge-error":H5.referenceEquals(status,"noshow")?"badge-warning":"badge-gray"}}}});H5.define("Dashboard.Pages.CalendarState",{fields:{Appointments:null,Loading:!1,Error:null,Year:0,Month:0,SelectedDay:0}});H5.define("Dashboard.Pages.ClinicalCodingPage",{statics:{methods:{Render:function(){var $t,stateResult=Dashboard.React.Hooks.UseState(Dashboard.Pages.ClinicalCodingState,($t=new Dashboard.Pages.ClinicalCodingState,$t.SearchQuery="",$t.SearchMode="keyword",$t.Icd10Results=System.Array.init(0,null,Object),$t.AchiResults=System.Array.init(0,null,Object),$t.SemanticResults=System.Array.init(0,null,Object),$t.SelectedCode=null,$t.Loading=!1,$t.Error=null,$t.IncludeAchi=!1,$t.CopiedCode=null,$t)),state=stateResult.State,setState=stateResult.SetState;return Dashboard.React.Elements.Div("page clinical-coding-page",void 0,void 0,void 0,System.Array.init([Dashboard.Pages.ClinicalCodingPage.RenderHeader(),Dashboard.Pages.ClinicalCodingPage.RenderSearchSection(state,setState),Dashboard.Pages.ClinicalCodingPage.RenderContent(state,setState)],Object))},RenderHeader:function(){return Dashboard.React.Elements.Div("page-header",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Div("flex items-center gap-3",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Div("page-header-icon",void 0,{background:"linear-gradient(135deg, #3b82f6, #8b5cf6)",borderRadius:"12px",padding:"12px",display:"flex",alignItems:"center",justifyContent:"center"},void 0,System.Array.init([Dashboard.Components.Icons.Code()],Object)),Dashboard.React.Elements.Div(void 0,void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.H(2,"page-title",System.Array.init([Dashboard.React.Elements.Text("Clinical Coding")],Object)),Dashboard.React.Elements.P("page-description",void 0,System.Array.init([Dashboard.React.Elements.Text("Search ICD-10-AM diagnosis codes and ACHI procedure codes")],Object))],Object))],Object))],Object))},RenderSearchSection:function(state,setState){return Dashboard.React.Elements.Div("card mb-6",void 0,{padding:"24px"},void 0,System.Array.init([Dashboard.Pages.ClinicalCodingPage.RenderSearchTabs(state,setState),Dashboard.Pages.ClinicalCodingPage.RenderSearchInput(state,setState),Dashboard.Pages.ClinicalCodingPage.RenderSearchOptions(state,setState)],Object))},RenderSearchTabs:function(state,setState){return Dashboard.React.Elements.Div("flex gap-2 mb-4",void 0,void 0,void 0,System.Array.init([Dashboard.Pages.ClinicalCodingPage.RenderTab("Keyword Search",Dashboard.Components.Icons.Search,H5.referenceEquals(state.SearchMode,"keyword"),function(){Dashboard.Pages.ClinicalCodingPage.SetSearchMode(state,setState,"keyword")}),Dashboard.Pages.ClinicalCodingPage.RenderTab("AI Search",Dashboard.Components.Icons.Sparkles,H5.referenceEquals(state.SearchMode,"semantic"),function(){Dashboard.Pages.ClinicalCodingPage.SetSearchMode(state,setState,"semantic")}),Dashboard.Pages.ClinicalCodingPage.RenderTab("Code Lookup",Dashboard.Components.Icons.FileText,H5.referenceEquals(state.SearchMode,"lookup"),function(){Dashboard.Pages.ClinicalCodingPage.SetSearchMode(state,setState,"lookup")})],Object))},RenderTab:function(label,icon,isActive,onClick){return Dashboard.React.Elements.Button("btn "+((isActive?"btn-primary":"btn-secondary")||""),onClick,!1,"button",System.Array.init([icon(),Dashboard.React.Elements.Text(label)],Object))},SetSearchMode:function(state,setState,mode){var $t;setState(($t=new Dashboard.Pages.ClinicalCodingState,$t.SearchQuery=state.SearchQuery,$t.SearchMode=mode,$t.Icd10Results=System.Array.init(0,null,Object),$t.AchiResults=System.Array.init(0,null,Object),$t.SemanticResults=System.Array.init(0,null,Object),$t.SelectedCode=null,$t.Loading=!1,$t.Error=null,$t.IncludeAchi=state.IncludeAchi,$t.CopiedCode=null,$t))},RenderSearchInput:function(state,setState){var placeholder=Dashboard.Pages.ClinicalCodingPage.GetPlaceholder(state.SearchMode);return Dashboard.React.Elements.Div("flex gap-4",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Div("flex-1 search-input search-input-lg",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Span("search-icon",void 0,void 0,System.Array.init([Dashboard.Components.Icons.Search()],Object)),Dashboard.React.Elements.Input("input input-lg","text",state.SearchQuery,placeholder,function(query){Dashboard.Pages.ClinicalCodingPage.UpdateQuery(state,setState,query)},function(key){H5.referenceEquals(key,"Enter")&&Dashboard.Pages.ClinicalCodingPage.ExecuteSearch(state,setState)},!1)],Object)),Dashboard.React.Elements.Button("btn btn-primary btn-lg",function(){Dashboard.Pages.ClinicalCodingPage.ExecuteSearch(state,setState)},!1,"button",System.Array.init([state.Loading?Dashboard.Components.Icons.Refresh():Dashboard.Components.Icons.Search(),Dashboard.React.Elements.Text(state.Loading?"Searching...":"Search")],Object))],Object))},GetPlaceholder:function(mode){return H5.referenceEquals(mode,"keyword")?"Search by code, description, or keywords (e.g., 'diabetes', 'fracture')":H5.referenceEquals(mode,"semantic")?"Describe symptoms or conditions in natural language...":"Enter ICD-10 code or prefix (e.g., 'O9A.', 'E11', 'J18.9')"},UpdateQuery:function(state,setState,query){var $t;setState(($t=new Dashboard.Pages.ClinicalCodingState,$t.SearchQuery=query,$t.SearchMode=state.SearchMode,$t.Icd10Results=state.Icd10Results,$t.AchiResults=state.AchiResults,$t.SemanticResults=state.SemanticResults,$t.SelectedCode=state.SelectedCode,$t.Loading=state.Loading,$t.Error=state.Error,$t.IncludeAchi=state.IncludeAchi,$t.CopiedCode=state.CopiedCode,$t))},RenderSearchOptions:function(state,setState){return H5.referenceEquals(state.SearchMode,"semantic")?Dashboard.React.Elements.Div("flex items-center gap-4 mt-4",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Label(void 0,"flex items-center gap-2 cursor-pointer",System.Array.init([Dashboard.React.Elements.Input("checkbox","checkbox",state.IncludeAchi?"true":"",void 0,function(_){Dashboard.Pages.ClinicalCodingPage.ToggleAchi(state,setState)},void 0,!1),Dashboard.React.Elements.Span(void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Text("Include ACHI procedure codes")],Object))],Object)),Dashboard.React.Elements.Span("text-sm text-gray-500",void 0,void 0,System.Array.init([Dashboard.Components.Icons.Sparkles(),Dashboard.React.Elements.Text(" Powered by medical AI embeddings")],Object))],Object)):Dashboard.React.Elements.Text("")},ToggleAchi:function(state,setState){var $t;setState(($t=new Dashboard.Pages.ClinicalCodingState,$t.SearchQuery=state.SearchQuery,$t.SearchMode=state.SearchMode,$t.Icd10Results=state.Icd10Results,$t.AchiResults=state.AchiResults,$t.SemanticResults=state.SemanticResults,$t.SelectedCode=state.SelectedCode,$t.Loading=state.Loading,$t.Error=state.Error,$t.IncludeAchi=!state.IncludeAchi,$t.CopiedCode=state.CopiedCode,$t))},ExecuteSearch:function(state,setState){(async()=>{var $t,$t1,results,results1,c,fullCode;if(!System.String.isNullOrWhiteSpace(state.SearchQuery)){setState(($t=new Dashboard.Pages.ClinicalCodingState,$t.SearchQuery=state.SearchQuery,$t.SearchMode=state.SearchMode,$t.Icd10Results=System.Array.init(0,null,Object),$t.AchiResults=System.Array.init(0,null,Object),$t.SemanticResults=System.Array.init(0,null,Object),$t.SelectedCode=null,$t.Loading=!0,$t.Error=null,$t.IncludeAchi=state.IncludeAchi,$t.CopiedCode=null,$t));try{if(H5.referenceEquals(state.SearchMode,"keyword"))results=await H5.toPromise(Dashboard.Api.ApiClient.SearchIcd10CodesAsync(state.SearchQuery,50)),setState(($t=new Dashboard.Pages.ClinicalCodingState,$t.SearchQuery=state.SearchQuery,$t.SearchMode=state.SearchMode,$t.Icd10Results=results,$t.AchiResults=System.Array.init(0,null,Object),$t.SemanticResults=System.Array.init(0,null,Object),$t.SelectedCode=null,$t.Loading=!1,$t.Error=null,$t.IncludeAchi=state.IncludeAchi,$t.CopiedCode=null,$t));else if(H5.referenceEquals(state.SearchMode,"semantic"))results1=await H5.toPromise(Dashboard.Api.ApiClient.SemanticSearchAsync(state.SearchQuery,20,state.IncludeAchi)),setState(($t=new Dashboard.Pages.ClinicalCodingState,$t.SearchQuery=state.SearchQuery,$t.SearchMode=state.SearchMode,$t.Icd10Results=System.Array.init(0,null,Object),$t.AchiResults=System.Array.init(0,null,Object),$t.SemanticResults=results1,$t.SelectedCode=null,$t.Loading=!1,$t.Error=null,$t.IncludeAchi=state.IncludeAchi,$t.CopiedCode=null,$t));else{var allResults=await H5.toPromise(Dashboard.Api.ApiClient.SearchIcd10CodesAsync(state.SearchQuery,100)),query=state.SearchQuery.toUpperCase(),matchingCodes=new(System.Collections.Generic.List$1(Object).ctor);$t=H5.getEnumerator(allResults);try{while($t.moveNext())c=$t.Current,c.Code!=null&&System.String.startsWith(c.Code.toUpperCase(),query)&&matchingCodes.add(c)}finally{H5.is($t,System.IDisposable)&&$t.System$IDisposable$Dispose()}matchingCodes.Count===1?(fullCode=await H5.toPromise(Dashboard.Api.ApiClient.GetIcd10CodeAsync(matchingCodes.getItem(0).Code)),setState(($t1=new Dashboard.Pages.ClinicalCodingState,$t1.SearchQuery=state.SearchQuery,$t1.SearchMode=state.SearchMode,$t1.Icd10Results=System.Array.init(0,null,Object),$t1.AchiResults=System.Array.init(0,null,Object),$t1.SemanticResults=System.Array.init(0,null,Object),$t1.SelectedCode=fullCode,$t1.Loading=!1,$t1.Error=null,$t1.IncludeAchi=state.IncludeAchi,$t1.CopiedCode=null,$t1))):setState(($t1=new Dashboard.Pages.ClinicalCodingState,$t1.SearchQuery=state.SearchQuery,$t1.SearchMode=state.SearchMode,$t1.Icd10Results=matchingCodes.ToArray(),$t1.AchiResults=System.Array.init(0,null,Object),$t1.SemanticResults=System.Array.init(0,null,Object),$t1.SelectedCode=null,$t1.Loading=!1,$t1.Error=null,$t1.IncludeAchi=state.IncludeAchi,$t1.CopiedCode=null,$t1))}}catch(ex){ex=System.Exception.create(ex);setState(($t1=new Dashboard.Pages.ClinicalCodingState,$t1.SearchQuery=state.SearchQuery,$t1.SearchMode=state.SearchMode,$t1.Icd10Results=System.Array.init(0,null,Object),$t1.AchiResults=System.Array.init(0,null,Object),$t1.SemanticResults=System.Array.init(0,null,Object),$t1.SelectedCode=null,$t1.Loading=!1,$t1.Error=ex.Message,$t1.IncludeAchi=state.IncludeAchi,$t1.CopiedCode=null,$t1))}}})()},RenderContent:function(state,setState){return state.Loading?Dashboard.Pages.ClinicalCodingPage.RenderLoading():state.Error!=null?Dashboard.Pages.ClinicalCodingPage.RenderError(state.Error):state.SelectedCode!=null?Dashboard.Pages.ClinicalCodingPage.RenderCodeDetail(state,setState):state.SemanticResults.length>0?Dashboard.Pages.ClinicalCodingPage.RenderSemanticResults(state,setState):state.Icd10Results.length>0?Dashboard.Pages.ClinicalCodingPage.RenderKeywordResults(state,setState):H5.referenceEquals(state.SearchMode,"lookup")&&!System.String.isNullOrWhiteSpace(state.SearchQuery)&&!state.Loading?Dashboard.Pages.ClinicalCodingPage.RenderNoResults(state.SearchQuery):Dashboard.Pages.ClinicalCodingPage.RenderEmptyState(state)},RenderNoResults:function(query){return Dashboard.React.Elements.Div("card",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Div("empty-state",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Div(void 0,void 0,{background:"linear-gradient(135deg, #6b7280, #9ca3af)",borderRadius:"16px",padding:"20px",marginBottom:"16px"},void 0,System.Array.init([Dashboard.Components.Icons.Search()],Object)),Dashboard.React.Elements.H(4,"empty-state-title",System.Array.init([Dashboard.React.Elements.Text("No codes found")],Object)),Dashboard.React.Elements.P("empty-state-description",void 0,System.Array.init([Dashboard.React.Elements.Text("No ICD-10 codes match '"+(query||"")+"'. Try a different code or use keyword search.")],Object))],Object))],Object))},RenderLoading:function(){return Dashboard.React.Elements.Div("card",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Div("flex items-center justify-center p-12",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Div("loading-spinner",void 0,{width:"48px",height:"48px",border:"4px solid #e5e7eb",borderTop:"4px solid #3b82f6",borderRadius:"50%",animation:"spin 1s linear infinite"},void 0)],Object))],Object))},RenderError:function(error){return Dashboard.React.Elements.Div("card",void 0,{borderLeft:"4px solid var(--error)"},void 0,System.Array.init([Dashboard.React.Elements.Div("flex items-center gap-3 p-4",void 0,void 0,void 0,System.Array.init([Dashboard.Components.Icons.X(),Dashboard.React.Elements.Div(void 0,void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.H(4,"font-semibold",System.Array.init([Dashboard.React.Elements.Text("Search Error")],Object)),Dashboard.React.Elements.P("text-sm text-gray-600",void 0,System.Array.init([Dashboard.React.Elements.Text(error)],Object)),Dashboard.React.Elements.P("text-sm text-gray-500 mt-2",void 0,System.Array.init([Dashboard.React.Elements.Text("Make sure the ICD-10 API (port 5090) is running.")],Object))],Object))],Object))],Object))},RenderEmptyState:function(state){var title=Dashboard.Pages.ClinicalCodingPage.GetEmptyTitle(state.SearchMode),description=Dashboard.Pages.ClinicalCodingPage.GetEmptyDescription(state.SearchMode);return Dashboard.React.Elements.Div("card",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Div("empty-state",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Div(void 0,void 0,{background:"linear-gradient(135deg, #3b82f6, #8b5cf6)",borderRadius:"16px",padding:"20px",marginBottom:"16px"},void 0,System.Array.init([Dashboard.Components.Icons.Code()],Object)),Dashboard.React.Elements.H(4,"empty-state-title",System.Array.init([Dashboard.React.Elements.Text(title)],Object)),Dashboard.React.Elements.P("empty-state-description",void 0,System.Array.init([Dashboard.React.Elements.Text(description)],Object)),Dashboard.Pages.ClinicalCodingPage.RenderQuickSearches(state)],Object))],Object))},GetEmptyTitle:function(mode){return H5.referenceEquals(mode,"semantic")?"AI-Powered Code Search":H5.referenceEquals(mode,"lookup")?"Direct Code Lookup":"ICD-10-AM Code Search"},GetEmptyDescription:function(mode){return H5.referenceEquals(mode,"semantic")?"Describe symptoms in natural language and let AI find the right codes.":H5.referenceEquals(mode,"lookup")?"Enter an ICD-10 code or prefix to find matching codes (e.g., 'O9A.' lists all O9A codes).":"Search diagnosis codes by keyword, description, or code fragment."},RenderQuickSearches:function(state){var examples,buttons,i,example;if(H5.referenceEquals(state.SearchMode,"lookup"))return Dashboard.React.Elements.Text("");for(examples=H5.referenceEquals(state.SearchMode,"semantic")?System.Array.init(["Patient with chest pain and shortness of breath","Type 2 diabetes with kidney complications","Broken arm from fall","Chronic lower back pain"],System.String):System.Array.init(["diabetes","pneumonia","fracture","hypertension"],System.String),buttons=System.Array.init(examples.length,null,Object),i=0;i{var $t,fullCode;setState(($t=new Dashboard.Pages.ClinicalCodingState,$t.SearchQuery=state.SearchQuery,$t.SearchMode=state.SearchMode,$t.Icd10Results=state.Icd10Results,$t.AchiResults=state.AchiResults,$t.SemanticResults=state.SemanticResults,$t.SelectedCode=null,$t.Loading=!0,$t.Error=null,$t.IncludeAchi=state.IncludeAchi,$t.CopiedCode=state.CopiedCode,$t));try{fullCode=await H5.toPromise(Dashboard.Api.ApiClient.GetIcd10CodeAsync(code.Code));setState(($t=new Dashboard.Pages.ClinicalCodingState,$t.SearchQuery=state.SearchQuery,$t.SearchMode=state.SearchMode,$t.Icd10Results=state.Icd10Results,$t.AchiResults=state.AchiResults,$t.SemanticResults=state.SemanticResults,$t.SelectedCode=fullCode,$t.Loading=!1,$t.Error=null,$t.IncludeAchi=state.IncludeAchi,$t.CopiedCode=state.CopiedCode,$t))}catch(ex){ex=System.Exception.create(ex);setState(($t=new Dashboard.Pages.ClinicalCodingState,$t.SearchQuery=state.SearchQuery,$t.SearchMode=state.SearchMode,$t.Icd10Results=state.Icd10Results,$t.AchiResults=state.AchiResults,$t.SemanticResults=state.SemanticResults,$t.SelectedCode=null,$t.Loading=!1,$t.Error="Failed to load code details: "+(ex.Message||""),$t.IncludeAchi=state.IncludeAchi,$t.CopiedCode=state.CopiedCode,$t))}})()},CopyCode:function(code,state,setState){var $t;navigator.clipboard.writeText(code);setState(($t=new Dashboard.Pages.ClinicalCodingState,$t.SearchQuery=state.SearchQuery,$t.SearchMode=state.SearchMode,$t.Icd10Results=state.Icd10Results,$t.AchiResults=state.AchiResults,$t.SemanticResults=state.SemanticResults,$t.SelectedCode=state.SelectedCode,$t.Loading=state.Loading,$t.Error=state.Error,$t.IncludeAchi=state.IncludeAchi,$t.CopiedCode=code,$t))},RenderSemanticResults:function(state,setState){for(var result,$t,resultRows=System.Array.init(state.SemanticResults.length,null,Object),i=0;i=80?"#22c55e":confidencePercent>=60?"#f59e0b":"#ef4444",badgeClass=confidencePercent>=80?"badge-success":confidencePercent>=60?"badge-warning":"badge-error";return Dashboard.React.Elements.Tr("search-result-row",function(){Dashboard.Pages.ClinicalCodingPage.LookupSemanticCode(result.Code,state,setState)},System.Array.init([Dashboard.React.Elements.Td(void 0,System.Array.init([Dashboard.React.Elements.Span("badge badge-primary",void 0,{background:H5.referenceEquals(result.CodeType,"ACHI")?"linear-gradient(135deg, #14b8a6, #0d9488)":"linear-gradient(135deg, #3b82f6, #8b5cf6)",color:"white",fontWeight:"600"},System.Array.init([Dashboard.React.Elements.Text(result.Code)],Object))],Object)),Dashboard.React.Elements.Td(void 0,System.Array.init([Dashboard.React.Elements.Span(H5.referenceEquals(result.CodeType,"ACHI")?"badge badge-teal":"badge badge-violet",void 0,void 0,System.Array.init([Dashboard.React.Elements.Text(($t=result.CodeType,$t!=null?$t:"ICD10CM"))],Object))],Object)),Dashboard.React.Elements.Td("text-sm text-gray-600",System.Array.init([Dashboard.React.Elements.Text(System.String.isNullOrEmpty(result.Chapter)?"-":"Ch. "+(result.Chapter||""))],Object)),Dashboard.React.Elements.Td("text-sm text-gray-600",System.Array.init([Dashboard.React.Elements.Text(($t1=result.Category,$t1!=null?$t1:"-"))],Object)),Dashboard.React.Elements.Td("result-description-cell",System.Array.init([Dashboard.React.Elements.Span(void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Text(($t2=result.Description,$t2!=null?$t2:""))],Object)),Dashboard.React.Elements.Div("result-tooltip",void 0,void 0,void 0,Dashboard.Pages.ClinicalCodingPage.RenderSemanticTooltipContent(result,confidenceColor,confidencePercent))],Object)),Dashboard.React.Elements.Td(void 0,System.Array.init([Dashboard.React.Elements.Div("flex items-center gap-2",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Div(void 0,void 0,{width:"60px",height:"8px",background:"#e5e7eb",borderRadius:"4px",overflow:"hidden"},void 0,System.Array.init([Dashboard.React.Elements.Div(void 0,void 0,{width:confidencePercent+"%",height:"100%",background:confidenceColor},void 0)],Object)),Dashboard.React.Elements.Span("badge "+(badgeClass||""),void 0,void 0,System.Array.init([Dashboard.React.Elements.Text(confidencePercent+"%")],Object))],Object))],Object))],Object))},RenderSemanticTooltipContent:function(result,confidenceColor,confidencePercent){var $t,elements=function(_o1){var $t,$t1,$t2;return _o1.add(Dashboard.React.Elements.H(4,"font-semibold mb-2",System.Array.init([Dashboard.React.Elements.Text((result.Code||"")+" - "+(($t=result.Description,$t!=null?$t:"")||""))],Object))),_o1.add(Dashboard.React.Elements.P("text-sm text-gray-600 mb-3",void 0,System.Array.init([Dashboard.React.Elements.Text(($t1=result.LongDescription,$t1!=null?$t1:($t2=result.Description,$t2!=null?$t2:"")))],Object))),_o1}(new(System.Collections.Generic.List$1(Object).ctor)),footerChildren;return System.String.isNullOrEmpty(result.InclusionTerms)||elements.add(Dashboard.React.Elements.Div("text-xs text-green-700 mb-2",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Span("font-semibold",void 0,void 0,System.Array.init([Dashboard.React.Elements.Text("Includes: ")],Object)),Dashboard.React.Elements.Text(result.InclusionTerms)],Object))),System.String.isNullOrEmpty(result.ExclusionTerms)||elements.add(Dashboard.React.Elements.Div("text-xs text-red-700 mb-2",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Span("font-semibold",void 0,void 0,System.Array.init([Dashboard.React.Elements.Text("Excludes: ")],Object)),Dashboard.React.Elements.Text(result.ExclusionTerms)],Object))),System.String.isNullOrEmpty(result.CodeAlso)||elements.add(Dashboard.React.Elements.Div("text-xs text-blue-700 mb-2",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Span("font-semibold",void 0,void 0,System.Array.init([Dashboard.React.Elements.Text("Code also: ")],Object)),Dashboard.React.Elements.Text(result.CodeAlso)],Object))),System.String.isNullOrEmpty(result.CodeFirst)||elements.add(Dashboard.React.Elements.Div("text-xs text-purple-700 mb-2",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Span("font-semibold",void 0,void 0,System.Array.init([Dashboard.React.Elements.Text("Code first: ")],Object)),Dashboard.React.Elements.Text(result.CodeFirst)],Object))),footerChildren=function(_o2){var $t;return _o2.add(Dashboard.React.Elements.Span("font-semibold",void 0,void 0,System.Array.init([Dashboard.React.Elements.Text("Type: ")],Object))),_o2.add(Dashboard.React.Elements.Text(($t=result.CodeType,$t!=null?$t:"ICD10CM"))),_o2}(new(System.Collections.Generic.List$1(Object).ctor)),System.String.isNullOrEmpty(result.Chapter)||(footerChildren.add(Dashboard.React.Elements.Text(" | ")),footerChildren.add(Dashboard.React.Elements.Span("font-semibold",void 0,void 0,System.Array.init([Dashboard.React.Elements.Text("Chapter: ")],Object))),footerChildren.add(Dashboard.React.Elements.Text((result.Chapter||"")+" - "+(($t=result.ChapterTitle,$t!=null?$t:"")||"")))),System.String.isNullOrEmpty(result.Category)||(footerChildren.add(Dashboard.React.Elements.Text(" | ")),footerChildren.add(Dashboard.React.Elements.Span("font-semibold",void 0,void 0,System.Array.init([Dashboard.React.Elements.Text("Category: ")],Object))),footerChildren.add(Dashboard.React.Elements.Text(result.Category))),footerChildren.add(Dashboard.React.Elements.Text(" | ")),footerChildren.add(Dashboard.React.Elements.Span("font-semibold",void 0,void 0,System.Array.init([Dashboard.React.Elements.Text("Confidence: ")],Object))),footerChildren.add(Dashboard.React.Elements.Span(void 0,void 0,{color:confidenceColor},System.Array.init([Dashboard.React.Elements.Text(confidencePercent+"%")],Object))),elements.add(Dashboard.React.Elements.Div("text-xs text-gray-500 mt-2 pt-2 border-t border-gray-200",void 0,void 0,void 0,footerChildren.ToArray())),elements.ToArray()},LookupSemanticCode:function(code,state,setState){(async()=>{var $t,result;setState(($t=new Dashboard.Pages.ClinicalCodingState,$t.SearchQuery=code,$t.SearchMode="lookup",$t.Icd10Results=System.Array.init(0,null,Object),$t.AchiResults=System.Array.init(0,null,Object),$t.SemanticResults=System.Array.init(0,null,Object),$t.SelectedCode=null,$t.Loading=!0,$t.Error=null,$t.IncludeAchi=state.IncludeAchi,$t.CopiedCode=null,$t));try{result=await H5.toPromise(Dashboard.Api.ApiClient.GetIcd10CodeAsync(code));setState(($t=new Dashboard.Pages.ClinicalCodingState,$t.SearchQuery=code,$t.SearchMode="lookup",$t.Icd10Results=System.Array.init(0,null,Object),$t.AchiResults=System.Array.init(0,null,Object),$t.SemanticResults=System.Array.init(0,null,Object),$t.SelectedCode=result,$t.Loading=!1,$t.Error=null,$t.IncludeAchi=state.IncludeAchi,$t.CopiedCode=null,$t))}catch(ex){ex=System.Exception.create(ex);setState(($t=new Dashboard.Pages.ClinicalCodingState,$t.SearchQuery=code,$t.SearchMode="lookup",$t.Icd10Results=System.Array.init(0,null,Object),$t.AchiResults=System.Array.init(0,null,Object),$t.SemanticResults=System.Array.init(0,null,Object),$t.SelectedCode=null,$t.Loading=!1,$t.Error=ex.Message,$t.IncludeAchi=state.IncludeAchi,$t.CopiedCode=null,$t))}})()},RenderCodeDetail:function(state,setState){var $t,$t1,$t2,$t3,code=state.SelectedCode;return Dashboard.React.Elements.Div(void 0,void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Button("btn btn-ghost mb-4",function(){Dashboard.Pages.ClinicalCodingPage.ClearSelection(state,setState)},!1,"button",System.Array.init([Dashboard.Components.Icons.ChevronLeft(),Dashboard.React.Elements.Text("Back to results")],Object)),Dashboard.React.Elements.Div("card",void 0,{padding:"32px"},void 0,System.Array.init([Dashboard.React.Elements.Div("flex items-start justify-between mb-6",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Div(void 0,void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Div("flex items-center gap-3 mb-2",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Span(void 0,void 0,{background:"linear-gradient(135deg, #3b82f6, #8b5cf6)",color:"white",padding:"8px 20px",borderRadius:"8px",fontWeight:"700",fontSize:"20px"},System.Array.init([Dashboard.React.Elements.Text(code.Code)],Object)),code.Billable?Dashboard.React.Elements.Span("badge badge-success",void 0,void 0,System.Array.init([Dashboard.Components.Icons.Check(),Dashboard.React.Elements.Text("Billable")],Object)):Dashboard.React.Elements.Span("badge badge-gray",void 0,void 0,System.Array.init([Dashboard.React.Elements.Text("Non-billable")],Object))],Object)),Dashboard.React.Elements.H(2,"text-xl font-semibold mt-4",System.Array.init([Dashboard.React.Elements.Text(($t=code.ShortDescription,$t!=null?$t:""))],Object))],Object)),Dashboard.React.Elements.Button("btn btn-primary",function(){Dashboard.Pages.ClinicalCodingPage.CopyCode(code.Code,state,setState)},!1,"button",System.Array.init([H5.referenceEquals(state.CopiedCode,code.Code)?Dashboard.Components.Icons.Check():Dashboard.Components.Icons.Copy(),Dashboard.React.Elements.Text(H5.referenceEquals(state.CopiedCode,code.Code)?"Copied!":"Copy Code")],Object))],Object)),Dashboard.React.Elements.Div("grid grid-cols-3 gap-4 mb-6 p-4",void 0,{background:"#f9fafb",borderRadius:"8px"},void 0,System.Array.init([Dashboard.Pages.ClinicalCodingPage.RenderDetailItem("Chapter",(code.ChapterNumber||"")+" - "+(($t1=code.ChapterTitle,$t1!=null?$t1:"")||"")),Dashboard.Pages.ClinicalCodingPage.RenderDetailItem("Block",($t2=code.BlockCode,$t2!=null?$t2:"")),Dashboard.Pages.ClinicalCodingPage.RenderDetailItem("Category",($t3=code.CategoryCode,$t3!=null?$t3:""))],Object)),Dashboard.Pages.ClinicalCodingPage.RenderDetailSection("Full Description",code.LongDescription),Dashboard.Pages.ClinicalCodingPage.RenderDetailSection("Inclusion Terms",code.InclusionTerms),Dashboard.Pages.ClinicalCodingPage.RenderDetailSection("Exclusion Terms",code.ExclusionTerms),Dashboard.Pages.ClinicalCodingPage.RenderDetailSection("Code Also",code.CodeAlso),Dashboard.Pages.ClinicalCodingPage.RenderDetailSection("Code First",code.CodeFirst)],Object))],Object))},RenderDetailItem:function(label,value){return Dashboard.React.Elements.Div(void 0,void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Span("text-xs text-gray-500 uppercase tracking-wide",void 0,void 0,System.Array.init([Dashboard.React.Elements.Text(label)],Object)),Dashboard.React.Elements.P("font-medium",void 0,System.Array.init([Dashboard.React.Elements.Text(value)],Object))],Object))},RenderDetailSection:function(title,content){return System.String.isNullOrWhiteSpace(content)?Dashboard.React.Elements.Text(""):Dashboard.React.Elements.Div("mb-4",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.H(4,"font-semibold text-gray-700 mb-2",System.Array.init([Dashboard.React.Elements.Text(title)],Object)),Dashboard.React.Elements.Div("p-4",void 0,{background:"#f9fafb",borderRadius:"8px",borderLeft:"4px solid #3b82f6"},void 0,System.Array.init([Dashboard.React.Elements.P("text-gray-700 whitespace-pre-wrap",void 0,System.Array.init([Dashboard.React.Elements.Text(content)],Object))],Object))],Object))},ClearSelection:function(state,setState){var $t;setState(($t=new Dashboard.Pages.ClinicalCodingState,$t.SearchQuery=state.SearchQuery,$t.SearchMode=state.SearchMode,$t.Icd10Results=state.Icd10Results,$t.AchiResults=state.AchiResults,$t.SemanticResults=state.SemanticResults,$t.SelectedCode=null,$t.Loading=!1,$t.Error=null,$t.IncludeAchi=state.IncludeAchi,$t.CopiedCode=null,$t))}}}});H5.define("Dashboard.Pages.ClinicalCodingState",{fields:{SearchQuery:null,SearchMode:null,Icd10Results:null,AchiResults:null,SemanticResults:null,SelectedCode:null,Loading:!1,Error:null,IncludeAchi:!1,CopiedCode:null}});H5.define("Dashboard.Pages.DashboardPage",{statics:{methods:{Render:function(){var $t,stateResult=Dashboard.React.Hooks.UseState(Dashboard.Pages.DashboardState,($t=new Dashboard.Pages.DashboardState,$t.PatientCount=0,$t.PractitionerCount=0,$t.AppointmentCount=0,$t.EncounterCount=0,$t.Loading=!0,$t.Error=null,$t)),state=stateResult.State,setState=stateResult.SetState,errorElement;return Dashboard.React.Hooks.UseEffect$1(function(){Dashboard.Pages.DashboardPage.LoadData(setState)},System.Array.init(0,null,System.Object)),errorElement=state.Error!=null?Dashboard.Pages.DashboardPage.RenderError(state.Error):Dashboard.React.Elements.Text(""),Dashboard.React.Elements.Div("page",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Div("page-header",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.H(2,"page-title",System.Array.init([Dashboard.React.Elements.Text("Dashboard")],Object)),Dashboard.React.Elements.P("page-description",void 0,System.Array.init([Dashboard.React.Elements.Text("Overview of your healthcare system")],Object))],Object)),errorElement,Dashboard.React.Elements.Div("dashboard-grid metrics mb-6",void 0,void 0,void 0,System.Array.init([Dashboard.Components.MetricCard.Render(($t=new Dashboard.Components.MetricCardProps,$t.Label="Total Patients",$t.Value=state.Loading?"-":H5.toString(state.PatientCount),$t.Icon=Dashboard.Components.Icons.Users,$t.IconColor="blue",$t.TrendValue="+12%",$t.Trend=Dashboard.Components.TrendDirection.Up,$t)),Dashboard.Components.MetricCard.Render(($t=new Dashboard.Components.MetricCardProps,$t.Label="Practitioners",$t.Value=state.Loading?"-":H5.toString(state.PractitionerCount),$t.Icon=Dashboard.Components.Icons.UserDoctor,$t.IconColor="teal",$t)),Dashboard.Components.MetricCard.Render(($t=new Dashboard.Components.MetricCardProps,$t.Label="Appointments",$t.Value=state.Loading?"-":H5.toString(state.AppointmentCount),$t.Icon=Dashboard.Components.Icons.Calendar,$t.IconColor="success",$t.TrendValue="+8%",$t.Trend=Dashboard.Components.TrendDirection.Up,$t)),Dashboard.Components.MetricCard.Render(($t=new Dashboard.Components.MetricCardProps,$t.Label="Encounters",$t.Value=state.Loading?"-":H5.toString(state.EncounterCount),$t.Icon=Dashboard.Components.Icons.Clipboard,$t.IconColor="warning",$t.TrendValue="-3%",$t.Trend=Dashboard.Components.TrendDirection.Down,$t))],Object)),Dashboard.React.Elements.Div("dashboard-grid mixed",void 0,void 0,void 0,System.Array.init([Dashboard.Pages.DashboardPage.RenderQuickActions(),Dashboard.Pages.DashboardPage.RenderRecentActivity()],Object))],Object))},LoadData:function(setState){(async()=>{var $t;try{var patients=await H5.toPromise(Dashboard.Api.ApiClient.GetPatientsAsync()),practitioners=await H5.toPromise(Dashboard.Api.ApiClient.GetPractitionersAsync()),appointments=await H5.toPromise(Dashboard.Api.ApiClient.GetAppointmentsAsync());setState(($t=new Dashboard.Pages.DashboardState,$t.PatientCount=patients.length,$t.PractitionerCount=practitioners.length,$t.AppointmentCount=appointments.length,$t.EncounterCount=0,$t.Loading=!1,$t.Error=null,$t))}catch(ex){ex=System.Exception.create(ex);setState(($t=new Dashboard.Pages.DashboardState,$t.PatientCount=0,$t.PractitionerCount=0,$t.AppointmentCount=0,$t.EncounterCount=0,$t.Loading=!1,$t.Error=ex.Message,$t))}})()},RenderError:function(message){return Dashboard.React.Elements.Div("card mb-6",void 0,{borderLeft:"4px solid var(--warning)"},void 0,System.Array.init([Dashboard.React.Elements.Div("flex items-center gap-3",void 0,void 0,void 0,System.Array.init([Dashboard.Components.Icons.Bell(),Dashboard.React.Elements.Div(void 0,void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.H(4,"font-semibold",System.Array.init([Dashboard.React.Elements.Text("Connection Warning")],Object)),Dashboard.React.Elements.P("text-sm text-gray-600",void 0,System.Array.init([Dashboard.React.Elements.Text("Could not connect to API: "+(message||""))],Object)),Dashboard.React.Elements.P("text-sm text-gray-500",void 0,System.Array.init([Dashboard.React.Elements.Text("Make sure Clinical API (port 5000) and Scheduling API (port 5001) are running.")],Object))],Object))],Object))],Object))},RenderQuickActions:function(){return Dashboard.React.Elements.Div("card",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Div("card-header",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.H(3,"card-title",System.Array.init([Dashboard.React.Elements.Text("Quick Actions")],Object))],Object)),Dashboard.React.Elements.Div("card-body",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Div("grid grid-cols-2 gap-4",void 0,void 0,void 0,System.Array.init([Dashboard.Pages.DashboardPage.RenderActionButton("New Patient",Dashboard.Components.Icons.Plus,"primary"),Dashboard.Pages.DashboardPage.RenderActionButton("New Appointment",Dashboard.Components.Icons.Calendar,"secondary"),Dashboard.Pages.DashboardPage.RenderActionButton("View Schedule",Dashboard.Components.Icons.Calendar,"secondary"),Dashboard.Pages.DashboardPage.RenderActionButton("Patient Search",Dashboard.Components.Icons.Search,"secondary")],Object))],Object))],Object))},RenderActionButton:function(label,icon,variant){return Dashboard.React.Elements.Button("btn btn-"+(variant||"")+" w-full",void 0,!1,"button",System.Array.init([icon(),Dashboard.React.Elements.Text(label)],Object))},RenderRecentActivity:function(){return Dashboard.React.Elements.Div("card",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Div("card-header",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.H(3,"card-title",System.Array.init([Dashboard.React.Elements.Text("Recent Activity")],Object)),Dashboard.React.Elements.Button("btn btn-ghost btn-sm",void 0,!1,"button",System.Array.init([Dashboard.React.Elements.Text("View All")],Object))],Object)),Dashboard.React.Elements.Div("card-body",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Div("data-list",void 0,void 0,void 0,System.Array.init([Dashboard.Pages.DashboardPage.RenderActivityItem("New patient registered","John Smith added to system","2 min ago"),Dashboard.Pages.DashboardPage.RenderActivityItem("Appointment completed","Dr. Wilson with Jane Doe","15 min ago"),Dashboard.Pages.DashboardPage.RenderActivityItem("Lab results available","Patient ID: PAT-0042","1 hour ago")],Object))],Object))],Object))},RenderActivityItem:function(title,subtitle,time){return Dashboard.React.Elements.Div("data-list-item",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Div("avatar avatar-sm",void 0,void 0,void 0,System.Array.init([Dashboard.Components.Icons.Activity()],Object)),Dashboard.React.Elements.Div("data-list-item-content",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Div("data-list-item-title",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Text(title)],Object)),Dashboard.React.Elements.Div("data-list-item-subtitle",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Text(subtitle)],Object))],Object)),Dashboard.React.Elements.Div("data-list-item-meta",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Text(time)],Object))],Object))}}}});H5.define("Dashboard.Pages.DashboardState",{fields:{PatientCount:0,PractitionerCount:0,AppointmentCount:0,EncounterCount:0,Loading:!1,Error:null}});H5.define("Dashboard.Pages.EditAppointmentPage",{statics:{methods:{Render:function(appointmentId,onBack){var $t,stateResult=Dashboard.React.Hooks.UseState(Dashboard.Pages.EditAppointmentState,($t=new Dashboard.Pages.EditAppointmentState,$t.Appointment=null,$t.Loading=!0,$t.Saving=!1,$t.Error=null,$t.Success=null,$t.ServiceCategory="",$t.ServiceType="",$t.ReasonCode="",$t.Priority="routine",$t.Description="",$t.StartDate="",$t.StartTime="",$t.EndDate="",$t.EndTime="",$t.PatientReference="",$t.PractitionerReference="",$t.Comment="",$t.Status="booked",$t)),state=stateResult.State,setState=stateResult.SetState;return(Dashboard.React.Hooks.UseEffect$1(function(){Dashboard.Pages.EditAppointmentPage.LoadAppointment(appointmentId,setState)},System.Array.init([appointmentId],System.Object)),state.Loading)?Dashboard.Pages.EditAppointmentPage.RenderLoadingState():state.Error!=null&&state.Appointment==null?Dashboard.Pages.EditAppointmentPage.RenderErrorState(state.Error,onBack):Dashboard.React.Elements.Div("page",void 0,void 0,void 0,System.Array.init([Dashboard.Pages.EditAppointmentPage.RenderHeader(state.Appointment,onBack),Dashboard.Pages.EditAppointmentPage.RenderForm(state,setState,onBack)],Object))},LoadAppointment:function(appointmentId,setState){(async()=>{var $t,$t1,$t2,$t3,$t4,$t5,$t6,$t7,$t8,$t9;try{var appointment=await H5.toPromise(Dashboard.Api.ApiClient.GetAppointmentAsync(appointmentId)),startParts=Dashboard.Pages.EditAppointmentPage.ParseDateTime(appointment.StartTime),endParts=Dashboard.Pages.EditAppointmentPage.ParseDateTime(appointment.EndTime);setState(($t=new Dashboard.Pages.EditAppointmentState,$t.Appointment=appointment,$t.Loading=!1,$t.Saving=!1,$t.Error=null,$t.Success=null,$t.ServiceCategory=($t1=appointment.ServiceCategory,$t1!=null?$t1:""),$t.ServiceType=($t2=appointment.ServiceType,$t2!=null?$t2:""),$t.ReasonCode=($t3=appointment.ReasonCode,$t3!=null?$t3:""),$t.Priority=($t4=appointment.Priority,$t4!=null?$t4:"routine"),$t.Description=($t5=appointment.Description,$t5!=null?$t5:""),$t.StartDate=startParts.Item1,$t.StartTime=startParts.Item2,$t.EndDate=endParts.Item1,$t.EndTime=endParts.Item2,$t.PatientReference=($t6=appointment.PatientReference,$t6!=null?$t6:""),$t.PractitionerReference=($t7=appointment.PractitionerReference,$t7!=null?$t7:""),$t.Comment=($t8=appointment.Comment,$t8!=null?$t8:""),$t.Status=($t9=appointment.Status,$t9!=null?$t9:"booked"),$t))}catch(ex){ex=System.Exception.create(ex);setState(($t=new Dashboard.Pages.EditAppointmentState,$t.Appointment=null,$t.Loading=!1,$t.Saving=!1,$t.Error=ex.Message,$t.Success=null,$t.ServiceCategory="",$t.ServiceType="",$t.ReasonCode="",$t.Priority="routine",$t.Description="",$t.StartDate="",$t.StartTime="",$t.EndDate="",$t.EndTime="",$t.PatientReference="",$t.PractitionerReference="",$t.Comment="",$t.Status="booked",$t))}})()},ParseDateTime:function(isoDateTime){if(System.String.isNullOrEmpty(isoDateTime))return new(System.ValueTuple$2(System.String,System.String).$ctor1)("","");if(isoDateTime.length>=16){var datePart=isoDateTime.substr(0,10),timePart=isoDateTime.substr(11,5);return new(System.ValueTuple$2(System.String,System.String).$ctor1)(datePart,timePart)}return new(System.ValueTuple$2(System.String,System.String).$ctor1)("","")},CombineDateTime:function(date,time){return System.String.isNullOrEmpty(date)||System.String.isNullOrEmpty(time)?"":(date||"")+"T"+(time||"")+":00.000Z"},SaveAppointment:function(state,setState,onBack){(async()=>{var $t,$t1,$t2,$t3,$t4,$t5,$t6,$t7,$t8,$t9;setState(($t=new Dashboard.Pages.EditAppointmentState,$t.Appointment=state.Appointment,$t.Loading=!1,$t.Saving=!0,$t.Error=null,$t.Success=null,$t.ServiceCategory=state.ServiceCategory,$t.ServiceType=state.ServiceType,$t.ReasonCode=state.ReasonCode,$t.Priority=state.Priority,$t.Description=state.Description,$t.StartDate=state.StartDate,$t.StartTime=state.StartTime,$t.EndDate=state.EndDate,$t.EndTime=state.EndTime,$t.PatientReference=state.PatientReference,$t.PractitionerReference=state.PractitionerReference,$t.Comment=state.Comment,$t.Status=state.Status,$t));try{var updateData={ServiceCategory:state.ServiceCategory,ServiceType:state.ServiceType,ReasonCode:System.String.isNullOrWhiteSpace(state.ReasonCode)?null:state.ReasonCode,Priority:state.Priority,Description:System.String.isNullOrWhiteSpace(state.Description)?null:state.Description,Start:Dashboard.Pages.EditAppointmentPage.CombineDateTime(state.StartDate,state.StartTime),End:Dashboard.Pages.EditAppointmentPage.CombineDateTime(state.EndDate,state.EndTime),PatientReference:state.PatientReference,PractitionerReference:state.PractitionerReference,Comment:System.String.isNullOrWhiteSpace(state.Comment)?null:state.Comment,Status:state.Status},updatedAppointment=await H5.toPromise(Dashboard.Api.ApiClient.UpdateAppointmentAsync(state.Appointment.Id,updateData)),startParts=Dashboard.Pages.EditAppointmentPage.ParseDateTime(updatedAppointment.StartTime),endParts=Dashboard.Pages.EditAppointmentPage.ParseDateTime(updatedAppointment.EndTime);setState(($t=new Dashboard.Pages.EditAppointmentState,$t.Appointment=updatedAppointment,$t.Loading=!1,$t.Saving=!1,$t.Error=null,$t.Success="Appointment updated successfully!",$t.ServiceCategory=($t1=updatedAppointment.ServiceCategory,$t1!=null?$t1:""),$t.ServiceType=($t2=updatedAppointment.ServiceType,$t2!=null?$t2:""),$t.ReasonCode=($t3=updatedAppointment.ReasonCode,$t3!=null?$t3:""),$t.Priority=($t4=updatedAppointment.Priority,$t4!=null?$t4:"routine"),$t.Description=($t5=updatedAppointment.Description,$t5!=null?$t5:""),$t.StartDate=startParts.Item1,$t.StartTime=startParts.Item2,$t.EndDate=endParts.Item1,$t.EndTime=endParts.Item2,$t.PatientReference=($t6=updatedAppointment.PatientReference,$t6!=null?$t6:""),$t.PractitionerReference=($t7=updatedAppointment.PractitionerReference,$t7!=null?$t7:""),$t.Comment=($t8=updatedAppointment.Comment,$t8!=null?$t8:""),$t.Status=($t9=updatedAppointment.Status,$t9!=null?$t9:"booked"),$t))}catch(ex){ex=System.Exception.create(ex);setState(($t=new Dashboard.Pages.EditAppointmentState,$t.Appointment=state.Appointment,$t.Loading=!1,$t.Saving=!1,$t.Error=ex.Message,$t.Success=null,$t.ServiceCategory=state.ServiceCategory,$t.ServiceType=state.ServiceType,$t.ReasonCode=state.ReasonCode,$t.Priority=state.Priority,$t.Description=state.Description,$t.StartDate=state.StartDate,$t.StartTime=state.StartTime,$t.EndDate=state.EndDate,$t.EndTime=state.EndTime,$t.PatientReference=state.PatientReference,$t.PractitionerReference=state.PractitionerReference,$t.Comment=state.Comment,$t.Status=state.Status,$t))}})()},RenderLoadingState:function(){return Dashboard.React.Elements.Div("page",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Div("page-header",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.H(2,"page-title",System.Array.init([Dashboard.React.Elements.Text("Edit Appointment")],Object)),Dashboard.React.Elements.P("page-description",void 0,System.Array.init([Dashboard.React.Elements.Text("Loading appointment data...")],Object))],Object)),Dashboard.React.Elements.Div("card",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Div("flex items-center justify-center p-8",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Text("Loading...")],Object))],Object))],Object))},RenderErrorState:function(error,onBack){return Dashboard.React.Elements.Div("page",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Div("page-header flex justify-between items-center",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Div(void 0,void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.H(2,"page-title",System.Array.init([Dashboard.React.Elements.Text("Edit Appointment")],Object)),Dashboard.React.Elements.P("page-description",void 0,System.Array.init([Dashboard.React.Elements.Text("Error loading appointment")],Object))],Object)),Dashboard.React.Elements.Button("btn btn-secondary",onBack,!1,"button",System.Array.init([Dashboard.Components.Icons.ChevronLeft(),Dashboard.React.Elements.Text("Back to Appointments")],Object))],Object)),Dashboard.React.Elements.Div("card",void 0,{borderLeft:"4px solid var(--error)"},void 0,System.Array.init([Dashboard.React.Elements.Div("flex items-center gap-3 p-4",void 0,void 0,void 0,System.Array.init([Dashboard.Components.Icons.X(),Dashboard.React.Elements.Text("Error loading appointment: "+(error||""))],Object))],Object))],Object))},RenderHeader:function(appointment,onBack){var $t,title=($t=appointment.ServiceType,$t!=null?$t:"Appointment");return Dashboard.React.Elements.Div("page-header flex justify-between items-center",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Div(void 0,void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.H(2,"page-title",System.Array.init([Dashboard.React.Elements.Text("Edit Appointment")],Object)),Dashboard.React.Elements.P("page-description",void 0,System.Array.init([Dashboard.React.Elements.Text("Update details for "+(title||""))],Object))],Object)),Dashboard.React.Elements.Button("btn btn-secondary",onBack,!1,"button",System.Array.init([Dashboard.Components.Icons.ChevronLeft(),Dashboard.React.Elements.Text("Back to Appointments")],Object))],Object))},RenderForm:function(state,setState,onBack){return Dashboard.React.Elements.Div("card",void 0,void 0,void 0,System.Array.init([state.Error!=null?Dashboard.React.Elements.Div("alert alert-error mb-4",void 0,void 0,void 0,System.Array.init([Dashboard.Components.Icons.X(),Dashboard.React.Elements.Text(state.Error)],Object)):null,state.Success!=null?Dashboard.React.Elements.Div("alert alert-success mb-4",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Text(state.Success)],Object)):null,Dashboard.React.Elements.Form("form",function(){Dashboard.Pages.EditAppointmentPage.SaveAppointment(state,setState,onBack)},System.Array.init([Dashboard.Pages.EditAppointmentPage.RenderFormSection("Appointment Details",System.Array.init([Dashboard.Pages.EditAppointmentPage.RenderInputField("Service Category","appointment-service-category",state.ServiceCategory,"e.g., General Practice",function(v){Dashboard.Pages.EditAppointmentPage.UpdateField(state,setState,"ServiceCategory",v)}),Dashboard.Pages.EditAppointmentPage.RenderInputField("Service Type","appointment-service-type",state.ServiceType,"e.g., Checkup, Follow-up",function(v){Dashboard.Pages.EditAppointmentPage.UpdateField(state,setState,"ServiceType",v)}),Dashboard.Pages.EditAppointmentPage.RenderInputField("Reason","appointment-reason",state.ReasonCode,"Reason for appointment",function(v){Dashboard.Pages.EditAppointmentPage.UpdateField(state,setState,"ReasonCode",v)}),Dashboard.Pages.EditAppointmentPage.RenderSelectField("Priority","appointment-priority",state.Priority,System.Array.init([new(System.ValueTuple$2(System.String,System.String).$ctor1)("routine","Routine"),new(System.ValueTuple$2(System.String,System.String).$ctor1)("urgent","Urgent"),new(System.ValueTuple$2(System.String,System.String).$ctor1)("asap","ASAP"),new(System.ValueTuple$2(System.String,System.String).$ctor1)("stat","STAT")],System.ValueTuple$2(System.String,System.String)),function(v){Dashboard.Pages.EditAppointmentPage.UpdateField(state,setState,"Priority",v)}),Dashboard.Pages.EditAppointmentPage.RenderSelectField("Status","appointment-status",state.Status,System.Array.init([new(System.ValueTuple$2(System.String,System.String).$ctor1)("booked","Booked"),new(System.ValueTuple$2(System.String,System.String).$ctor1)("arrived","Arrived"),new(System.ValueTuple$2(System.String,System.String).$ctor1)("fulfilled","Fulfilled"),new(System.ValueTuple$2(System.String,System.String).$ctor1)("cancelled","Cancelled"),new(System.ValueTuple$2(System.String,System.String).$ctor1)("noshow","No Show")],System.ValueTuple$2(System.String,System.String)),function(v){Dashboard.Pages.EditAppointmentPage.UpdateField(state,setState,"Status",v)}),Dashboard.Pages.EditAppointmentPage.RenderTextareaField("Description","appointment-description",state.Description,"Additional details",function(v){Dashboard.Pages.EditAppointmentPage.UpdateField(state,setState,"Description",v)})],Object)),Dashboard.Pages.EditAppointmentPage.RenderFormSection("Schedule",System.Array.init([Dashboard.Pages.EditAppointmentPage.RenderInputField("Start Date","appointment-start-date",state.StartDate,"YYYY-MM-DD",function(v){Dashboard.Pages.EditAppointmentPage.UpdateField(state,setState,"StartDate",v)},"date"),Dashboard.Pages.EditAppointmentPage.RenderInputField("Start Time","appointment-start-time",state.StartTime,"HH:MM",function(v){Dashboard.Pages.EditAppointmentPage.UpdateField(state,setState,"StartTime",v)},"time"),Dashboard.Pages.EditAppointmentPage.RenderInputField("End Date","appointment-end-date",state.EndDate,"YYYY-MM-DD",function(v){Dashboard.Pages.EditAppointmentPage.UpdateField(state,setState,"EndDate",v)},"date"),Dashboard.Pages.EditAppointmentPage.RenderInputField("End Time","appointment-end-time",state.EndTime,"HH:MM",function(v){Dashboard.Pages.EditAppointmentPage.UpdateField(state,setState,"EndTime",v)},"time")],Object)),Dashboard.Pages.EditAppointmentPage.RenderFormSection("Participants",System.Array.init([Dashboard.Pages.EditAppointmentPage.RenderInputField("Patient Reference","appointment-patient",state.PatientReference,"Patient/[id]",function(v){Dashboard.Pages.EditAppointmentPage.UpdateField(state,setState,"PatientReference",v)}),Dashboard.Pages.EditAppointmentPage.RenderInputField("Practitioner Reference","appointment-practitioner",state.PractitionerReference,"Practitioner/[id]",function(v){Dashboard.Pages.EditAppointmentPage.UpdateField(state,setState,"PractitionerReference",v)})],Object)),Dashboard.Pages.EditAppointmentPage.RenderFormSection("Notes",System.Array.init([Dashboard.Pages.EditAppointmentPage.RenderTextareaField("Comment","appointment-comment",state.Comment,"Any additional comments",function(v){Dashboard.Pages.EditAppointmentPage.UpdateField(state,setState,"Comment",v)})],Object)),Dashboard.Pages.EditAppointmentPage.RenderFormActions(state,onBack)],Object))],Object))},RenderFormSection:function(title,fields){return Dashboard.React.Elements.Div("form-section mb-6",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.H(4,"form-section-title mb-4",System.Array.init([Dashboard.React.Elements.Text(title)],Object)),Dashboard.React.Elements.Div("grid grid-cols-2 gap-4",void 0,void 0,void 0,fields)],Object))},RenderInputField:function(label,id,value,placeholder,onChange,type){return type===void 0&&(type="text"),Dashboard.React.Elements.Div("form-group",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Label(id,"form-label",System.Array.init([Dashboard.React.Elements.Text(label)],Object)),Dashboard.React.Elements.Input("input",type,value,placeholder,onChange,void 0,!1)],Object))},RenderTextareaField:function(label,id,value,placeholder,onChange){return Dashboard.React.Elements.Div("form-group col-span-2",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Label(id,"form-label",System.Array.init([Dashboard.React.Elements.Text(label)],Object)),Dashboard.React.Elements.TextArea("input",value,placeholder,3,onChange)],Object))},RenderSelectField:function(label,id,value,options,onChange){for(var optionElements=System.Array.init(options.length,null,Object),i=0;i{var $t,$t1,$t2,$t3,$t4,$t5,$t6,$t7,$t8,$t9,$t10,$t11,patient;try{patient=await H5.toPromise(Dashboard.Api.ApiClient.GetPatientAsync(patientId));setState(($t=new Dashboard.Pages.EditPatientState,$t.Patient=patient,$t.Loading=!1,$t.Saving=!1,$t.Error=null,$t.Success=null,$t.Active=patient.Active,$t.GivenName=($t1=patient.GivenName,$t1!=null?$t1:""),$t.FamilyName=($t2=patient.FamilyName,$t2!=null?$t2:""),$t.BirthDate=($t3=patient.BirthDate,$t3!=null?$t3:""),$t.Gender=($t4=patient.Gender,$t4!=null?$t4:""),$t.Phone=($t5=patient.Phone,$t5!=null?$t5:""),$t.Email=($t6=patient.Email,$t6!=null?$t6:""),$t.AddressLine=($t7=patient.AddressLine,$t7!=null?$t7:""),$t.City=($t8=patient.City,$t8!=null?$t8:""),$t.State=($t9=patient.State,$t9!=null?$t9:""),$t.PostalCode=($t10=patient.PostalCode,$t10!=null?$t10:""),$t.Country=($t11=patient.Country,$t11!=null?$t11:""),$t))}catch(ex){ex=System.Exception.create(ex);setState(($t=new Dashboard.Pages.EditPatientState,$t.Patient=null,$t.Loading=!1,$t.Saving=!1,$t.Error=ex.Message,$t.Success=null,$t.Active=!0,$t.GivenName="",$t.FamilyName="",$t.BirthDate="",$t.Gender="",$t.Phone="",$t.Email="",$t.AddressLine="",$t.City="",$t.State="",$t.PostalCode="",$t.Country="",$t))}})()},SavePatient:function(state,setState,onBack){(async()=>{var $t,$t1,$t2,$t3,$t4,$t5,$t6,$t7,$t8,$t9,$t10,$t11,updateData,updatedPatient;setState(($t=new Dashboard.Pages.EditPatientState,$t.Patient=state.Patient,$t.Loading=!1,$t.Saving=!0,$t.Error=null,$t.Success=null,$t.Active=state.Active,$t.GivenName=state.GivenName,$t.FamilyName=state.FamilyName,$t.BirthDate=state.BirthDate,$t.Gender=state.Gender,$t.Phone=state.Phone,$t.Email=state.Email,$t.AddressLine=state.AddressLine,$t.City=state.City,$t.State=state.State,$t.PostalCode=state.PostalCode,$t.Country=state.Country,$t));try{updateData=($t={},$t.Id=state.Patient.Id,$t.Active=state.Active,$t.GivenName=state.GivenName,$t.FamilyName=state.FamilyName,$t.BirthDate=System.String.isNullOrWhiteSpace(state.BirthDate)?null:state.BirthDate,$t.Gender=System.String.isNullOrWhiteSpace(state.Gender)?null:state.Gender,$t.Phone=System.String.isNullOrWhiteSpace(state.Phone)?null:state.Phone,$t.Email=System.String.isNullOrWhiteSpace(state.Email)?null:state.Email,$t.AddressLine=System.String.isNullOrWhiteSpace(state.AddressLine)?null:state.AddressLine,$t.City=System.String.isNullOrWhiteSpace(state.City)?null:state.City,$t.State=System.String.isNullOrWhiteSpace(state.State)?null:state.State,$t.PostalCode=System.String.isNullOrWhiteSpace(state.PostalCode)?null:state.PostalCode,$t.Country=System.String.isNullOrWhiteSpace(state.Country)?null:state.Country,$t);updatedPatient=await H5.toPromise(Dashboard.Api.ApiClient.UpdatePatientAsync(state.Patient.Id,updateData));setState(($t=new Dashboard.Pages.EditPatientState,$t.Patient=updatedPatient,$t.Loading=!1,$t.Saving=!1,$t.Error=null,$t.Success="Patient updated successfully!",$t.Active=updatedPatient.Active,$t.GivenName=($t1=updatedPatient.GivenName,$t1!=null?$t1:""),$t.FamilyName=($t2=updatedPatient.FamilyName,$t2!=null?$t2:""),$t.BirthDate=($t3=updatedPatient.BirthDate,$t3!=null?$t3:""),$t.Gender=($t4=updatedPatient.Gender,$t4!=null?$t4:""),$t.Phone=($t5=updatedPatient.Phone,$t5!=null?$t5:""),$t.Email=($t6=updatedPatient.Email,$t6!=null?$t6:""),$t.AddressLine=($t7=updatedPatient.AddressLine,$t7!=null?$t7:""),$t.City=($t8=updatedPatient.City,$t8!=null?$t8:""),$t.State=($t9=updatedPatient.State,$t9!=null?$t9:""),$t.PostalCode=($t10=updatedPatient.PostalCode,$t10!=null?$t10:""),$t.Country=($t11=updatedPatient.Country,$t11!=null?$t11:""),$t))}catch(ex){ex=System.Exception.create(ex);setState(($t=new Dashboard.Pages.EditPatientState,$t.Patient=state.Patient,$t.Loading=!1,$t.Saving=!1,$t.Error=ex.Message,$t.Success=null,$t.Active=state.Active,$t.GivenName=state.GivenName,$t.FamilyName=state.FamilyName,$t.BirthDate=state.BirthDate,$t.Gender=state.Gender,$t.Phone=state.Phone,$t.Email=state.Email,$t.AddressLine=state.AddressLine,$t.City=state.City,$t.State=state.State,$t.PostalCode=state.PostalCode,$t.Country=state.Country,$t))}})()},RenderLoadingState:function(){return Dashboard.React.Elements.Div("page",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Div("page-header",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.H(2,"page-title",System.Array.init([Dashboard.React.Elements.Text("Edit Patient")],Object)),Dashboard.React.Elements.P("page-description",void 0,System.Array.init([Dashboard.React.Elements.Text("Loading patient data...")],Object))],Object)),Dashboard.React.Elements.Div("card",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Div("flex items-center justify-center p-8",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Text("Loading...")],Object))],Object))],Object))},RenderErrorState:function(error,onBack){return Dashboard.React.Elements.Div("page",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Div("page-header flex justify-between items-center",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Div(void 0,void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.H(2,"page-title",System.Array.init([Dashboard.React.Elements.Text("Edit Patient")],Object)),Dashboard.React.Elements.P("page-description",void 0,System.Array.init([Dashboard.React.Elements.Text("Error loading patient")],Object))],Object)),Dashboard.React.Elements.Button("btn btn-secondary",onBack,!1,"button",System.Array.init([Dashboard.Components.Icons.ChevronLeft(),Dashboard.React.Elements.Text("Back to Patients")],Object))],Object)),Dashboard.React.Elements.Div("card",void 0,{borderLeft:"4px solid var(--error)"},void 0,System.Array.init([Dashboard.React.Elements.Div("flex items-center gap-3 p-4",void 0,void 0,void 0,System.Array.init([Dashboard.Components.Icons.X(),Dashboard.React.Elements.Text("Error loading patient: "+(error||""))],Object))],Object))],Object))},RenderHeader:function(patient,onBack){var fullName=(patient.GivenName||"")+" "+(patient.FamilyName||"");return Dashboard.React.Elements.Div("page-header flex justify-between items-center",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Div(void 0,void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.H(2,"page-title",System.Array.init([Dashboard.React.Elements.Text("Edit Patient")],Object)),Dashboard.React.Elements.P("page-description",void 0,System.Array.init([Dashboard.React.Elements.Text("Update information for "+(fullName||""))],Object))],Object)),Dashboard.React.Elements.Button("btn btn-secondary",onBack,!1,"button",System.Array.init([Dashboard.Components.Icons.ChevronLeft(),Dashboard.React.Elements.Text("Back to Patients")],Object))],Object))},RenderForm:function(state,setState,onBack){return Dashboard.React.Elements.Div("card",void 0,void 0,void 0,System.Array.init([state.Error!=null?Dashboard.React.Elements.Div("alert alert-error mb-4",void 0,void 0,void 0,System.Array.init([Dashboard.Components.Icons.X(),Dashboard.React.Elements.Text(state.Error)],Object)):null,state.Success!=null?Dashboard.React.Elements.Div("alert alert-success mb-4",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Text(state.Success)],Object)):null,Dashboard.React.Elements.Form("form",function(){Dashboard.Pages.EditPatientPage.SavePatient(state,setState,onBack)},System.Array.init([Dashboard.Pages.EditPatientPage.RenderFormSection("Personal Information",System.Array.init([Dashboard.Pages.EditPatientPage.RenderInputField("Given Name","patient-edit-given-name",state.GivenName,"Enter first name",function(v){Dashboard.Pages.EditPatientPage.UpdateField(state,setState,"GivenName",v)}),Dashboard.Pages.EditPatientPage.RenderInputField("Family Name","patient-edit-family-name",state.FamilyName,"Enter last name",function(v){Dashboard.Pages.EditPatientPage.UpdateField(state,setState,"FamilyName",v)}),Dashboard.Pages.EditPatientPage.RenderInputField("Birth Date","patient-edit-birth-date",state.BirthDate,"YYYY-MM-DD",function(v){Dashboard.Pages.EditPatientPage.UpdateField(state,setState,"BirthDate",v)},"date"),Dashboard.Pages.EditPatientPage.RenderSelectField("Gender","patient-edit-gender",state.Gender,System.Array.init([new(System.ValueTuple$2(System.String,System.String).$ctor1)("","Select gender"),new(System.ValueTuple$2(System.String,System.String).$ctor1)("male","Male"),new(System.ValueTuple$2(System.String,System.String).$ctor1)("female","Female"),new(System.ValueTuple$2(System.String,System.String).$ctor1)("other","Other"),new(System.ValueTuple$2(System.String,System.String).$ctor1)("unknown","Unknown")],System.ValueTuple$2(System.String,System.String)),function(v){Dashboard.Pages.EditPatientPage.UpdateField(state,setState,"Gender",v)}),Dashboard.Pages.EditPatientPage.RenderCheckboxField("Active","patient-edit-active",state.Active,function(v){Dashboard.Pages.EditPatientPage.UpdateActive(state,setState,v)})],Object)),Dashboard.Pages.EditPatientPage.RenderFormSection("Contact Information",System.Array.init([Dashboard.Pages.EditPatientPage.RenderInputField("Phone","patient-edit-phone",state.Phone,"Enter phone number",function(v){Dashboard.Pages.EditPatientPage.UpdateField(state,setState,"Phone",v)},"tel"),Dashboard.Pages.EditPatientPage.RenderInputField("Email","patient-edit-email",state.Email,"Enter email address",function(v){Dashboard.Pages.EditPatientPage.UpdateField(state,setState,"Email",v)},"email")],Object)),Dashboard.Pages.EditPatientPage.RenderFormSection("Address",System.Array.init([Dashboard.Pages.EditPatientPage.RenderInputField("Address Line","patient-edit-address",state.AddressLine,"Enter street address",function(v){Dashboard.Pages.EditPatientPage.UpdateField(state,setState,"AddressLine",v)}),Dashboard.Pages.EditPatientPage.RenderInputField("City","patient-edit-city",state.City,"Enter city",function(v){Dashboard.Pages.EditPatientPage.UpdateField(state,setState,"City",v)}),Dashboard.Pages.EditPatientPage.RenderInputField("State","patient-edit-state",state.State,"Enter state/province",function(v){Dashboard.Pages.EditPatientPage.UpdateField(state,setState,"State",v)}),Dashboard.Pages.EditPatientPage.RenderInputField("Postal Code","patient-edit-postal-code",state.PostalCode,"Enter postal code",function(v){Dashboard.Pages.EditPatientPage.UpdateField(state,setState,"PostalCode",v)}),Dashboard.Pages.EditPatientPage.RenderInputField("Country","patient-edit-country",state.Country,"Enter country",function(v){Dashboard.Pages.EditPatientPage.UpdateField(state,setState,"Country",v)})],Object)),Dashboard.Pages.EditPatientPage.RenderFormActions(state,onBack)],Object))],Object))},RenderFormSection:function(title,fields){return Dashboard.React.Elements.Div("form-section mb-6",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.H(4,"form-section-title mb-4",System.Array.init([Dashboard.React.Elements.Text(title)],Object)),Dashboard.React.Elements.Div("grid grid-cols-2 gap-4",void 0,void 0,void 0,fields)],Object))},RenderInputField:function(label,id,value,placeholder,onChange,type){return type===void 0&&(type="text"),Dashboard.React.Elements.Div("form-group",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Label(id,"form-label",System.Array.init([Dashboard.React.Elements.Text(label)],Object)),Dashboard.React.Elements.Input("input",type,value,placeholder,onChange,void 0,!1)],Object))},RenderSelectField:function(label,id,value,options,onChange){for(var optionElements=System.Array.init(options.length,null,Object),i=0;i{var $t,patients;try{patients=await H5.toPromise(Dashboard.Api.ApiClient.GetPatientsAsync());setState(($t=new Dashboard.Pages.PatientsState,$t.Patients=patients,$t.Loading=!1,$t.Error=null,$t.SearchQuery="",$t.SelectedPatient=null,$t))}catch(ex){ex=System.Exception.create(ex);setState(($t=new Dashboard.Pages.PatientsState,$t.Patients=System.Array.init(0,null,Object),$t.Loading=!1,$t.Error=ex.Message,$t.SearchQuery="",$t.SelectedPatient=null,$t))}})()},HandleSearch:function(query,setState){(async()=>{var $t,patients;if(System.String.isNullOrWhiteSpace(query)){Dashboard.Pages.PatientsPage.LoadPatients(setState);return}try{patients=await H5.toPromise(Dashboard.Api.ApiClient.SearchPatientsAsync(query));setState(($t=new Dashboard.Pages.PatientsState,$t.Patients=patients,$t.Loading=!1,$t.Error=null,$t.SearchQuery=query,$t.SelectedPatient=null,$t))}catch(ex){ex=System.Exception.create(ex);setState(($t=new Dashboard.Pages.PatientsState,$t.Patients=System.Array.init(0,null,Object),$t.Loading=!1,$t.Error=ex.Message,$t.SearchQuery=query,$t.SelectedPatient=null,$t))}})()},SelectPatient:function(patient,setState){},RenderError:function(message){return Dashboard.React.Elements.Div("card",void 0,{borderLeft:"4px solid var(--error)"},void 0,System.Array.init([Dashboard.React.Elements.Div("flex items-center gap-3 p-4",void 0,void 0,void 0,System.Array.init([Dashboard.Components.Icons.X(),Dashboard.React.Elements.Text("Error loading patients: "+(message||""))],Object))],Object))},RenderPatientTable:function(patients,onSelect){var $t,columns=System.Array.init([($t=new Dashboard.Components.Column,$t.Key="name",$t.Header="Name",$t),($t=new Dashboard.Components.Column,$t.Key="gender",$t.Header="Gender",$t),($t=new Dashboard.Components.Column,$t.Key="birthDate",$t.Header="Birth Date",$t),($t=new Dashboard.Components.Column,$t.Key="contact",$t.Header="Contact",$t),($t=new Dashboard.Components.Column,$t.Key="status",$t.Header="Status",$t),($t=new Dashboard.Components.Column,$t.Key="actions",$t.Header="Actions",$t.ClassName="text-right",$t)],Dashboard.Components.Column);return Dashboard.Components.DataTable.Render(Object,columns,patients,function(p){return p.Id},function(patient,key){return Dashboard.Pages.PatientsPage.RenderCell(patient,key,onSelect)},onSelect)},RenderCell:function(patient,key,onSelect){var $t;return H5.referenceEquals(key,"name")?Dashboard.Pages.PatientsPage.RenderPatientName(patient):H5.referenceEquals(key,"gender")?Dashboard.Pages.PatientsPage.RenderGender(patient.Gender):H5.referenceEquals(key,"birthDate")?Dashboard.React.Elements.Text(($t=patient.BirthDate,$t!=null?$t:"N/A")):H5.referenceEquals(key,"contact")?Dashboard.Pages.PatientsPage.RenderContact(patient):H5.referenceEquals(key,"status")?Dashboard.Pages.PatientsPage.RenderStatus(patient.Active):H5.referenceEquals(key,"actions")?Dashboard.Pages.PatientsPage.RenderActions(patient,onSelect):Dashboard.React.Elements.Text("")},RenderPatientName:function(patient){var idPrefix=patient.Id.length>8?patient.Id.substr(0,8):patient.Id;return Dashboard.React.Elements.Div("flex items-center gap-3",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Div("avatar avatar-sm",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Text(Dashboard.Pages.PatientsPage.GetInitials(patient))],Object)),Dashboard.React.Elements.Div(void 0,void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Div("font-medium",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Text((patient.GivenName||"")+" "+(patient.FamilyName||""))],Object)),Dashboard.React.Elements.Div("text-sm text-gray-500",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Text("ID: "+(idPrefix||"")+"...")],Object))],Object))],Object))},RenderGender:function(gender){var $t;return Dashboard.React.Elements.Span("badge "+(Dashboard.Pages.PatientsPage.GenderBadgeClass(gender)||""),void 0,void 0,System.Array.init([Dashboard.React.Elements.Text(($t=gender,$t!=null?$t:"Unknown"))],Object))},GenderBadgeClass:function(gender){return H5.referenceEquals(gender,"male")?"badge-primary":H5.referenceEquals(gender,"female")?"badge-teal":"badge-gray"},RenderContact:function(patient){var $t,$t1,contact=($t=patient.Email,$t!=null?$t:($t1=patient.Phone,$t1!=null?$t1:"No contact"));return Dashboard.React.Elements.Text(contact)},RenderStatus:function(active){return Dashboard.React.Elements.Div("flex items-center gap-2",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Span("status-dot "+((active?"active":"inactive")||""),void 0,void 0),Dashboard.React.Elements.Text(active?"Active":"Inactive")],Object))},RenderActions:function(patient,onSelect){return Dashboard.React.Elements.Div("table-action",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Button("btn btn-ghost btn-sm",function(){onSelect(patient)},!1,"button",System.Array.init([Dashboard.Components.Icons.Eye()],Object)),Dashboard.React.Elements.Button("btn btn-ghost btn-sm",function(){H5.staticEquals(Dashboard.Pages.PatientsPage._onEditPatient,null)?null:Dashboard.Pages.PatientsPage._onEditPatient(patient.Id)},!1,"button",System.Array.init([Dashboard.Components.Icons.Edit()],Object))],Object))},GetInitials:function(patient){return(Dashboard.Pages.PatientsPage.FirstChar(patient.GivenName)||"")+(Dashboard.Pages.PatientsPage.FirstChar(patient.FamilyName)||"")},FirstChar:function(s){return System.String.isNullOrEmpty(s)?"":s.substr(0,1).toUpperCase()}}}});H5.define("Dashboard.Pages.PatientsState",{fields:{Patients:null,Loading:!1,Error:null,SearchQuery:null,SelectedPatient:null}});H5.define("Dashboard.Pages.PractitionersPage",{statics:{methods:{Render:function(){var $t,stateResult=Dashboard.React.Hooks.UseState(Dashboard.Pages.PractitionersState,($t=new Dashboard.Pages.PractitionersState,$t.Practitioners=System.Array.init(0,null,Object),$t.Loading=!0,$t.Error=null,$t.SpecialtyFilter=null,$t)),state=stateResult.State,setState=stateResult.SetState,content;return Dashboard.React.Hooks.UseEffect$1(function(){Dashboard.Pages.PractitionersPage.LoadPractitioners(setState)},System.Array.init(0,null,System.Object)),content=state.Loading?Dashboard.Pages.PractitionersPage.RenderLoadingGrid():state.Error!=null?Dashboard.Pages.PractitionersPage.RenderError(state.Error):state.Practitioners.length===0?Dashboard.Pages.PractitionersPage.RenderEmpty():Dashboard.Pages.PractitionersPage.RenderPractitionerGrid(state.Practitioners),Dashboard.React.Elements.Div("page",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Div("page-header flex justify-between items-center",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Div(void 0,void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.H(2,"page-title",System.Array.init([Dashboard.React.Elements.Text("Practitioners")],Object)),Dashboard.React.Elements.P("page-description",void 0,System.Array.init([Dashboard.React.Elements.Text("Manage healthcare providers from the Scheduling domain")],Object))],Object)),Dashboard.React.Elements.Button("btn btn-primary",void 0,!1,"button",System.Array.init([Dashboard.Components.Icons.Plus(),Dashboard.React.Elements.Text("Add Practitioner")],Object))],Object)),Dashboard.React.Elements.Div("card mb-6",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Div("flex gap-4",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Div("input-group",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Label(void 0,"input-label",System.Array.init([Dashboard.React.Elements.Text("Filter by Specialty")],Object)),Dashboard.React.Elements.Select("input",($t=state.SpecialtyFilter,$t!=null?$t:""),function(specialty){Dashboard.Pages.PractitionersPage.FilterBySpecialty(specialty,setState)},System.Array.init([Dashboard.React.Elements.Option("","All Specialties"),Dashboard.React.Elements.Option("Cardiology","Cardiology"),Dashboard.React.Elements.Option("Dermatology","Dermatology"),Dashboard.React.Elements.Option("Family Medicine","Family Medicine"),Dashboard.React.Elements.Option("Internal Medicine","Internal Medicine"),Dashboard.React.Elements.Option("Neurology","Neurology"),Dashboard.React.Elements.Option("Oncology","Oncology"),Dashboard.React.Elements.Option("Pediatrics","Pediatrics"),Dashboard.React.Elements.Option("Psychiatry","Psychiatry"),Dashboard.React.Elements.Option("Surgery","Surgery")],Object))],Object)),Dashboard.React.Elements.Div("flex-1",void 0,void 0,void 0),Dashboard.React.Elements.Button("btn btn-secondary",function(){Dashboard.Pages.PractitionersPage.LoadPractitioners(setState)},!1,"button",System.Array.init([Dashboard.Components.Icons.Refresh(),Dashboard.React.Elements.Text("Refresh")],Object))],Object))],Object)),content],Object))},LoadPractitioners:function(setState){(async()=>{var $t,practitioners;try{practitioners=await H5.toPromise(Dashboard.Api.ApiClient.GetPractitionersAsync());setState(($t=new Dashboard.Pages.PractitionersState,$t.Practitioners=practitioners,$t.Loading=!1,$t.Error=null,$t.SpecialtyFilter=null,$t))}catch(ex){ex=System.Exception.create(ex);setState(($t=new Dashboard.Pages.PractitionersState,$t.Practitioners=System.Array.init(0,null,Object),$t.Loading=!1,$t.Error=ex.Message,$t.SpecialtyFilter=null,$t))}})()},FilterBySpecialty:function(specialty,setState){(async()=>{var $t,practitioners;if(System.String.isNullOrEmpty(specialty)){Dashboard.Pages.PractitionersPage.LoadPractitioners(setState);return}try{practitioners=await H5.toPromise(Dashboard.Api.ApiClient.SearchPractitionersAsync(specialty));setState(($t=new Dashboard.Pages.PractitionersState,$t.Practitioners=practitioners,$t.Loading=!1,$t.Error=null,$t.SpecialtyFilter=specialty,$t))}catch(ex){ex=System.Exception.create(ex);setState(($t=new Dashboard.Pages.PractitionersState,$t.Practitioners=System.Array.init(0,null,Object),$t.Loading=!1,$t.Error=ex.Message,$t.SpecialtyFilter=specialty,$t))}})()},RenderError:function(message){return Dashboard.React.Elements.Div("card",void 0,{borderLeft:"4px solid var(--error)"},void 0,System.Array.init([Dashboard.React.Elements.Div("flex items-center gap-3 p-4",void 0,void 0,void 0,System.Array.init([Dashboard.Components.Icons.X(),Dashboard.React.Elements.Text("Error loading practitioners: "+(message||""))],Object))],Object))},RenderEmpty:function(){return Dashboard.React.Elements.Div("card",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Div("empty-state",void 0,void 0,void 0,System.Array.init([Dashboard.Components.Icons.UserDoctor(),Dashboard.React.Elements.H(4,"empty-state-title",System.Array.init([Dashboard.React.Elements.Text("No Practitioners")],Object)),Dashboard.React.Elements.P("empty-state-description",void 0,System.Array.init([Dashboard.React.Elements.Text("No practitioners found. Add a new practitioner to get started.")],Object)),Dashboard.React.Elements.Button("btn btn-primary mt-4",void 0,!1,"button",System.Array.init([Dashboard.Components.Icons.Plus(),Dashboard.React.Elements.Text("Add Practitioner")],Object))],Object))],Object))},RenderLoadingGrid:function(){return Dashboard.React.Elements.Div("grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6",void 0,void 0,void 0,System.Linq.Enumerable.range(0,6).select(function(i){return Dashboard.React.Elements.Div("card",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Div("skeleton",void 0,{width:"80px",height:"80px",borderRadius:"50%"},void 0),Dashboard.React.Elements.Div("skeleton mt-4",void 0,{width:"60%",height:"20px"},void 0),Dashboard.React.Elements.Div("skeleton mt-2",void 0,{width:"40%",height:"16px"},void 0),Dashboard.React.Elements.Div("skeleton mt-4",void 0,{width:"100%",height:"16px"},void 0)],Object))}).ToArray(Object))},RenderPractitionerGrid:function(practitioners){return Dashboard.React.Elements.Div("grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6",void 0,void 0,void 0,System.Linq.Enumerable.from(practitioners,Object).select(Dashboard.Pages.PractitionersPage.RenderPractitionerCard).ToArray(Object))},RenderPractitionerCard:function(practitioner){var $t,$t1,$t2,$t3;return Dashboard.React.Elements.Div("card",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Div("flex items-start gap-4",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Div("avatar avatar-xl",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Text(Dashboard.Pages.PractitionersPage.GetInitials(practitioner))],Object)),Dashboard.React.Elements.Div("flex-1",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.H(4,"font-semibold",System.Array.init([Dashboard.React.Elements.Text("Dr. "+(practitioner.NameGiven||"")+" "+(practitioner.NameFamily||""))],Object)),Dashboard.React.Elements.Span("badge badge-teal mt-1",void 0,void 0,System.Array.init([Dashboard.React.Elements.Text(($t=practitioner.Specialty,$t!=null?$t:"General"))],Object)),Dashboard.React.Elements.Div("flex items-center gap-2 mt-2",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Span("status-dot "+((practitioner.Active?"active":"inactive")||""),void 0,void 0),Dashboard.React.Elements.Text(practitioner.Active?"Available":"Unavailable")],Object))],Object))],Object)),Dashboard.React.Elements.Div("mt-4 pt-4 border-t border-gray-200",void 0,void 0,void 0,System.Array.init([Dashboard.Pages.PractitionersPage.RenderDetail("ID",practitioner.Identifier),Dashboard.Pages.PractitionersPage.RenderDetail("Qualification",($t1=practitioner.Qualification,$t1!=null?$t1:"N/A")),Dashboard.Pages.PractitionersPage.RenderDetail("Email",($t2=practitioner.TelecomEmail,$t2!=null?$t2:"N/A")),Dashboard.Pages.PractitionersPage.RenderDetail("Phone",($t3=practitioner.TelecomPhone,$t3!=null?$t3:"N/A"))],Object)),Dashboard.React.Elements.Div("flex gap-2 mt-4",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Button("btn btn-primary btn-sm flex-1",void 0,!1,"button",System.Array.init([Dashboard.Components.Icons.Calendar(),Dashboard.React.Elements.Text("View Schedule")],Object)),Dashboard.React.Elements.Button("btn btn-secondary btn-sm",void 0,!1,"button",System.Array.init([Dashboard.Components.Icons.Edit()],Object))],Object))],Object))},RenderDetail:function(label,value){return Dashboard.React.Elements.Div("flex justify-between py-1",void 0,void 0,void 0,System.Array.init([Dashboard.React.Elements.Span("text-sm text-gray-500",void 0,void 0,System.Array.init([Dashboard.React.Elements.Text(label)],Object)),Dashboard.React.Elements.Span("text-sm font-medium",void 0,void 0,System.Array.init([Dashboard.React.Elements.Text(value)],Object))],Object))},GetInitials:function(p){return(Dashboard.Pages.PractitionersPage.FirstChar(p.NameGiven)||"")+(Dashboard.Pages.PractitionersPage.FirstChar(p.NameFamily)||"")},FirstChar:function(s){return System.String.isNullOrEmpty(s)?"":s.substr(0,1).toUpperCase()}}}});H5.define("Dashboard.Pages.PractitionersState",{fields:{Practitioners:null,Loading:!1,Error:null,SpecialtyFilter:null}});H5.define("Dashboard.Program",{main:function(){var clinicalUrl=Dashboard.Program.GetConfigValue("CLINICAL_API_URL","http://localhost:5080"),schedulingUrl=Dashboard.Program.GetConfigValue("SCHEDULING_API_URL","http://localhost:5001"),icd10Url,authToken;Dashboard.Api.ApiClient.Configure(clinicalUrl,schedulingUrl);icd10Url=Dashboard.Program.GetConfigValue("ICD10_API_URL","http://localhost:5090");Dashboard.Api.ApiClient.ConfigureIcd10(icd10Url);authToken=Dashboard.Program.GetConfigValue("AUTH_TOKEN","eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkYXNoYm9hcmQtdXNlciIsImp0aSI6IjE1MTMwYTg0LTY4NTktNGNmMy05MjA3LTMyMGJhYWRiNzhjNSIsInJvbGVzIjpbImNsaW5pY2lhbiIsInNjaGVkdWxlciJdLCJleHAiOjIwODE5MjIxMDQsImlhdCI6MTc2NjM4OTMwNH0.mk66XyKaLWukzZOmGNwss74lSlXobt6Em0NoEbXRdKU");Dashboard.Api.ApiClient.SetTokens(authToken,authToken);Dashboard.Program.Log("Healthcare Dashboard starting...");Dashboard.Program.Log("Clinical API: "+(clinicalUrl||""));Dashboard.Program.Log("Scheduling API: "+(schedulingUrl||""));Dashboard.Program.Log("ICD-10 API: "+(icd10Url||""));Dashboard.Program.HideLoadingScreen();Dashboard.React.ReactInterop.RenderApp(Dashboard.App.Render());Dashboard.Program.Log("Dashboard initialized successfully!")},statics:{methods:{GetConfigValue:function(key,defaultValue){var windowConfig=window.dashboardConfig,value;return windowConfig!=null&&(value=H5.unbox(windowConfig)[key],!System.String.isNullOrEmpty(value))?value:defaultValue},HideLoadingScreen:function(){var loadingScreen=document.getElementById("loading-screen");loadingScreen!=null&&loadingScreen.classList.add("hidden")},Log:function(message){console.log("[Dashboard] "+(message||""))}}}});H5.define("Dashboard.React.Elements",{statics:{methods:{Div:function(className,id,style,onClick,children){return className===void 0&&(className=null),id===void 0&&(id=null),style===void 0&&(style=null),onClick===void 0&&(onClick=null),children===void 0&&(children=[]),Dashboard.React.Elements.CreateElement("div",className,id,style,onClick,children)},Span:function(className,id,style,children){return className===void 0&&(className=null),id===void 0&&(id=null),style===void 0&&(style=null),children===void 0&&(children=[]),Dashboard.React.Elements.CreateElement("span",className,id,style,null,children)},P:function(className,style,children){return className===void 0&&(className=null),style===void 0&&(style=null),children===void 0&&(children=[]),Dashboard.React.Elements.CreateElement("p",className,null,style,null,children)},H:function(level,className,children){return className===void 0&&(className=null),children===void 0&&(children=[]),Dashboard.React.Elements.CreateElement("h"+level,className,null,null,null,children)},Button:function(className,onClick,disabled,type,children){var clickHandler,props;return className===void 0&&(className=null),onClick===void 0&&(onClick=null),disabled===void 0&&(disabled=!1),type===void 0&&(type="button"),children===void 0&&(children=[]),clickHandler=null,H5.staticEquals(onClick,null)||(clickHandler=function(e){e.stopPropagation();onClick()}),props={className:className,onClick:clickHandler,disabled:disabled,type:type},React.createElement("button",props,children)},Input:function(className,type,value,placeholder,onChange,onKeyDown,disabled){var changeHandler,keyDownHandler,props;return className===void 0&&(className=null),type===void 0&&(type="text"),value===void 0&&(value=null),placeholder===void 0&&(placeholder=null),onChange===void 0&&(onChange=null),onKeyDown===void 0&&(onKeyDown=null),disabled===void 0&&(disabled=!1),changeHandler=null,H5.staticEquals(onChange,null)||(changeHandler=function(e){onChange(H5.unbox(H5.unbox(e).target).value)}),keyDownHandler=null,H5.staticEquals(onKeyDown,null)||(keyDownHandler=function(e){onKeyDown(H5.unbox(e).key)}),props={className:className,type:type,value:value,placeholder:placeholder,onChange:changeHandler,onKeyDown:keyDownHandler,disabled:disabled},React.createElement("input",props)},Text:function(content){return React.createElement("span",null,content)},Img:function(src,alt,className,style){alt===void 0&&(alt=null);className===void 0&&(className=null);style===void 0&&(style=null);var props={src:src,alt:alt,className:className,style:style};return React.createElement("img",props)},A:function(href,className,target,onClick,children){var clickHandler,props;return className===void 0&&(className=null),target===void 0&&(target=null),onClick===void 0&&(onClick=null),children===void 0&&(children=[]),clickHandler=null,H5.staticEquals(onClick,null)||(clickHandler=function(e){e.preventDefault();onClick()}),props={href:href,className:className,target:target,onClick:clickHandler},React.createElement("a",props,children)},Nav:function(className,children){return className===void 0&&(className=null),children===void 0&&(children=[]),Dashboard.React.Elements.CreateElement("nav",className,null,null,null,children)},Header:function(className,children){return className===void 0&&(className=null),children===void 0&&(children=[]),Dashboard.React.Elements.CreateElement("header",className,null,null,null,children)},Main:function(className,children){return className===void 0&&(className=null),children===void 0&&(children=[]),Dashboard.React.Elements.CreateElement("main",className,null,null,null,children)},Aside:function(className,children){return className===void 0&&(className=null),children===void 0&&(children=[]),Dashboard.React.Elements.CreateElement("aside",className,null,null,null,children)},Section:function(className,children){return className===void 0&&(className=null),children===void 0&&(children=[]),Dashboard.React.Elements.CreateElement("section",className,null,null,null,children)},Article:function(className,children){return className===void 0&&(className=null),children===void 0&&(children=[]),Dashboard.React.Elements.CreateElement("article",className,null,null,null,children)},Footer:function(className,children){return className===void 0&&(className=null),children===void 0&&(children=[]),Dashboard.React.Elements.CreateElement("footer",className,null,null,null,children)},Table:function(className,children){return className===void 0&&(className=null),children===void 0&&(children=[]),Dashboard.React.Elements.CreateElement("table",className,null,null,null,children)},THead:function(children){return children===void 0&&(children=[]),React.createElement("thead",null,children)},TBody:function(children){return children===void 0&&(children=[]),React.createElement("tbody",null,children)},Tr:function(className,onClick,children){var clickHandler,props;return className===void 0&&(className=null),onClick===void 0&&(onClick=null),children===void 0&&(children=[]),clickHandler=null,H5.staticEquals(onClick,null)||(clickHandler=function(_){onClick()}),props={className:className,onClick:clickHandler},React.createElement("tr",props,children)},Th:function(className,children){return className===void 0&&(className=null),children===void 0&&(children=[]),Dashboard.React.Elements.CreateElement("th",className,null,null,null,children)},Td:function(className,children){return className===void 0&&(className=null),children===void 0&&(children=[]),Dashboard.React.Elements.CreateElement("td",className,null,null,null,children)},Ul:function(className,children){return className===void 0&&(className=null),children===void 0&&(children=[]),Dashboard.React.Elements.CreateElement("ul",className,null,null,null,children)},Li:function(className,onClick,children){return className===void 0&&(className=null),onClick===void 0&&(onClick=null),children===void 0&&(children=[]),Dashboard.React.Elements.CreateElement("li",className,null,null,onClick,children)},Form:function(className,onSubmit,children){var submitHandler,props;return className===void 0&&(className=null),onSubmit===void 0&&(onSubmit=null),children===void 0&&(children=[]),submitHandler=null,H5.staticEquals(onSubmit,null)||(submitHandler=function(e){e.preventDefault();onSubmit()}),props={className:className,onSubmit:submitHandler},React.createElement("form",props,children)},Label:function(htmlFor,className,children){htmlFor===void 0&&(htmlFor=null);className===void 0&&(className=null);children===void 0&&(children=[]);var props={htmlFor:htmlFor,className:className};return React.createElement("label",props,children)},Select:function(className,value,onChange,children){var changeHandler,props;return className===void 0&&(className=null),value===void 0&&(value=null),onChange===void 0&&(onChange=null),children===void 0&&(children=[]),changeHandler=null,H5.staticEquals(onChange,null)||(changeHandler=function(e){onChange(H5.unbox(H5.unbox(e).target).value)}),props={className:className,value:value,onChange:changeHandler},React.createElement("select",props,children)},Option:function(value,label){var props={value:value};return React.createElement("option",props,label)},TextArea:function(className,value,placeholder,rows,onChange){var changeHandler,props;return className===void 0&&(className=null),value===void 0&&(value=null),placeholder===void 0&&(placeholder=null),rows===void 0&&(rows=0),onChange===void 0&&(onChange=null),changeHandler=null,H5.staticEquals(onChange,null)||(changeHandler=function(e){onChange(H5.unbox(H5.unbox(e).target).value)}),props={className:className,value:value,placeholder:placeholder,rows:rows>0?H5.box(rows,System.Int32):null,onChange:changeHandler},React.createElement("textarea",props)},Svg:function(className,width,height,viewBox,fill,children){className===void 0&&(className=null);width===void 0&&(width=0);height===void 0&&(height=0);viewBox===void 0&&(viewBox=null);fill===void 0&&(fill=null);children===void 0&&(children=[]);var props={className:className,width:width>0?H5.box(width,System.Int32):null,height:height>0?H5.box(height,System.Int32):null,viewBox:viewBox,fill:fill};return React.createElement("svg",props,children)},Path:function(d,fill,stroke,strokeWidth){fill===void 0&&(fill=null);stroke===void 0&&(stroke=null);strokeWidth===void 0&&(strokeWidth=0);var props={d:d,fill:fill,stroke:stroke,strokeWidth:strokeWidth>0?H5.box(strokeWidth,System.Int32):null};return React.createElement("path",props)},Fragment:function(children){return children===void 0&&(children=[]),React.createElement(H5.unbox(React.Fragment),null,children)},CreateElement:function(tag,className,id,style,onClick,children){var clickHandler=null,props;return H5.staticEquals(onClick,null)||(clickHandler=function(_){onClick()}),props={className:className,id:id,style:style,onClick:clickHandler},React.createElement(tag,props,children)}}}});H5.define("Dashboard.React.Hooks",{statics:{methods:{UseState:function(T,initialValue){var $t,result=React.useState(initialValue),state=H5.cast(H5.unbox(result[System.Array.index(0,result)],T),T),setState=result[System.Array.index(1,result)];return $t=new(Dashboard.React.StateResult$1(T)),$t.State=state,$t.SetState=setState,$t},UseStateFunc:function(T,initialValue){var $t,result=React.useState(initialValue),state=H5.cast(H5.unbox(result[System.Array.index(0,result)],T),T),setState=result[System.Array.index(1,result)];return $t=new(Dashboard.React.StateFuncResult$1(T)),$t.State=state,$t.SetState=setState,$t},UseEffect$1:function(effect,deps){deps===void 0&&(deps=null);React.useEffect(function(){return effect(),null},H5.unbox(deps))},UseEffect:function(effect,cleanup,deps){deps===void 0&&(deps=null);React.useEffect(function(){return effect(),cleanup()},H5.unbox(deps))},UseRef:function(T,initialValue){return initialValue===void 0&&(initialValue=H5.getDefaultValue(T)),React.useRef(initialValue)},UseMemo:function(T,factory,deps){return React.useMemo(factory,H5.unbox(deps))},UseCallback:function(T,callback,deps){return React.useCallback(callback,H5.unbox(deps))},UseContext:function(T,context){return React.useContext(H5.unbox(context))}}}});H5.define("Dashboard.React.ReactInterop",{statics:{methods:{CreateElement$1:function(type,props,children){return props===void 0&&(props=null),children===void 0&&(children=[]),React.createElement(type,H5.unbox(props),H5.unbox(children))},CreateElement:function(component,props,children){return props===void 0&&(props=null),children===void 0&&(children=[]),React.createElement(component,H5.unbox(props),H5.unbox(children))},RenderApp:function(element,containerId){containerId===void 0&&(containerId="root");var container=document.getElementById(containerId),root=ReactDOM.createRoot(container);root.Render(element)}}}});H5.define("Dashboard.React.StateFuncResult$1",function(T){return{fields:{State:H5.getDefaultValue(T),SetState:null}}});H5.define("Dashboard.React.StateResult$1",function(T){return{fields:{State:H5.getDefaultValue(T),SetState:null}}})});H5.assemblyVersion("Dashboard.Web","1.0.0.0");H5.assembly("Dashboard.Web",function($asm,globals){"use strict";var $m=H5.setMetadata,$n=["System","Dashboard","Dashboard.React","Dashboard.Pages","Dashboard.Components","System.Threading.Tasks"];$m("Dashboard.AppState",function(){return{att:1048577,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:"ActiveView",t:16,rt:$n[0].String,g:{a:2,n:"get_ActiveView",t:8,rt:$n[0].String,fg:"ActiveView"},s:{a:2,n:"set_ActiveView",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"ActiveView"},fn:"ActiveView"},{a:2,n:"EditingAppointmentId",t:16,rt:$n[0].String,g:{a:2,n:"get_EditingAppointmentId",t:8,rt:$n[0].String,fg:"EditingAppointmentId"},s:{a:2,n:"set_EditingAppointmentId",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"EditingAppointmentId"},fn:"EditingAppointmentId"},{a:2,n:"EditingPatientId",t:16,rt:$n[0].String,g:{a:2,n:"get_EditingPatientId",t:8,rt:$n[0].String,fg:"EditingPatientId"},s:{a:2,n:"set_EditingPatientId",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"EditingPatientId"},fn:"EditingPatientId"},{a:2,n:"NotificationCount",t:16,rt:$n[0].Int32,g:{a:2,n:"get_NotificationCount",t:8,rt:$n[0].Int32,fg:"NotificationCount",box:function($v){return H5.box($v,System.Int32)}},s:{a:2,n:"set_NotificationCount",t:8,p:[$n[0].Int32],rt:$n[0].Void,fs:"NotificationCount"},fn:"NotificationCount"},{a:2,n:"SearchQuery",t:16,rt:$n[0].String,g:{a:2,n:"get_SearchQuery",t:8,rt:$n[0].String,fg:"SearchQuery"},s:{a:2,n:"set_SearchQuery",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"SearchQuery"},fn:"SearchQuery"},{a:2,n:"SidebarCollapsed",t:16,rt:$n[0].Boolean,g:{a:2,n:"get_SidebarCollapsed",t:8,rt:$n[0].Boolean,fg:"SidebarCollapsed",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},s:{a:2,n:"set_SidebarCollapsed",t:8,p:[$n[0].Boolean],rt:$n[0].Void,fs:"SidebarCollapsed"},fn:"SidebarCollapsed"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"ActiveView"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"EditingAppointmentId"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"EditingPatientId"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Int32,sn:"NotificationCount",box:function($v){return H5.box($v,System.Int32)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"SearchQuery"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Boolean,sn:"SidebarCollapsed",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}}]}},$n);$m("Dashboard.App",function(){return{att:1048961,a:2,s:!0,m:[{a:1,n:"GetPageTitle",is:!0,t:8,pi:[{n:"view",pt:$n[0].String,ps:0}],sn:"GetPageTitle",rt:$n[0].String,p:[$n[0].String]},{a:2,n:"Render",is:!0,t:8,sn:"Render",rt:Object},{a:1,n:"RenderPage",is:!0,t:8,pi:[{n:"state",pt:$n[1].AppState,ps:0},{n:"setState",pt:Function,ps:1}],sn:"RenderPage",rt:Object,p:[$n[1].AppState,Function]},{a:1,n:"RenderPlaceholderPage",is:!0,t:8,pi:[{n:"title",pt:$n[0].String,ps:0},{n:"description",pt:$n[0].String,ps:1}],sn:"RenderPlaceholderPage",rt:Object,p:[$n[0].String,$n[0].String]}]}},$n);$m("Dashboard.Program",function(){return{att:1048961,a:2,s:!0,m:[{a:1,n:"GetConfigValue",is:!0,t:8,pi:[{n:"key",pt:$n[0].String,ps:0},{n:"defaultValue",pt:$n[0].String,ps:1}],sn:"GetConfigValue",rt:$n[0].String,p:[$n[0].String,$n[0].String]},{a:1,n:"HideLoadingScreen",is:!0,t:8,sn:"HideLoadingScreen",rt:$n[0].Void},{a:1,n:"Log",is:!0,t:8,pi:[{n:"message",pt:$n[0].String,ps:0}],sn:"Log",rt:$n[0].Void,p:[$n[0].String]},{a:2,n:"Main",is:!0,t:8,sn:"Main",rt:$n[0].Void}]}},$n);$m("Dashboard.React.Elements",function(){return{att:1048961,a:2,s:!0,m:[{a:2,n:"A",is:!0,t:8,pi:[{n:"href",pt:$n[0].String,ps:0},{n:"className",dv:null,o:!0,pt:$n[0].String,ps:1},{n:"target",dv:null,o:!0,pt:$n[0].String,ps:2},{n:"onClick",dv:null,o:!0,pt:Function,ps:3},{n:"children",ip:!0,pt:System.Array.type(Object),ps:4}],sn:"A",rt:Object,p:[$n[0].String,$n[0].String,$n[0].String,Function,System.Array.type(Object)]},{a:2,n:"Article",is:!0,t:8,pi:[{n:"className",dv:null,o:!0,pt:$n[0].String,ps:0},{n:"children",ip:!0,pt:System.Array.type(Object),ps:1}],sn:"Article",rt:Object,p:[$n[0].String,System.Array.type(Object)]},{a:2,n:"Aside",is:!0,t:8,pi:[{n:"className",dv:null,o:!0,pt:$n[0].String,ps:0},{n:"children",ip:!0,pt:System.Array.type(Object),ps:1}],sn:"Aside",rt:Object,p:[$n[0].String,System.Array.type(Object)]},{a:2,n:"Button",is:!0,t:8,pi:[{n:"className",dv:null,o:!0,pt:$n[0].String,ps:0},{n:"onClick",dv:null,o:!0,pt:Function,ps:1},{n:"disabled",dv:!1,o:!0,pt:$n[0].Boolean,ps:2},{n:"type",dv:"button",o:!0,pt:$n[0].String,ps:3},{n:"children",ip:!0,pt:System.Array.type(Object),ps:4}],sn:"Button",rt:Object,p:[$n[0].String,Function,$n[0].Boolean,$n[0].String,System.Array.type(Object)]},{a:1,n:"CreateElement",is:!0,t:8,pi:[{n:"tag",pt:$n[0].String,ps:0},{n:"className",pt:$n[0].String,ps:1},{n:"id",pt:$n[0].String,ps:2},{n:"style",pt:$n[0].Object,ps:3},{n:"onClick",pt:Function,ps:4},{n:"children",pt:System.Array.type(Object),ps:5}],sn:"CreateElement",rt:Object,p:[$n[0].String,$n[0].String,$n[0].String,$n[0].Object,Function,System.Array.type(Object)]},{a:2,n:"Div",is:!0,t:8,pi:[{n:"className",dv:null,o:!0,pt:$n[0].String,ps:0},{n:"id",dv:null,o:!0,pt:$n[0].String,ps:1},{n:"style",dv:null,o:!0,pt:$n[0].Object,ps:2},{n:"onClick",dv:null,o:!0,pt:Function,ps:3},{n:"children",ip:!0,pt:System.Array.type(Object),ps:4}],sn:"Div",rt:Object,p:[$n[0].String,$n[0].String,$n[0].Object,Function,System.Array.type(Object)]},{a:2,n:"Footer",is:!0,t:8,pi:[{n:"className",dv:null,o:!0,pt:$n[0].String,ps:0},{n:"children",ip:!0,pt:System.Array.type(Object),ps:1}],sn:"Footer",rt:Object,p:[$n[0].String,System.Array.type(Object)]},{a:2,n:"Form",is:!0,t:8,pi:[{n:"className",dv:null,o:!0,pt:$n[0].String,ps:0},{n:"onSubmit",dv:null,o:!0,pt:Function,ps:1},{n:"children",ip:!0,pt:System.Array.type(Object),ps:2}],sn:"Form",rt:Object,p:[$n[0].String,Function,System.Array.type(Object)]},{a:2,n:"Fragment",is:!0,t:8,pi:[{n:"children",ip:!0,pt:System.Array.type(Object),ps:0}],sn:"Fragment",rt:Object,p:[System.Array.type(Object)]},{a:2,n:"H",is:!0,t:8,pi:[{n:"level",pt:$n[0].Int32,ps:0},{n:"className",dv:null,o:!0,pt:$n[0].String,ps:1},{n:"children",ip:!0,pt:System.Array.type(Object),ps:2}],sn:"H",rt:Object,p:[$n[0].Int32,$n[0].String,System.Array.type(Object)]},{a:2,n:"Header",is:!0,t:8,pi:[{n:"className",dv:null,o:!0,pt:$n[0].String,ps:0},{n:"children",ip:!0,pt:System.Array.type(Object),ps:1}],sn:"Header",rt:Object,p:[$n[0].String,System.Array.type(Object)]},{a:2,n:"Img",is:!0,t:8,pi:[{n:"src",pt:$n[0].String,ps:0},{n:"alt",dv:null,o:!0,pt:$n[0].String,ps:1},{n:"className",dv:null,o:!0,pt:$n[0].String,ps:2},{n:"style",dv:null,o:!0,pt:$n[0].Object,ps:3}],sn:"Img",rt:Object,p:[$n[0].String,$n[0].String,$n[0].String,$n[0].Object]},{a:2,n:"Input",is:!0,t:8,pi:[{n:"className",dv:null,o:!0,pt:$n[0].String,ps:0},{n:"type",dv:"text",o:!0,pt:$n[0].String,ps:1},{n:"value",dv:null,o:!0,pt:$n[0].String,ps:2},{n:"placeholder",dv:null,o:!0,pt:$n[0].String,ps:3},{n:"onChange",dv:null,o:!0,pt:Function,ps:4},{n:"onKeyDown",dv:null,o:!0,pt:Function,ps:5},{n:"disabled",dv:!1,o:!0,pt:$n[0].Boolean,ps:6}],sn:"Input",rt:Object,p:[$n[0].String,$n[0].String,$n[0].String,$n[0].String,Function,Function,$n[0].Boolean]},{a:2,n:"Label",is:!0,t:8,pi:[{n:"htmlFor",dv:null,o:!0,pt:$n[0].String,ps:0},{n:"className",dv:null,o:!0,pt:$n[0].String,ps:1},{n:"children",ip:!0,pt:System.Array.type(Object),ps:2}],sn:"Label",rt:Object,p:[$n[0].String,$n[0].String,System.Array.type(Object)]},{a:2,n:"Li",is:!0,t:8,pi:[{n:"className",dv:null,o:!0,pt:$n[0].String,ps:0},{n:"onClick",dv:null,o:!0,pt:Function,ps:1},{n:"children",ip:!0,pt:System.Array.type(Object),ps:2}],sn:"Li",rt:Object,p:[$n[0].String,Function,System.Array.type(Object)]},{a:2,n:"Main",is:!0,t:8,pi:[{n:"className",dv:null,o:!0,pt:$n[0].String,ps:0},{n:"children",ip:!0,pt:System.Array.type(Object),ps:1}],sn:"Main",rt:Object,p:[$n[0].String,System.Array.type(Object)]},{a:2,n:"Nav",is:!0,t:8,pi:[{n:"className",dv:null,o:!0,pt:$n[0].String,ps:0},{n:"children",ip:!0,pt:System.Array.type(Object),ps:1}],sn:"Nav",rt:Object,p:[$n[0].String,System.Array.type(Object)]},{a:2,n:"Option",is:!0,t:8,pi:[{n:"value",pt:$n[0].String,ps:0},{n:"label",pt:$n[0].String,ps:1}],sn:"Option",rt:Object,p:[$n[0].String,$n[0].String]},{a:2,n:"P",is:!0,t:8,pi:[{n:"className",dv:null,o:!0,pt:$n[0].String,ps:0},{n:"style",dv:null,o:!0,pt:$n[0].Object,ps:1},{n:"children",ip:!0,pt:System.Array.type(Object),ps:2}],sn:"P",rt:Object,p:[$n[0].String,$n[0].Object,System.Array.type(Object)]},{a:2,n:"Path",is:!0,t:8,pi:[{n:"d",pt:$n[0].String,ps:0},{n:"fill",dv:null,o:!0,pt:$n[0].String,ps:1},{n:"stroke",dv:null,o:!0,pt:$n[0].String,ps:2},{n:"strokeWidth",dv:0,o:!0,pt:$n[0].Int32,ps:3}],sn:"Path",rt:Object,p:[$n[0].String,$n[0].String,$n[0].String,$n[0].Int32]},{a:2,n:"Section",is:!0,t:8,pi:[{n:"className",dv:null,o:!0,pt:$n[0].String,ps:0},{n:"children",ip:!0,pt:System.Array.type(Object),ps:1}],sn:"Section",rt:Object,p:[$n[0].String,System.Array.type(Object)]},{a:2,n:"Select",is:!0,t:8,pi:[{n:"className",dv:null,o:!0,pt:$n[0].String,ps:0},{n:"value",dv:null,o:!0,pt:$n[0].String,ps:1},{n:"onChange",dv:null,o:!0,pt:Function,ps:2},{n:"children",ip:!0,pt:System.Array.type(Object),ps:3}],sn:"Select",rt:Object,p:[$n[0].String,$n[0].String,Function,System.Array.type(Object)]},{a:2,n:"Span",is:!0,t:8,pi:[{n:"className",dv:null,o:!0,pt:$n[0].String,ps:0},{n:"id",dv:null,o:!0,pt:$n[0].String,ps:1},{n:"style",dv:null,o:!0,pt:$n[0].Object,ps:2},{n:"children",ip:!0,pt:System.Array.type(Object),ps:3}],sn:"Span",rt:Object,p:[$n[0].String,$n[0].String,$n[0].Object,System.Array.type(Object)]},{a:2,n:"Svg",is:!0,t:8,pi:[{n:"className",dv:null,o:!0,pt:$n[0].String,ps:0},{n:"width",dv:0,o:!0,pt:$n[0].Int32,ps:1},{n:"height",dv:0,o:!0,pt:$n[0].Int32,ps:2},{n:"viewBox",dv:null,o:!0,pt:$n[0].String,ps:3},{n:"fill",dv:null,o:!0,pt:$n[0].String,ps:4},{n:"children",ip:!0,pt:System.Array.type(Object),ps:5}],sn:"Svg",rt:Object,p:[$n[0].String,$n[0].Int32,$n[0].Int32,$n[0].String,$n[0].String,System.Array.type(Object)]},{a:2,n:"TBody",is:!0,t:8,pi:[{n:"children",ip:!0,pt:System.Array.type(Object),ps:0}],sn:"TBody",rt:Object,p:[System.Array.type(Object)]},{a:2,n:"THead",is:!0,t:8,pi:[{n:"children",ip:!0,pt:System.Array.type(Object),ps:0}],sn:"THead",rt:Object,p:[System.Array.type(Object)]},{a:2,n:"Table",is:!0,t:8,pi:[{n:"className",dv:null,o:!0,pt:$n[0].String,ps:0},{n:"children",ip:!0,pt:System.Array.type(Object),ps:1}],sn:"Table",rt:Object,p:[$n[0].String,System.Array.type(Object)]},{a:2,n:"Td",is:!0,t:8,pi:[{n:"className",dv:null,o:!0,pt:$n[0].String,ps:0},{n:"children",ip:!0,pt:System.Array.type(Object),ps:1}],sn:"Td",rt:Object,p:[$n[0].String,System.Array.type(Object)]},{a:2,n:"Text",is:!0,t:8,pi:[{n:"content",pt:$n[0].String,ps:0}],sn:"Text",rt:Object,p:[$n[0].String]},{a:2,n:"TextArea",is:!0,t:8,pi:[{n:"className",dv:null,o:!0,pt:$n[0].String,ps:0},{n:"value",dv:null,o:!0,pt:$n[0].String,ps:1},{n:"placeholder",dv:null,o:!0,pt:$n[0].String,ps:2},{n:"rows",dv:0,o:!0,pt:$n[0].Int32,ps:3},{n:"onChange",dv:null,o:!0,pt:Function,ps:4}],sn:"TextArea",rt:Object,p:[$n[0].String,$n[0].String,$n[0].String,$n[0].Int32,Function]},{a:2,n:"Th",is:!0,t:8,pi:[{n:"className",dv:null,o:!0,pt:$n[0].String,ps:0},{n:"children",ip:!0,pt:System.Array.type(Object),ps:1}],sn:"Th",rt:Object,p:[$n[0].String,System.Array.type(Object)]},{a:2,n:"Tr",is:!0,t:8,pi:[{n:"className",dv:null,o:!0,pt:$n[0].String,ps:0},{n:"onClick",dv:null,o:!0,pt:Function,ps:1},{n:"children",ip:!0,pt:System.Array.type(Object),ps:2}],sn:"Tr",rt:Object,p:[$n[0].String,Function,System.Array.type(Object)]},{a:2,n:"Ul",is:!0,t:8,pi:[{n:"className",dv:null,o:!0,pt:$n[0].String,ps:0},{n:"children",ip:!0,pt:System.Array.type(Object),ps:1}],sn:"Ul",rt:Object,p:[$n[0].String,System.Array.type(Object)]}]}},$n);$m("Dashboard.React.StateResult$1",function(T){return{att:1048577,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:"SetState",t:16,rt:Function,g:{a:2,n:"get_SetState",t:8,rt:Function,fg:"SetState"},s:{a:2,n:"set_SetState",t:8,p:[Function],rt:$n[0].Void,fs:"SetState"},fn:"SetState"},{a:2,n:"State",t:16,rt:T,g:{a:2,n:"get_State",t:8,rt:T,fg:"State"},s:{a:2,n:"set_State",t:8,p:[T],rt:$n[0].Void,fs:"State"},fn:"State"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:Function,sn:"SetState"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:T,sn:"State"}]}},$n);$m("Dashboard.React.StateFuncResult$1",function(T){return{att:1048577,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:"SetState",t:16,rt:Function,g:{a:2,n:"get_SetState",t:8,rt:Function,fg:"SetState"},s:{a:2,n:"set_SetState",t:8,p:[Function],rt:$n[0].Void,fs:"SetState"},fn:"SetState"},{a:2,n:"State",t:16,rt:T,g:{a:2,n:"get_State",t:8,rt:T,fg:"State"},s:{a:2,n:"set_State",t:8,p:[T],rt:$n[0].Void,fs:"State"},fn:"State"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:Function,sn:"SetState"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:T,sn:"State"}]}},$n);$m("Dashboard.React.Hooks",function(){return{att:1048961,a:2,s:!0,m:[{a:2,n:"UseCallback",is:!0,t:8,pi:[{n:"callback",pt:System.Object,ps:0},{n:"deps",pt:$n[0].Array.type(System.Object),ps:1}],tpc:1,tprm:["T"],sn:"UseCallback",rt:System.Object,p:[System.Object,$n[0].Array.type(System.Object)]},{a:2,n:"UseContext",is:!0,t:8,pi:[{n:"context",pt:$n[0].Object,ps:0}],tpc:1,tprm:["T"],sn:"UseContext",rt:System.Object,p:[$n[0].Object]},{a:2,n:"UseEffect",is:!0,t:8,pi:[{n:"effect",pt:Function,ps:0},{n:"deps",dv:null,o:!0,pt:$n[0].Array.type(System.Object),ps:1}],sn:"UseEffect$1",rt:$n[0].Void,p:[Function,$n[0].Array.type(System.Object)]},{a:2,n:"UseEffect",is:!0,t:8,pi:[{n:"effect",pt:Function,ps:0},{n:"cleanup",pt:Function,ps:1},{n:"deps",dv:null,o:!0,pt:$n[0].Array.type(System.Object),ps:2}],sn:"UseEffect",rt:$n[0].Void,p:[Function,Function,$n[0].Array.type(System.Object)]},{a:2,n:"UseMemo",is:!0,t:8,pi:[{n:"factory",pt:Function,ps:0},{n:"deps",pt:$n[0].Array.type(System.Object),ps:1}],tpc:1,tprm:["T"],sn:"UseMemo",rt:System.Object,p:[Function,$n[0].Array.type(System.Object)]},{a:2,n:"UseRef",is:!0,t:8,pi:[{n:"initialValue",dv:null,o:!0,pt:System.Object,ps:0}],tpc:1,tprm:["T"],sn:"UseRef",rt:Object(System.Object),p:[System.Object]},{a:2,n:"UseState",is:!0,t:8,pi:[{n:"initialValue",pt:System.Object,ps:0}],tpc:1,tprm:["T"],sn:"UseState",rt:$n[2].StateResult$1(System.Object),p:[System.Object]},{a:2,n:"UseStateFunc",is:!0,t:8,pi:[{n:"initialValue",pt:System.Object,ps:0}],tpc:1,tprm:["T"],sn:"UseStateFunc",rt:$n[2].StateFuncResult$1(System.Object),p:[System.Object]}]}},$n);$m("Dashboard.React.ReactInterop",function(){return{att:1048961,a:2,s:!0,m:[{a:2,n:"CreateElement",is:!0,t:8,pi:[{n:"component",pt:Function,ps:0},{n:"props",dv:null,o:!0,pt:$n[0].Object,ps:1},{n:"children",ip:!0,pt:$n[0].Array.type(System.Object),ps:2}],sn:"CreateElement",rt:Object,p:[Function,$n[0].Object,$n[0].Array.type(System.Object)]},{a:2,n:"CreateElement",is:!0,t:8,pi:[{n:"type",pt:$n[0].String,ps:0},{n:"props",dv:null,o:!0,pt:$n[0].Object,ps:1},{n:"children",ip:!0,pt:$n[0].Array.type(System.Object),ps:2}],sn:"CreateElement$1",rt:Object,p:[$n[0].String,$n[0].Object,$n[0].Array.type(System.Object)]},{a:2,n:"RenderApp",is:!0,t:8,pi:[{n:"element",pt:Object,ps:0},{n:"containerId",dv:"root",o:!0,pt:$n[0].String,ps:1}],sn:"RenderApp",rt:$n[0].Void,p:[Object,$n[0].String]}]}},$n);$m("Dashboard.Pages.AppointmentsState",function(){return{att:1048577,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:"Appointments",t:16,rt:System.Array.type(Object),g:{a:2,n:"get_Appointments",t:8,rt:System.Array.type(Object),fg:"Appointments"},s:{a:2,n:"set_Appointments",t:8,p:[System.Array.type(Object)],rt:$n[0].Void,fs:"Appointments"},fn:"Appointments"},{a:2,n:"Error",t:16,rt:$n[0].String,g:{a:2,n:"get_Error",t:8,rt:$n[0].String,fg:"Error"},s:{a:2,n:"set_Error",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"Error"},fn:"Error"},{a:2,n:"Loading",t:16,rt:$n[0].Boolean,g:{a:2,n:"get_Loading",t:8,rt:$n[0].Boolean,fg:"Loading",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},s:{a:2,n:"set_Loading",t:8,p:[$n[0].Boolean],rt:$n[0].Void,fs:"Loading"},fn:"Loading"},{a:2,n:"StatusFilter",t:16,rt:$n[0].String,g:{a:2,n:"get_StatusFilter",t:8,rt:$n[0].String,fg:"StatusFilter"},s:{a:2,n:"set_StatusFilter",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"StatusFilter"},fn:"StatusFilter"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:System.Array.type(Object),sn:"Appointments"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"Error"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Boolean,sn:"Loading",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"StatusFilter"}]}},$n);$m("Dashboard.Pages.AppointmentsPage",function(){return{att:1048961,a:2,s:!0,m:[{a:1,n:"FilterByStatus",is:!0,t:8,pi:[{n:"status",pt:$n[0].String,ps:0},{n:"currentState",pt:$n[3].AppointmentsState,ps:1},{n:"setState",pt:Function,ps:2}],sn:"FilterByStatus",rt:$n[0].Void,p:[$n[0].String,$n[3].AppointmentsState,Function]},{a:1,n:"FormatReference",is:!0,t:8,pi:[{n:"reference",pt:$n[0].String,ps:0}],sn:"FormatReference",rt:$n[0].String,p:[$n[0].String]},{a:1,n:"FormatTime",is:!0,t:8,pi:[{n:"dateTime",pt:$n[0].String,ps:0}],sn:"FormatTime",rt:$n[0].String,p:[$n[0].String]},{a:1,n:"LoadAppointments",is:!0,t:8,pi:[{n:"setState",pt:Function,ps:0}],sn:"LoadAppointments",rt:$n[0].Void,p:[Function]},{a:2,n:"Render",is:!0,t:8,pi:[{n:"onEditAppointment",pt:Function,ps:0}],sn:"Render",rt:Object,p:[Function]},{a:1,n:"RenderAppointmentCard",is:!0,t:8,pi:[{n:"appointment",pt:Object,ps:0},{n:"onEditAppointment",pt:Function,ps:1}],sn:"RenderAppointmentCard",rt:Object,p:[Object,Function]},{a:1,n:"RenderAppointmentList",is:!0,t:8,pi:[{n:"appointments",pt:System.Array.type(Object),ps:0},{n:"statusFilter",pt:$n[0].String,ps:1},{n:"onEditAppointment",pt:Function,ps:2}],sn:"RenderAppointmentList",rt:Object,p:[System.Array.type(Object),$n[0].String,Function]},{a:1,n:"RenderEmpty",is:!0,t:8,sn:"RenderEmpty",rt:Object},{a:1,n:"RenderError",is:!0,t:8,pi:[{n:"message",pt:$n[0].String,ps:0}],sn:"RenderError",rt:Object,p:[$n[0].String]},{a:1,n:"RenderInternal",is:!0,t:8,pi:[{n:"onEditAppointment",pt:Function,ps:0}],sn:"RenderInternal",rt:Object,p:[Function]},{a:1,n:"RenderLoadingList",is:!0,t:8,sn:"RenderLoadingList",rt:Object},{a:1,n:"RenderPriorityBadge",is:!0,t:8,pi:[{n:"priority",pt:$n[0].String,ps:0}],sn:"RenderPriorityBadge",rt:Object,p:[$n[0].String]},{a:1,n:"RenderStatusBadge",is:!0,t:8,pi:[{n:"status",pt:$n[0].String,ps:0}],sn:"RenderStatusBadge",rt:Object,p:[$n[0].String]},{a:1,n:"RenderTab",is:!0,t:8,pi:[{n:"label",pt:$n[0].String,ps:0},{n:"status",pt:$n[0].String,ps:1},{n:"currentFilter",pt:$n[0].String,ps:2},{n:"onSelect",pt:Function,ps:3}],sn:"RenderTab",rt:Object,p:[$n[0].String,$n[0].String,$n[0].String,Function]}]}},$n);$m("Dashboard.Pages.CalendarState",function(){return{att:1048577,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:"Appointments",t:16,rt:System.Array.type(Object),g:{a:2,n:"get_Appointments",t:8,rt:System.Array.type(Object),fg:"Appointments"},s:{a:2,n:"set_Appointments",t:8,p:[System.Array.type(Object)],rt:$n[0].Void,fs:"Appointments"},fn:"Appointments"},{a:2,n:"Error",t:16,rt:$n[0].String,g:{a:2,n:"get_Error",t:8,rt:$n[0].String,fg:"Error"},s:{a:2,n:"set_Error",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"Error"},fn:"Error"},{a:2,n:"Loading",t:16,rt:$n[0].Boolean,g:{a:2,n:"get_Loading",t:8,rt:$n[0].Boolean,fg:"Loading",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},s:{a:2,n:"set_Loading",t:8,p:[$n[0].Boolean],rt:$n[0].Void,fs:"Loading"},fn:"Loading"},{a:2,n:"Month",t:16,rt:$n[0].Int32,g:{a:2,n:"get_Month",t:8,rt:$n[0].Int32,fg:"Month",box:function($v){return H5.box($v,System.Int32)}},s:{a:2,n:"set_Month",t:8,p:[$n[0].Int32],rt:$n[0].Void,fs:"Month"},fn:"Month"},{a:2,n:"SelectedDay",t:16,rt:$n[0].Int32,g:{a:2,n:"get_SelectedDay",t:8,rt:$n[0].Int32,fg:"SelectedDay",box:function($v){return H5.box($v,System.Int32)}},s:{a:2,n:"set_SelectedDay",t:8,p:[$n[0].Int32],rt:$n[0].Void,fs:"SelectedDay"},fn:"SelectedDay"},{a:2,n:"Year",t:16,rt:$n[0].Int32,g:{a:2,n:"get_Year",t:8,rt:$n[0].Int32,fg:"Year",box:function($v){return H5.box($v,System.Int32)}},s:{a:2,n:"set_Year",t:8,p:[$n[0].Int32],rt:$n[0].Void,fs:"Year"},fn:"Year"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:System.Array.type(Object),sn:"Appointments"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"Error"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Boolean,sn:"Loading",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Int32,sn:"Month",box:function($v){return H5.box($v,System.Int32)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Int32,sn:"SelectedDay",box:function($v){return H5.box($v,System.Int32)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Int32,sn:"Year",box:function($v){return H5.box($v,System.Int32)}}]}},$n);$m("Dashboard.Pages.CalendarPage",function(){return{att:1048961,a:2,s:!0,m:[{a:1,n:"FormatReference",is:!0,t:8,pi:[{n:"reference",pt:$n[0].String,ps:0}],sn:"FormatReference",rt:$n[0].String,p:[$n[0].String]},{a:1,n:"FormatTime",is:!0,t:8,pi:[{n:"dateTime",pt:$n[0].String,ps:0}],sn:"FormatTime",rt:$n[0].String,p:[$n[0].String]},{a:1,n:"GetAppointmentsForDay",is:!0,t:8,pi:[{n:"appointments",pt:System.Array.type(Object),ps:0},{n:"year",pt:$n[0].Int32,ps:1},{n:"month",pt:$n[0].Int32,ps:2},{n:"day",pt:$n[0].Int32,ps:3}],sn:"GetAppointmentsForDay",rt:System.Array.type(Object),p:[System.Array.type(Object),$n[0].Int32,$n[0].Int32,$n[0].Int32]},{a:1,n:"GetStatusClass",is:!0,t:8,pi:[{n:"status",pt:$n[0].String,ps:0}],sn:"GetStatusClass",rt:$n[0].String,p:[$n[0].String]},{a:1,n:"GoToToday",is:!0,t:8,pi:[{n:"state",pt:$n[3].CalendarState,ps:0},{n:"setState",pt:Function,ps:1}],sn:"GoToToday",rt:$n[0].Void,p:[$n[3].CalendarState,Function]},{a:1,n:"LoadAppointments",is:!0,t:8,pi:[{n:"setState",pt:Function,ps:0},{n:"currentState",pt:$n[3].CalendarState,ps:1}],sn:"LoadAppointments",rt:$n[0].Void,p:[Function,$n[3].CalendarState]},{a:1,n:"NavigateMonth",is:!0,t:8,pi:[{n:"state",pt:$n[3].CalendarState,ps:0},{n:"setState",pt:Function,ps:1},{n:"delta",pt:$n[0].Int32,ps:2}],sn:"NavigateMonth",rt:$n[0].Void,p:[$n[3].CalendarState,Function,$n[0].Int32]},{a:2,n:"Render",is:!0,t:8,pi:[{n:"onEditAppointment",pt:Function,ps:0}],sn:"Render",rt:Object,p:[Function]},{a:1,n:"RenderAppointmentDot",is:!0,t:8,pi:[{n:"appointment",pt:Object,ps:0}],sn:"RenderAppointmentDot",rt:Object,p:[Object]},{a:1,n:"RenderCalendarContent",is:!0,t:8,pi:[{n:"state",pt:$n[3].CalendarState,ps:0},{n:"setState",pt:Function,ps:1},{n:"onEditAppointment",pt:Function,ps:2}],sn:"RenderCalendarContent",rt:Object,p:[$n[3].CalendarState,Function,Function]},{a:1,n:"RenderCalendarGrid",is:!0,t:8,pi:[{n:"state",pt:$n[3].CalendarState,ps:0},{n:"setState",pt:Function,ps:1}],sn:"RenderCalendarGrid",rt:Object,p:[$n[3].CalendarState,Function]},{a:1,n:"RenderDayAppointment",is:!0,t:8,pi:[{n:"appointment",pt:Object,ps:0},{n:"onEditAppointment",pt:Function,ps:1}],sn:"RenderDayAppointment",rt:Object,p:[Object,Function]},{a:1,n:"RenderDayDetails",is:!0,t:8,pi:[{n:"state",pt:$n[3].CalendarState,ps:0},{n:"setState",pt:Function,ps:1},{n:"onEditAppointment",pt:Function,ps:2}],sn:"RenderDayDetails",rt:Object,p:[$n[3].CalendarState,Function,Function]},{a:1,n:"RenderError",is:!0,t:8,pi:[{n:"message",pt:$n[0].String,ps:0}],sn:"RenderError",rt:Object,p:[$n[0].String]},{a:1,n:"RenderHeader",is:!0,t:8,pi:[{n:"state",pt:$n[3].CalendarState,ps:0},{n:"setState",pt:Function,ps:1}],sn:"RenderHeader",rt:Object,p:[$n[3].CalendarState,Function]},{a:1,n:"RenderLoadingState",is:!0,t:8,sn:"RenderLoadingState",rt:Object},{a:1,n:"RenderNoSelection",is:!0,t:8,sn:"RenderNoSelection",rt:Object},{a:1,n:"SelectDay",is:!0,t:8,pi:[{n:"state",pt:$n[3].CalendarState,ps:0},{n:"setState",pt:Function,ps:1},{n:"day",pt:$n[0].Int32,ps:2}],sn:"SelectDay",rt:$n[0].Void,p:[$n[3].CalendarState,Function,$n[0].Int32]},{a:1,n:"DayNames",is:!0,t:4,rt:$n[0].Array.type(System.String),sn:"DayNames",ro:!0},{a:1,n:"MonthNames",is:!0,t:4,rt:$n[0].Array.type(System.String),sn:"MonthNames",ro:!0}]}},$n);$m("Dashboard.Pages.ClinicalCodingState",function(){return{att:1048577,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:"AchiResults",t:16,rt:System.Array.type(Object),g:{a:2,n:"get_AchiResults",t:8,rt:System.Array.type(Object),fg:"AchiResults"},s:{a:2,n:"set_AchiResults",t:8,p:[System.Array.type(Object)],rt:$n[0].Void,fs:"AchiResults"},fn:"AchiResults"},{a:2,n:"CopiedCode",t:16,rt:$n[0].String,g:{a:2,n:"get_CopiedCode",t:8,rt:$n[0].String,fg:"CopiedCode"},s:{a:2,n:"set_CopiedCode",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"CopiedCode"},fn:"CopiedCode"},{a:2,n:"Error",t:16,rt:$n[0].String,g:{a:2,n:"get_Error",t:8,rt:$n[0].String,fg:"Error"},s:{a:2,n:"set_Error",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"Error"},fn:"Error"},{a:2,n:"Icd10Results",t:16,rt:System.Array.type(Object),g:{a:2,n:"get_Icd10Results",t:8,rt:System.Array.type(Object),fg:"Icd10Results"},s:{a:2,n:"set_Icd10Results",t:8,p:[System.Array.type(Object)],rt:$n[0].Void,fs:"Icd10Results"},fn:"Icd10Results"},{a:2,n:"IncludeAchi",t:16,rt:$n[0].Boolean,g:{a:2,n:"get_IncludeAchi",t:8,rt:$n[0].Boolean,fg:"IncludeAchi",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},s:{a:2,n:"set_IncludeAchi",t:8,p:[$n[0].Boolean],rt:$n[0].Void,fs:"IncludeAchi"},fn:"IncludeAchi"},{a:2,n:"Loading",t:16,rt:$n[0].Boolean,g:{a:2,n:"get_Loading",t:8,rt:$n[0].Boolean,fg:"Loading",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},s:{a:2,n:"set_Loading",t:8,p:[$n[0].Boolean],rt:$n[0].Void,fs:"Loading"},fn:"Loading"},{a:2,n:"SearchMode",t:16,rt:$n[0].String,g:{a:2,n:"get_SearchMode",t:8,rt:$n[0].String,fg:"SearchMode"},s:{a:2,n:"set_SearchMode",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"SearchMode"},fn:"SearchMode"},{a:2,n:"SearchQuery",t:16,rt:$n[0].String,g:{a:2,n:"get_SearchQuery",t:8,rt:$n[0].String,fg:"SearchQuery"},s:{a:2,n:"set_SearchQuery",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"SearchQuery"},fn:"SearchQuery"},{a:2,n:"SelectedCode",t:16,rt:Object,g:{a:2,n:"get_SelectedCode",t:8,rt:Object,fg:"SelectedCode"},s:{a:2,n:"set_SelectedCode",t:8,p:[Object],rt:$n[0].Void,fs:"SelectedCode"},fn:"SelectedCode"},{a:2,n:"SemanticResults",t:16,rt:System.Array.type(Object),g:{a:2,n:"get_SemanticResults",t:8,rt:System.Array.type(Object),fg:"SemanticResults"},s:{a:2,n:"set_SemanticResults",t:8,p:[System.Array.type(Object)],rt:$n[0].Void,fs:"SemanticResults"},fn:"SemanticResults"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:System.Array.type(Object),sn:"AchiResults"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"CopiedCode"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"Error"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:System.Array.type(Object),sn:"Icd10Results"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Boolean,sn:"IncludeAchi",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Boolean,sn:"Loading",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"SearchMode"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"SearchQuery"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:Object,sn:"SelectedCode"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:System.Array.type(Object),sn:"SemanticResults"}]}},$n);$m("Dashboard.Pages.ClinicalCodingPage",function(){return{att:1048961,a:2,s:!0,m:[{a:1,n:"ClearSelection",is:!0,t:8,pi:[{n:"state",pt:$n[3].ClinicalCodingState,ps:0},{n:"setState",pt:Function,ps:1}],sn:"ClearSelection",rt:$n[0].Void,p:[$n[3].ClinicalCodingState,Function]},{a:1,n:"Concat",is:!0,t:8,pi:[{n:"arr1",pt:System.Array.type(Object),ps:0},{n:"arr2",pt:System.Array.type(Object),ps:1}],sn:"Concat",rt:System.Array.type(Object),p:[System.Array.type(Object),System.Array.type(Object)]},{a:1,n:"CopyCode",is:!0,t:8,pi:[{n:"code",pt:$n[0].String,ps:0},{n:"state",pt:$n[3].ClinicalCodingState,ps:1},{n:"setState",pt:Function,ps:2}],sn:"CopyCode",rt:$n[0].Void,p:[$n[0].String,$n[3].ClinicalCodingState,Function]},{a:1,n:"ExecuteSearch",is:!0,t:8,pi:[{n:"state",pt:$n[3].ClinicalCodingState,ps:0},{n:"setState",pt:Function,ps:1}],sn:"ExecuteSearch",rt:$n[0].Void,p:[$n[3].ClinicalCodingState,Function]},{a:1,n:"GetEmptyDescription",is:!0,t:8,pi:[{n:"mode",pt:$n[0].String,ps:0}],sn:"GetEmptyDescription",rt:$n[0].String,p:[$n[0].String]},{a:1,n:"GetEmptyTitle",is:!0,t:8,pi:[{n:"mode",pt:$n[0].String,ps:0}],sn:"GetEmptyTitle",rt:$n[0].String,p:[$n[0].String]},{a:1,n:"GetPlaceholder",is:!0,t:8,pi:[{n:"mode",pt:$n[0].String,ps:0}],sn:"GetPlaceholder",rt:$n[0].String,p:[$n[0].String]},{a:1,n:"LookupSemanticCode",is:!0,t:8,pi:[{n:"code",pt:$n[0].String,ps:0},{n:"state",pt:$n[3].ClinicalCodingState,ps:1},{n:"setState",pt:Function,ps:2}],sn:"LookupSemanticCode",rt:$n[0].Void,p:[$n[0].String,$n[3].ClinicalCodingState,Function]},{a:2,n:"Render",is:!0,t:8,sn:"Render",rt:Object},{a:1,n:"RenderCodeDetail",is:!0,t:8,pi:[{n:"state",pt:$n[3].ClinicalCodingState,ps:0},{n:"setState",pt:Function,ps:1}],sn:"RenderCodeDetail",rt:Object,p:[$n[3].ClinicalCodingState,Function]},{a:1,n:"RenderCodeRow",is:!0,t:8,pi:[{n:"code",pt:Object,ps:0},{n:"state",pt:$n[3].ClinicalCodingState,ps:1},{n:"setState",pt:Function,ps:2}],sn:"RenderCodeRow",rt:Object,p:[Object,$n[3].ClinicalCodingState,Function]},{a:1,n:"RenderContent",is:!0,t:8,pi:[{n:"state",pt:$n[3].ClinicalCodingState,ps:0},{n:"setState",pt:Function,ps:1}],sn:"RenderContent",rt:Object,p:[$n[3].ClinicalCodingState,Function]},{a:1,n:"RenderDetailItem",is:!0,t:8,pi:[{n:"label",pt:$n[0].String,ps:0},{n:"value",pt:$n[0].String,ps:1}],sn:"RenderDetailItem",rt:Object,p:[$n[0].String,$n[0].String]},{a:1,n:"RenderDetailSection",is:!0,t:8,pi:[{n:"title",pt:$n[0].String,ps:0},{n:"content",pt:$n[0].String,ps:1}],sn:"RenderDetailSection",rt:Object,p:[$n[0].String,$n[0].String]},{a:1,n:"RenderEmptyState",is:!0,t:8,pi:[{n:"state",pt:$n[3].ClinicalCodingState,ps:0}],sn:"RenderEmptyState",rt:Object,p:[$n[3].ClinicalCodingState]},{a:1,n:"RenderError",is:!0,t:8,pi:[{n:"error",pt:$n[0].String,ps:0}],sn:"RenderError",rt:Object,p:[$n[0].String]},{a:1,n:"RenderHeader",is:!0,t:8,sn:"RenderHeader",rt:Object},{a:1,n:"RenderKeywordResults",is:!0,t:8,pi:[{n:"state",pt:$n[3].ClinicalCodingState,ps:0},{n:"setState",pt:Function,ps:1}],sn:"RenderKeywordResults",rt:Object,p:[$n[3].ClinicalCodingState,Function]},{a:1,n:"RenderLoading",is:!0,t:8,sn:"RenderLoading",rt:Object},{a:1,n:"RenderNoResults",is:!0,t:8,pi:[{n:"query",pt:$n[0].String,ps:0}],sn:"RenderNoResults",rt:Object,p:[$n[0].String]},{a:1,n:"RenderQuickSearches",is:!0,t:8,pi:[{n:"state",pt:$n[3].ClinicalCodingState,ps:0}],sn:"RenderQuickSearches",rt:Object,p:[$n[3].ClinicalCodingState]},{a:1,n:"RenderSearchInput",is:!0,t:8,pi:[{n:"state",pt:$n[3].ClinicalCodingState,ps:0},{n:"setState",pt:Function,ps:1}],sn:"RenderSearchInput",rt:Object,p:[$n[3].ClinicalCodingState,Function]},{a:1,n:"RenderSearchOptions",is:!0,t:8,pi:[{n:"state",pt:$n[3].ClinicalCodingState,ps:0},{n:"setState",pt:Function,ps:1}],sn:"RenderSearchOptions",rt:Object,p:[$n[3].ClinicalCodingState,Function]},{a:1,n:"RenderSearchSection",is:!0,t:8,pi:[{n:"state",pt:$n[3].ClinicalCodingState,ps:0},{n:"setState",pt:Function,ps:1}],sn:"RenderSearchSection",rt:Object,p:[$n[3].ClinicalCodingState,Function]},{a:1,n:"RenderSearchTabs",is:!0,t:8,pi:[{n:"state",pt:$n[3].ClinicalCodingState,ps:0},{n:"setState",pt:Function,ps:1}],sn:"RenderSearchTabs",rt:Object,p:[$n[3].ClinicalCodingState,Function]},{a:1,n:"RenderSemanticResults",is:!0,t:8,pi:[{n:"state",pt:$n[3].ClinicalCodingState,ps:0},{n:"setState",pt:Function,ps:1}],sn:"RenderSemanticResults",rt:Object,p:[$n[3].ClinicalCodingState,Function]},{a:1,n:"RenderSemanticRow",is:!0,t:8,pi:[{n:"result",pt:Object,ps:0},{n:"state",pt:$n[3].ClinicalCodingState,ps:1},{n:"setState",pt:Function,ps:2}],sn:"RenderSemanticRow",rt:Object,p:[Object,$n[3].ClinicalCodingState,Function]},{a:1,n:"RenderSemanticTooltipContent",is:!0,t:8,pi:[{n:"result",pt:Object,ps:0},{n:"confidenceColor",pt:$n[0].String,ps:1},{n:"confidencePercent",pt:$n[0].Int32,ps:2}],sn:"RenderSemanticTooltipContent",rt:System.Array.type(Object),p:[Object,$n[0].String,$n[0].Int32]},{a:1,n:"RenderTab",is:!0,t:8,pi:[{n:"label",pt:$n[0].String,ps:0},{n:"icon",pt:Function,ps:1},{n:"isActive",pt:$n[0].Boolean,ps:2},{n:"onClick",pt:Function,ps:3}],sn:"RenderTab",rt:Object,p:[$n[0].String,Function,$n[0].Boolean,Function]},{a:1,n:"SelectCode",is:!0,t:8,pi:[{n:"code",pt:Object,ps:0},{n:"state",pt:$n[3].ClinicalCodingState,ps:1},{n:"setState",pt:Function,ps:2}],sn:"SelectCode",rt:$n[0].Void,p:[Object,$n[3].ClinicalCodingState,Function]},{a:1,n:"SetSearchMode",is:!0,t:8,pi:[{n:"state",pt:$n[3].ClinicalCodingState,ps:0},{n:"setState",pt:Function,ps:1},{n:"mode",pt:$n[0].String,ps:2}],sn:"SetSearchMode",rt:$n[0].Void,p:[$n[3].ClinicalCodingState,Function,$n[0].String]},{a:1,n:"ToggleAchi",is:!0,t:8,pi:[{n:"state",pt:$n[3].ClinicalCodingState,ps:0},{n:"setState",pt:Function,ps:1}],sn:"ToggleAchi",rt:$n[0].Void,p:[$n[3].ClinicalCodingState,Function]},{a:1,n:"UpdateQuery",is:!0,t:8,pi:[{n:"state",pt:$n[3].ClinicalCodingState,ps:0},{n:"setState",pt:Function,ps:1},{n:"query",pt:$n[0].String,ps:2}],sn:"UpdateQuery",rt:$n[0].Void,p:[$n[3].ClinicalCodingState,Function,$n[0].String]}]}},$n);$m("Dashboard.Pages.DashboardState",function(){return{att:1048577,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:"AppointmentCount",t:16,rt:$n[0].Int32,g:{a:2,n:"get_AppointmentCount",t:8,rt:$n[0].Int32,fg:"AppointmentCount",box:function($v){return H5.box($v,System.Int32)}},s:{a:2,n:"set_AppointmentCount",t:8,p:[$n[0].Int32],rt:$n[0].Void,fs:"AppointmentCount"},fn:"AppointmentCount"},{a:2,n:"EncounterCount",t:16,rt:$n[0].Int32,g:{a:2,n:"get_EncounterCount",t:8,rt:$n[0].Int32,fg:"EncounterCount",box:function($v){return H5.box($v,System.Int32)}},s:{a:2,n:"set_EncounterCount",t:8,p:[$n[0].Int32],rt:$n[0].Void,fs:"EncounterCount"},fn:"EncounterCount"},{a:2,n:"Error",t:16,rt:$n[0].String,g:{a:2,n:"get_Error",t:8,rt:$n[0].String,fg:"Error"},s:{a:2,n:"set_Error",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"Error"},fn:"Error"},{a:2,n:"Loading",t:16,rt:$n[0].Boolean,g:{a:2,n:"get_Loading",t:8,rt:$n[0].Boolean,fg:"Loading",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},s:{a:2,n:"set_Loading",t:8,p:[$n[0].Boolean],rt:$n[0].Void,fs:"Loading"},fn:"Loading"},{a:2,n:"PatientCount",t:16,rt:$n[0].Int32,g:{a:2,n:"get_PatientCount",t:8,rt:$n[0].Int32,fg:"PatientCount",box:function($v){return H5.box($v,System.Int32)}},s:{a:2,n:"set_PatientCount",t:8,p:[$n[0].Int32],rt:$n[0].Void,fs:"PatientCount"},fn:"PatientCount"},{a:2,n:"PractitionerCount",t:16,rt:$n[0].Int32,g:{a:2,n:"get_PractitionerCount",t:8,rt:$n[0].Int32,fg:"PractitionerCount",box:function($v){return H5.box($v,System.Int32)}},s:{a:2,n:"set_PractitionerCount",t:8,p:[$n[0].Int32],rt:$n[0].Void,fs:"PractitionerCount"},fn:"PractitionerCount"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Int32,sn:"AppointmentCount",box:function($v){return H5.box($v,System.Int32)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Int32,sn:"EncounterCount",box:function($v){return H5.box($v,System.Int32)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"Error"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Boolean,sn:"Loading",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Int32,sn:"PatientCount",box:function($v){return H5.box($v,System.Int32)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Int32,sn:"PractitionerCount",box:function($v){return H5.box($v,System.Int32)}}]}},$n);$m("Dashboard.Pages.DashboardPage",function(){return{att:1048961,a:2,s:!0,m:[{a:1,n:"LoadData",is:!0,t:8,pi:[{n:"setState",pt:Function,ps:0}],sn:"LoadData",rt:$n[0].Void,p:[Function]},{a:2,n:"Render",is:!0,t:8,sn:"Render",rt:Object},{a:1,n:"RenderActionButton",is:!0,t:8,pi:[{n:"label",pt:$n[0].String,ps:0},{n:"icon",pt:Function,ps:1},{n:"variant",pt:$n[0].String,ps:2}],sn:"RenderActionButton",rt:Object,p:[$n[0].String,Function,$n[0].String]},{a:1,n:"RenderActivityItem",is:!0,t:8,pi:[{n:"title",pt:$n[0].String,ps:0},{n:"subtitle",pt:$n[0].String,ps:1},{n:"time",pt:$n[0].String,ps:2}],sn:"RenderActivityItem",rt:Object,p:[$n[0].String,$n[0].String,$n[0].String]},{a:1,n:"RenderError",is:!0,t:8,pi:[{n:"message",pt:$n[0].String,ps:0}],sn:"RenderError",rt:Object,p:[$n[0].String]},{a:1,n:"RenderQuickActions",is:!0,t:8,sn:"RenderQuickActions",rt:Object},{a:1,n:"RenderRecentActivity",is:!0,t:8,sn:"RenderRecentActivity",rt:Object}]}},$n);$m("Dashboard.Pages.EditAppointmentState",function(){return{att:1048577,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:"Appointment",t:16,rt:Object,g:{a:2,n:"get_Appointment",t:8,rt:Object,fg:"Appointment"},s:{a:2,n:"set_Appointment",t:8,p:[Object],rt:$n[0].Void,fs:"Appointment"},fn:"Appointment"},{a:2,n:"Comment",t:16,rt:$n[0].String,g:{a:2,n:"get_Comment",t:8,rt:$n[0].String,fg:"Comment"},s:{a:2,n:"set_Comment",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"Comment"},fn:"Comment"},{a:2,n:"Description",t:16,rt:$n[0].String,g:{a:2,n:"get_Description",t:8,rt:$n[0].String,fg:"Description"},s:{a:2,n:"set_Description",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"Description"},fn:"Description"},{a:2,n:"EndDate",t:16,rt:$n[0].String,g:{a:2,n:"get_EndDate",t:8,rt:$n[0].String,fg:"EndDate"},s:{a:2,n:"set_EndDate",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"EndDate"},fn:"EndDate"},{a:2,n:"EndTime",t:16,rt:$n[0].String,g:{a:2,n:"get_EndTime",t:8,rt:$n[0].String,fg:"EndTime"},s:{a:2,n:"set_EndTime",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"EndTime"},fn:"EndTime"},{a:2,n:"Error",t:16,rt:$n[0].String,g:{a:2,n:"get_Error",t:8,rt:$n[0].String,fg:"Error"},s:{a:2,n:"set_Error",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"Error"},fn:"Error"},{a:2,n:"Loading",t:16,rt:$n[0].Boolean,g:{a:2,n:"get_Loading",t:8,rt:$n[0].Boolean,fg:"Loading",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},s:{a:2,n:"set_Loading",t:8,p:[$n[0].Boolean],rt:$n[0].Void,fs:"Loading"},fn:"Loading"},{a:2,n:"PatientReference",t:16,rt:$n[0].String,g:{a:2,n:"get_PatientReference",t:8,rt:$n[0].String,fg:"PatientReference"},s:{a:2,n:"set_PatientReference",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"PatientReference"},fn:"PatientReference"},{a:2,n:"PractitionerReference",t:16,rt:$n[0].String,g:{a:2,n:"get_PractitionerReference",t:8,rt:$n[0].String,fg:"PractitionerReference"},s:{a:2,n:"set_PractitionerReference",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"PractitionerReference"},fn:"PractitionerReference"},{a:2,n:"Priority",t:16,rt:$n[0].String,g:{a:2,n:"get_Priority",t:8,rt:$n[0].String,fg:"Priority"},s:{a:2,n:"set_Priority",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"Priority"},fn:"Priority"},{a:2,n:"ReasonCode",t:16,rt:$n[0].String,g:{a:2,n:"get_ReasonCode",t:8,rt:$n[0].String,fg:"ReasonCode"},s:{a:2,n:"set_ReasonCode",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"ReasonCode"},fn:"ReasonCode"},{a:2,n:"Saving",t:16,rt:$n[0].Boolean,g:{a:2,n:"get_Saving",t:8,rt:$n[0].Boolean,fg:"Saving",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},s:{a:2,n:"set_Saving",t:8,p:[$n[0].Boolean],rt:$n[0].Void,fs:"Saving"},fn:"Saving"},{a:2,n:"ServiceCategory",t:16,rt:$n[0].String,g:{a:2,n:"get_ServiceCategory",t:8,rt:$n[0].String,fg:"ServiceCategory"},s:{a:2,n:"set_ServiceCategory",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"ServiceCategory"},fn:"ServiceCategory"},{a:2,n:"ServiceType",t:16,rt:$n[0].String,g:{a:2,n:"get_ServiceType",t:8,rt:$n[0].String,fg:"ServiceType"},s:{a:2,n:"set_ServiceType",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"ServiceType"},fn:"ServiceType"},{a:2,n:"StartDate",t:16,rt:$n[0].String,g:{a:2,n:"get_StartDate",t:8,rt:$n[0].String,fg:"StartDate"},s:{a:2,n:"set_StartDate",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"StartDate"},fn:"StartDate"},{a:2,n:"StartTime",t:16,rt:$n[0].String,g:{a:2,n:"get_StartTime",t:8,rt:$n[0].String,fg:"StartTime"},s:{a:2,n:"set_StartTime",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"StartTime"},fn:"StartTime"},{a:2,n:"Status",t:16,rt:$n[0].String,g:{a:2,n:"get_Status",t:8,rt:$n[0].String,fg:"Status"},s:{a:2,n:"set_Status",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"Status"},fn:"Status"},{a:2,n:"Success",t:16,rt:$n[0].String,g:{a:2,n:"get_Success",t:8,rt:$n[0].String,fg:"Success"},s:{a:2,n:"set_Success",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"Success"},fn:"Success"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:Object,sn:"Appointment"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"Comment"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"Description"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"EndDate"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"EndTime"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"Error"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Boolean,sn:"Loading",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"PatientReference"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"PractitionerReference"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"Priority"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"ReasonCode"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Boolean,sn:"Saving",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"ServiceCategory"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"ServiceType"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"StartDate"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"StartTime"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"Status"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"Success"}]}},$n);$m("Dashboard.Pages.EditAppointmentPage",function(){return{att:1048961,a:2,s:!0,m:[{a:1,n:"CombineDateTime",is:!0,t:8,pi:[{n:"date",pt:$n[0].String,ps:0},{n:"time",pt:$n[0].String,ps:1}],sn:"CombineDateTime",rt:$n[0].String,p:[$n[0].String,$n[0].String]},{a:1,n:"LoadAppointment",is:!0,t:8,pi:[{n:"appointmentId",pt:$n[0].String,ps:0},{n:"setState",pt:Function,ps:1}],sn:"LoadAppointment",rt:$n[0].Void,p:[$n[0].String,Function]},{a:1,n:"ParseDateTime",is:!0,t:8,pi:[{n:"isoDateTime",pt:$n[0].String,ps:0}],sn:"ParseDateTime",rt:$n[0].ValueTuple$2(System.String,System.String),p:[$n[0].String]},{a:2,n:"Render",is:!0,t:8,pi:[{n:"appointmentId",pt:$n[0].String,ps:0},{n:"onBack",pt:Function,ps:1}],sn:"Render",rt:Object,p:[$n[0].String,Function]},{a:1,n:"RenderErrorState",is:!0,t:8,pi:[{n:"error",pt:$n[0].String,ps:0},{n:"onBack",pt:Function,ps:1}],sn:"RenderErrorState",rt:Object,p:[$n[0].String,Function]},{a:1,n:"RenderForm",is:!0,t:8,pi:[{n:"state",pt:$n[3].EditAppointmentState,ps:0},{n:"setState",pt:Function,ps:1},{n:"onBack",pt:Function,ps:2}],sn:"RenderForm",rt:Object,p:[$n[3].EditAppointmentState,Function,Function]},{a:1,n:"RenderFormActions",is:!0,t:8,pi:[{n:"state",pt:$n[3].EditAppointmentState,ps:0},{n:"onBack",pt:Function,ps:1}],sn:"RenderFormActions",rt:Object,p:[$n[3].EditAppointmentState,Function]},{a:1,n:"RenderFormSection",is:!0,t:8,pi:[{n:"title",pt:$n[0].String,ps:0},{n:"fields",pt:System.Array.type(Object),ps:1}],sn:"RenderFormSection",rt:Object,p:[$n[0].String,System.Array.type(Object)]},{a:1,n:"RenderHeader",is:!0,t:8,pi:[{n:"appointment",pt:Object,ps:0},{n:"onBack",pt:Function,ps:1}],sn:"RenderHeader",rt:Object,p:[Object,Function]},{a:1,n:"RenderInputField",is:!0,t:8,pi:[{n:"label",pt:$n[0].String,ps:0},{n:"id",pt:$n[0].String,ps:1},{n:"value",pt:$n[0].String,ps:2},{n:"placeholder",pt:$n[0].String,ps:3},{n:"onChange",pt:Function,ps:4},{n:"type",dv:"text",o:!0,pt:$n[0].String,ps:5}],sn:"RenderInputField",rt:Object,p:[$n[0].String,$n[0].String,$n[0].String,$n[0].String,Function,$n[0].String]},{a:1,n:"RenderLoadingState",is:!0,t:8,sn:"RenderLoadingState",rt:Object},{a:1,n:"RenderSelectField",is:!0,t:8,pi:[{n:"label",pt:$n[0].String,ps:0},{n:"id",pt:$n[0].String,ps:1},{n:"value",pt:$n[0].String,ps:2},{n:"options",pt:$n[0].Array.type(System.ValueTuple$2(System.String,System.String)),ps:3},{n:"onChange",pt:Function,ps:4}],sn:"RenderSelectField",rt:Object,p:[$n[0].String,$n[0].String,$n[0].String,$n[0].Array.type(System.ValueTuple$2(System.String,System.String)),Function]},{a:1,n:"RenderTextareaField",is:!0,t:8,pi:[{n:"label",pt:$n[0].String,ps:0},{n:"id",pt:$n[0].String,ps:1},{n:"value",pt:$n[0].String,ps:2},{n:"placeholder",pt:$n[0].String,ps:3},{n:"onChange",pt:Function,ps:4}],sn:"RenderTextareaField",rt:Object,p:[$n[0].String,$n[0].String,$n[0].String,$n[0].String,Function]},{a:1,n:"SaveAppointment",is:!0,t:8,pi:[{n:"state",pt:$n[3].EditAppointmentState,ps:0},{n:"setState",pt:Function,ps:1},{n:"onBack",pt:Function,ps:2}],sn:"SaveAppointment",rt:$n[0].Void,p:[$n[3].EditAppointmentState,Function,Function]},{a:1,n:"UpdateField",is:!0,t:8,pi:[{n:"state",pt:$n[3].EditAppointmentState,ps:0},{n:"setState",pt:Function,ps:1},{n:"field",pt:$n[0].String,ps:2},{n:"value",pt:$n[0].String,ps:3}],sn:"UpdateField",rt:$n[0].Void,p:[$n[3].EditAppointmentState,Function,$n[0].String,$n[0].String]}]}},$n);$m("Dashboard.Pages.EditPatientState",function(){return{att:1048577,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:"Active",t:16,rt:$n[0].Boolean,g:{a:2,n:"get_Active",t:8,rt:$n[0].Boolean,fg:"Active",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},s:{a:2,n:"set_Active",t:8,p:[$n[0].Boolean],rt:$n[0].Void,fs:"Active"},fn:"Active"},{a:2,n:"AddressLine",t:16,rt:$n[0].String,g:{a:2,n:"get_AddressLine",t:8,rt:$n[0].String,fg:"AddressLine"},s:{a:2,n:"set_AddressLine",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"AddressLine"},fn:"AddressLine"},{a:2,n:"BirthDate",t:16,rt:$n[0].String,g:{a:2,n:"get_BirthDate",t:8,rt:$n[0].String,fg:"BirthDate"},s:{a:2,n:"set_BirthDate",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"BirthDate"},fn:"BirthDate"},{a:2,n:"City",t:16,rt:$n[0].String,g:{a:2,n:"get_City",t:8,rt:$n[0].String,fg:"City"},s:{a:2,n:"set_City",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"City"},fn:"City"},{a:2,n:"Country",t:16,rt:$n[0].String,g:{a:2,n:"get_Country",t:8,rt:$n[0].String,fg:"Country"},s:{a:2,n:"set_Country",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"Country"},fn:"Country"},{a:2,n:"Email",t:16,rt:$n[0].String,g:{a:2,n:"get_Email",t:8,rt:$n[0].String,fg:"Email"},s:{a:2,n:"set_Email",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"Email"},fn:"Email"},{a:2,n:"Error",t:16,rt:$n[0].String,g:{a:2,n:"get_Error",t:8,rt:$n[0].String,fg:"Error"},s:{a:2,n:"set_Error",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"Error"},fn:"Error"},{a:2,n:"FamilyName",t:16,rt:$n[0].String,g:{a:2,n:"get_FamilyName",t:8,rt:$n[0].String,fg:"FamilyName"},s:{a:2,n:"set_FamilyName",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"FamilyName"},fn:"FamilyName"},{a:2,n:"Gender",t:16,rt:$n[0].String,g:{a:2,n:"get_Gender",t:8,rt:$n[0].String,fg:"Gender"},s:{a:2,n:"set_Gender",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"Gender"},fn:"Gender"},{a:2,n:"GivenName",t:16,rt:$n[0].String,g:{a:2,n:"get_GivenName",t:8,rt:$n[0].String,fg:"GivenName"},s:{a:2,n:"set_GivenName",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"GivenName"},fn:"GivenName"},{a:2,n:"Loading",t:16,rt:$n[0].Boolean,g:{a:2,n:"get_Loading",t:8,rt:$n[0].Boolean,fg:"Loading",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},s:{a:2,n:"set_Loading",t:8,p:[$n[0].Boolean],rt:$n[0].Void,fs:"Loading"},fn:"Loading"},{a:2,n:"Patient",t:16,rt:Object,g:{a:2,n:"get_Patient",t:8,rt:Object,fg:"Patient"},s:{a:2,n:"set_Patient",t:8,p:[Object],rt:$n[0].Void,fs:"Patient"},fn:"Patient"},{a:2,n:"Phone",t:16,rt:$n[0].String,g:{a:2,n:"get_Phone",t:8,rt:$n[0].String,fg:"Phone"},s:{a:2,n:"set_Phone",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"Phone"},fn:"Phone"},{a:2,n:"PostalCode",t:16,rt:$n[0].String,g:{a:2,n:"get_PostalCode",t:8,rt:$n[0].String,fg:"PostalCode"},s:{a:2,n:"set_PostalCode",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"PostalCode"},fn:"PostalCode"},{a:2,n:"Saving",t:16,rt:$n[0].Boolean,g:{a:2,n:"get_Saving",t:8,rt:$n[0].Boolean,fg:"Saving",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},s:{a:2,n:"set_Saving",t:8,p:[$n[0].Boolean],rt:$n[0].Void,fs:"Saving"},fn:"Saving"},{a:2,n:"State",t:16,rt:$n[0].String,g:{a:2,n:"get_State",t:8,rt:$n[0].String,fg:"State"},s:{a:2,n:"set_State",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"State"},fn:"State"},{a:2,n:"Success",t:16,rt:$n[0].String,g:{a:2,n:"get_Success",t:8,rt:$n[0].String,fg:"Success"},s:{a:2,n:"set_Success",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"Success"},fn:"Success"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Boolean,sn:"Active",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"AddressLine"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"BirthDate"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"City"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"Country"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"Email"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"Error"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"FamilyName"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"Gender"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"GivenName"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Boolean,sn:"Loading",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:Object,sn:"Patient"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"Phone"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"PostalCode"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Boolean,sn:"Saving",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"State"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"Success"}]}},$n);$m("Dashboard.Pages.EditPatientPage",function(){return{att:1048961,a:2,s:!0,m:[{a:1,n:"LoadPatient",is:!0,t:8,pi:[{n:"patientId",pt:$n[0].String,ps:0},{n:"setState",pt:Function,ps:1}],sn:"LoadPatient",rt:$n[0].Void,p:[$n[0].String,Function]},{a:2,n:"Render",is:!0,t:8,pi:[{n:"patientId",pt:$n[0].String,ps:0},{n:"onBack",pt:Function,ps:1}],sn:"Render",rt:Object,p:[$n[0].String,Function]},{a:1,n:"RenderCheckboxField",is:!0,t:8,pi:[{n:"label",pt:$n[0].String,ps:0},{n:"id",pt:$n[0].String,ps:1},{n:"value",pt:$n[0].Boolean,ps:2},{n:"onChange",pt:Function,ps:3}],sn:"RenderCheckboxField",rt:Object,p:[$n[0].String,$n[0].String,$n[0].Boolean,Function]},{a:1,n:"RenderErrorState",is:!0,t:8,pi:[{n:"error",pt:$n[0].String,ps:0},{n:"onBack",pt:Function,ps:1}],sn:"RenderErrorState",rt:Object,p:[$n[0].String,Function]},{a:1,n:"RenderForm",is:!0,t:8,pi:[{n:"state",pt:$n[3].EditPatientState,ps:0},{n:"setState",pt:Function,ps:1},{n:"onBack",pt:Function,ps:2}],sn:"RenderForm",rt:Object,p:[$n[3].EditPatientState,Function,Function]},{a:1,n:"RenderFormActions",is:!0,t:8,pi:[{n:"state",pt:$n[3].EditPatientState,ps:0},{n:"onBack",pt:Function,ps:1}],sn:"RenderFormActions",rt:Object,p:[$n[3].EditPatientState,Function]},{a:1,n:"RenderFormSection",is:!0,t:8,pi:[{n:"title",pt:$n[0].String,ps:0},{n:"fields",pt:System.Array.type(Object),ps:1}],sn:"RenderFormSection",rt:Object,p:[$n[0].String,System.Array.type(Object)]},{a:1,n:"RenderHeader",is:!0,t:8,pi:[{n:"patient",pt:Object,ps:0},{n:"onBack",pt:Function,ps:1}],sn:"RenderHeader",rt:Object,p:[Object,Function]},{a:1,n:"RenderInputField",is:!0,t:8,pi:[{n:"label",pt:$n[0].String,ps:0},{n:"id",pt:$n[0].String,ps:1},{n:"value",pt:$n[0].String,ps:2},{n:"placeholder",pt:$n[0].String,ps:3},{n:"onChange",pt:Function,ps:4},{n:"type",dv:"text",o:!0,pt:$n[0].String,ps:5}],sn:"RenderInputField",rt:Object,p:[$n[0].String,$n[0].String,$n[0].String,$n[0].String,Function,$n[0].String]},{a:1,n:"RenderLoadingState",is:!0,t:8,sn:"RenderLoadingState",rt:Object},{a:1,n:"RenderSelectField",is:!0,t:8,pi:[{n:"label",pt:$n[0].String,ps:0},{n:"id",pt:$n[0].String,ps:1},{n:"value",pt:$n[0].String,ps:2},{n:"options",pt:$n[0].Array.type(System.ValueTuple$2(System.String,System.String)),ps:3},{n:"onChange",pt:Function,ps:4}],sn:"RenderSelectField",rt:Object,p:[$n[0].String,$n[0].String,$n[0].String,$n[0].Array.type(System.ValueTuple$2(System.String,System.String)),Function]},{a:1,n:"SavePatient",is:!0,t:8,pi:[{n:"state",pt:$n[3].EditPatientState,ps:0},{n:"setState",pt:Function,ps:1},{n:"onBack",pt:Function,ps:2}],sn:"SavePatient",rt:$n[0].Void,p:[$n[3].EditPatientState,Function,Function]},{a:1,n:"UpdateActive",is:!0,t:8,pi:[{n:"state",pt:$n[3].EditPatientState,ps:0},{n:"setState",pt:Function,ps:1},{n:"value",pt:$n[0].Boolean,ps:2}],sn:"UpdateActive",rt:$n[0].Void,p:[$n[3].EditPatientState,Function,$n[0].Boolean]},{a:1,n:"UpdateField",is:!0,t:8,pi:[{n:"state",pt:$n[3].EditPatientState,ps:0},{n:"setState",pt:Function,ps:1},{n:"field",pt:$n[0].String,ps:2},{n:"value",pt:$n[0].String,ps:3}],sn:"UpdateField",rt:$n[0].Void,p:[$n[3].EditPatientState,Function,$n[0].String,$n[0].String]}]}},$n);$m("Dashboard.Pages.PatientsState",function(){return{att:1048577,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:"Error",t:16,rt:$n[0].String,g:{a:2,n:"get_Error",t:8,rt:$n[0].String,fg:"Error"},s:{a:2,n:"set_Error",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"Error"},fn:"Error"},{a:2,n:"Loading",t:16,rt:$n[0].Boolean,g:{a:2,n:"get_Loading",t:8,rt:$n[0].Boolean,fg:"Loading",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},s:{a:2,n:"set_Loading",t:8,p:[$n[0].Boolean],rt:$n[0].Void,fs:"Loading"},fn:"Loading"},{a:2,n:"Patients",t:16,rt:System.Array.type(Object),g:{a:2,n:"get_Patients",t:8,rt:System.Array.type(Object),fg:"Patients"},s:{a:2,n:"set_Patients",t:8,p:[System.Array.type(Object)],rt:$n[0].Void,fs:"Patients"},fn:"Patients"},{a:2,n:"SearchQuery",t:16,rt:$n[0].String,g:{a:2,n:"get_SearchQuery",t:8,rt:$n[0].String,fg:"SearchQuery"},s:{a:2,n:"set_SearchQuery",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"SearchQuery"},fn:"SearchQuery"},{a:2,n:"SelectedPatient",t:16,rt:Object,g:{a:2,n:"get_SelectedPatient",t:8,rt:Object,fg:"SelectedPatient"},s:{a:2,n:"set_SelectedPatient",t:8,p:[Object],rt:$n[0].Void,fs:"SelectedPatient"},fn:"SelectedPatient"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"Error"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Boolean,sn:"Loading",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:System.Array.type(Object),sn:"Patients"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"SearchQuery"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:Object,sn:"SelectedPatient"}]}},$n);$m("Dashboard.Pages.PatientsPage",function(){return{att:1048961,a:2,s:!0,m:[{a:1,n:"FirstChar",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0}],sn:"FirstChar",rt:$n[0].String,p:[$n[0].String]},{a:1,n:"GenderBadgeClass",is:!0,t:8,pi:[{n:"gender",pt:$n[0].String,ps:0}],sn:"GenderBadgeClass",rt:$n[0].String,p:[$n[0].String]},{a:1,n:"GetInitials",is:!0,t:8,pi:[{n:"patient",pt:Object,ps:0}],sn:"GetInitials",rt:$n[0].String,p:[Object]},{a:1,n:"HandleSearch",is:!0,t:8,pi:[{n:"query",pt:$n[0].String,ps:0},{n:"setState",pt:Function,ps:1}],sn:"HandleSearch",rt:$n[0].Void,p:[$n[0].String,Function]},{a:1,n:"LoadPatients",is:!0,t:8,pi:[{n:"setState",pt:Function,ps:0}],sn:"LoadPatients",rt:$n[0].Void,p:[Function]},{a:2,n:"Render",is:!0,t:8,pi:[{n:"onEditPatient",dv:null,o:!0,pt:Function,ps:0}],sn:"Render",rt:Object,p:[Function]},{a:1,n:"RenderActions",is:!0,t:8,pi:[{n:"patient",pt:Object,ps:0},{n:"onSelect",pt:Function,ps:1}],sn:"RenderActions",rt:Object,p:[Object,Function]},{a:1,n:"RenderCell",is:!0,t:8,pi:[{n:"patient",pt:Object,ps:0},{n:"key",pt:$n[0].String,ps:1},{n:"onSelect",pt:Function,ps:2}],sn:"RenderCell",rt:Object,p:[Object,$n[0].String,Function]},{a:1,n:"RenderContact",is:!0,t:8,pi:[{n:"patient",pt:Object,ps:0}],sn:"RenderContact",rt:Object,p:[Object]},{a:1,n:"RenderError",is:!0,t:8,pi:[{n:"message",pt:$n[0].String,ps:0}],sn:"RenderError",rt:Object,p:[$n[0].String]},{a:1,n:"RenderGender",is:!0,t:8,pi:[{n:"gender",pt:$n[0].String,ps:0}],sn:"RenderGender",rt:Object,p:[$n[0].String]},{a:1,n:"RenderPatientName",is:!0,t:8,pi:[{n:"patient",pt:Object,ps:0}],sn:"RenderPatientName",rt:Object,p:[Object]},{a:1,n:"RenderPatientTable",is:!0,t:8,pi:[{n:"patients",pt:System.Array.type(Object),ps:0},{n:"onSelect",pt:Function,ps:1}],sn:"RenderPatientTable",rt:Object,p:[System.Array.type(Object),Function]},{a:1,n:"RenderStatus",is:!0,t:8,pi:[{n:"active",pt:$n[0].Boolean,ps:0}],sn:"RenderStatus",rt:Object,p:[$n[0].Boolean]},{a:1,n:"SelectPatient",is:!0,t:8,pi:[{n:"patient",pt:Object,ps:0},{n:"setState",pt:Function,ps:1}],sn:"SelectPatient",rt:$n[0].Void,p:[Object,Function]},{a:1,n:"_onEditPatient",is:!0,t:4,rt:Function,sn:"_onEditPatient"}]}},$n);$m("Dashboard.Pages.PractitionersState",function(){return{att:1048577,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:"Error",t:16,rt:$n[0].String,g:{a:2,n:"get_Error",t:8,rt:$n[0].String,fg:"Error"},s:{a:2,n:"set_Error",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"Error"},fn:"Error"},{a:2,n:"Loading",t:16,rt:$n[0].Boolean,g:{a:2,n:"get_Loading",t:8,rt:$n[0].Boolean,fg:"Loading",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},s:{a:2,n:"set_Loading",t:8,p:[$n[0].Boolean],rt:$n[0].Void,fs:"Loading"},fn:"Loading"},{a:2,n:"Practitioners",t:16,rt:System.Array.type(Object),g:{a:2,n:"get_Practitioners",t:8,rt:System.Array.type(Object),fg:"Practitioners"},s:{a:2,n:"set_Practitioners",t:8,p:[System.Array.type(Object)],rt:$n[0].Void,fs:"Practitioners"},fn:"Practitioners"},{a:2,n:"SpecialtyFilter",t:16,rt:$n[0].String,g:{a:2,n:"get_SpecialtyFilter",t:8,rt:$n[0].String,fg:"SpecialtyFilter"},s:{a:2,n:"set_SpecialtyFilter",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"SpecialtyFilter"},fn:"SpecialtyFilter"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"Error"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Boolean,sn:"Loading",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:System.Array.type(Object),sn:"Practitioners"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"SpecialtyFilter"}]}},$n);$m("Dashboard.Pages.PractitionersPage",function(){return{att:1048961,a:2,s:!0,m:[{a:1,n:"FilterBySpecialty",is:!0,t:8,pi:[{n:"specialty",pt:$n[0].String,ps:0},{n:"setState",pt:Function,ps:1}],sn:"FilterBySpecialty",rt:$n[0].Void,p:[$n[0].String,Function]},{a:1,n:"FirstChar",is:!0,t:8,pi:[{n:"s",pt:$n[0].String,ps:0}],sn:"FirstChar",rt:$n[0].String,p:[$n[0].String]},{a:1,n:"GetInitials",is:!0,t:8,pi:[{n:"p",pt:Object,ps:0}],sn:"GetInitials",rt:$n[0].String,p:[Object]},{a:1,n:"LoadPractitioners",is:!0,t:8,pi:[{n:"setState",pt:Function,ps:0}],sn:"LoadPractitioners",rt:$n[0].Void,p:[Function]},{a:2,n:"Render",is:!0,t:8,sn:"Render",rt:Object},{a:1,n:"RenderDetail",is:!0,t:8,pi:[{n:"label",pt:$n[0].String,ps:0},{n:"value",pt:$n[0].String,ps:1}],sn:"RenderDetail",rt:Object,p:[$n[0].String,$n[0].String]},{a:1,n:"RenderEmpty",is:!0,t:8,sn:"RenderEmpty",rt:Object},{a:1,n:"RenderError",is:!0,t:8,pi:[{n:"message",pt:$n[0].String,ps:0}],sn:"RenderError",rt:Object,p:[$n[0].String]},{a:1,n:"RenderLoadingGrid",is:!0,t:8,sn:"RenderLoadingGrid",rt:Object},{a:1,n:"RenderPractitionerCard",is:!0,t:8,pi:[{n:"practitioner",pt:Object,ps:0}],sn:"RenderPractitionerCard",rt:Object,p:[Object]},{a:1,n:"RenderPractitionerGrid",is:!0,t:8,pi:[{n:"practitioners",pt:System.Array.type(Object),ps:0}],sn:"RenderPractitionerGrid",rt:Object,p:[System.Array.type(Object)]}]}},$n);$m("Dashboard.Models.SemanticSearchRequest",function(){return{att:1048577,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:"IncludeAchi",t:16,rt:$n[0].Boolean,g:{a:2,n:"get_IncludeAchi",t:8,rt:$n[0].Boolean,fg:"IncludeAchi",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},s:{a:2,n:"set_IncludeAchi",t:8,p:[$n[0].Boolean],rt:$n[0].Void,fs:"IncludeAchi"},fn:"IncludeAchi"},{a:2,n:"Limit",t:16,rt:$n[0].Int32,g:{a:2,n:"get_Limit",t:8,rt:$n[0].Int32,fg:"Limit",box:function($v){return H5.box($v,System.Int32)}},s:{a:2,n:"set_Limit",t:8,p:[$n[0].Int32],rt:$n[0].Void,fs:"Limit"},fn:"Limit"},{a:2,n:"Query",t:16,rt:$n[0].String,g:{a:2,n:"get_Query",t:8,rt:$n[0].String,fg:"Query"},s:{a:2,n:"set_Query",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"Query"},fn:"Query"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Boolean,sn:"IncludeAchi",box:function($v){return H5.box($v,System.Boolean,System.Boolean.toString)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].Int32,sn:"Limit",box:function($v){return H5.box($v,System.Int32)}},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"Query"}]}},$n);$m("Dashboard.Components.Column",function(){return{att:1048577,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:"ClassName",t:16,rt:$n[0].String,g:{a:2,n:"get_ClassName",t:8,rt:$n[0].String,fg:"ClassName"},s:{a:2,n:"set_ClassName",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"ClassName"},fn:"ClassName"},{a:2,n:"Header",t:16,rt:$n[0].String,g:{a:2,n:"get_Header",t:8,rt:$n[0].String,fg:"Header"},s:{a:2,n:"set_Header",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"Header"},fn:"Header"},{a:2,n:"Key",t:16,rt:$n[0].String,g:{a:2,n:"get_Key",t:8,rt:$n[0].String,fg:"Key"},s:{a:2,n:"set_Key",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"Key"},fn:"Key"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"ClassName"},{a:1,backing:!0,n:"
k__BackingField",t:4,rt:$n[0].String,sn:"Header"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"Key"}]}},$n);$m("Dashboard.Components.DataTable",function(){return{att:1048961,a:2,s:!0,m:[{a:2,n:"Render",is:!0,t:8,pi:[{n:"columns",pt:System.Array.type(Dashboard.Components.Column),ps:0},{n:"data",pt:System.Array.type(System.Object),ps:1},{n:"getKey",pt:Function,ps:2},{n:"renderCell",pt:Function,ps:3},{n:"onRowClick",dv:null,o:!0,pt:Function,ps:4}],tpc:1,tprm:["T"],sn:"Render",rt:Object,p:[System.Array.type(Dashboard.Components.Column),System.Array.type(System.Object),Function,Function,Function]},{a:2,n:"RenderEmpty",is:!0,t:8,pi:[{n:"message",dv:"No data available",o:!0,pt:$n[0].String,ps:0}],sn:"RenderEmpty",rt:Object,p:[$n[0].String]},{a:2,n:"RenderLoading",is:!0,t:8,pi:[{n:"rows",dv:5,o:!0,pt:$n[0].Int32,ps:0},{n:"columns",dv:4,o:!0,pt:$n[0].Int32,ps:1}],sn:"RenderLoading",rt:Object,p:[$n[0].Int32,$n[0].Int32]}]}},$n);$m("Dashboard.Components.Header",function(){return{att:1048961,a:2,s:!0,m:[{a:2,n:"Render",is:!0,t:8,pi:[{n:"title",pt:$n[0].String,ps:0},{n:"searchQuery",dv:null,o:!0,pt:$n[0].String,ps:1},{n:"onSearchChange",dv:null,o:!0,pt:Function,ps:2},{n:"notificationCount",dv:0,o:!0,pt:$n[0].Int32,ps:3}],sn:"Render",rt:Object,p:[$n[0].String,$n[0].String,Function,$n[0].Int32]},{a:1,n:"RenderNotificationButton",is:!0,t:8,pi:[{n:"count",pt:$n[0].Int32,ps:0}],sn:"RenderNotificationButton",rt:Object,p:[$n[0].Int32]},{a:1,n:"RenderUserAvatar",is:!0,t:8,sn:"RenderUserAvatar",rt:Object}]}},$n);$m("Dashboard.Components.Icons",function(){return{att:1048961,a:2,s:!0,m:[{a:2,n:"Activity",is:!0,t:8,sn:"Activity",rt:Object},{a:2,n:"Bell",is:!0,t:8,sn:"Bell",rt:Object},{a:2,n:"Calendar",is:!0,t:8,sn:"Calendar",rt:Object},{a:2,n:"Check",is:!0,t:8,sn:"Check",rt:Object},{a:2,n:"ChevronLeft",is:!0,t:8,sn:"ChevronLeft",rt:Object},{a:2,n:"ChevronRight",is:!0,t:8,sn:"ChevronRight",rt:Object},{a:2,n:"Clipboard",is:!0,t:8,sn:"Clipboard",rt:Object},{a:2,n:"Code",is:!0,t:8,sn:"Code",rt:Object},{a:2,n:"Copy",is:!0,t:8,sn:"Copy",rt:Object},{a:2,n:"Edit",is:!0,t:8,sn:"Edit",rt:Object},{a:2,n:"Eye",is:!0,t:8,sn:"Eye",rt:Object},{a:2,n:"FileText",is:!0,t:8,sn:"FileText",rt:Object},{a:2,n:"Heart",is:!0,t:8,sn:"Heart",rt:Object},{a:2,n:"Home",is:!0,t:8,sn:"Home",rt:Object},{a:2,n:"Menu",is:!0,t:8,sn:"Menu",rt:Object},{a:2,n:"Pill",is:!0,t:8,sn:"Pill",rt:Object},{a:2,n:"Plus",is:!0,t:8,sn:"Plus",rt:Object},{a:2,n:"Refresh",is:!0,t:8,sn:"Refresh",rt:Object},{a:2,n:"Search",is:!0,t:8,sn:"Search",rt:Object},{a:2,n:"Settings",is:!0,t:8,sn:"Settings",rt:Object},{a:2,n:"Sparkles",is:!0,t:8,sn:"Sparkles",rt:Object},{a:2,n:"Trash",is:!0,t:8,sn:"Trash",rt:Object},{a:2,n:"TrendDown",is:!0,t:8,sn:"TrendDown",rt:Object},{a:2,n:"TrendUp",is:!0,t:8,sn:"TrendUp",rt:Object},{a:2,n:"UserDoctor",is:!0,t:8,sn:"UserDoctor",rt:Object},{a:2,n:"Users",is:!0,t:8,sn:"Users",rt:Object},{a:2,n:"X",is:!0,t:8,sn:"X",rt:Object}]}},$n);$m("Dashboard.Components.TrendDirection",function(){return{att:257,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:"Down",is:!0,t:4,rt:$n[4].TrendDirection,sn:"Down",box:function($v){return H5.box($v,Dashboard.Components.TrendDirection,System.Enum.toStringFn(Dashboard.Components.TrendDirection))}},{a:2,n:"Neutral",is:!0,t:4,rt:$n[4].TrendDirection,sn:"Neutral",box:function($v){return H5.box($v,Dashboard.Components.TrendDirection,System.Enum.toStringFn(Dashboard.Components.TrendDirection))}},{a:2,n:"Up",is:!0,t:4,rt:$n[4].TrendDirection,sn:"Up",box:function($v){return H5.box($v,Dashboard.Components.TrendDirection,System.Enum.toStringFn(Dashboard.Components.TrendDirection))}}]}},$n);$m("Dashboard.Components.MetricCardProps",function(){return{att:1048577,a:2,m:[{a:2,isSynthetic:!0,n:".ctor",t:1,sn:"ctor"},{a:2,n:"Icon",t:16,rt:Function,g:{a:2,n:"get_Icon",t:8,rt:Function,fg:"Icon"},s:{a:2,n:"set_Icon",t:8,p:[Function],rt:$n[0].Void,fs:"Icon"},fn:"Icon"},{a:2,n:"IconColor",t:16,rt:$n[0].String,g:{a:2,n:"get_IconColor",t:8,rt:$n[0].String,fg:"IconColor"},s:{a:2,n:"set_IconColor",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"IconColor"},fn:"IconColor"},{a:2,n:"Label",t:16,rt:$n[0].String,g:{a:2,n:"get_Label",t:8,rt:$n[0].String,fg:"Label"},s:{a:2,n:"set_Label",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"Label"},fn:"Label"},{a:2,n:"Trend",t:16,rt:$n[4].TrendDirection,g:{a:2,n:"get_Trend",t:8,rt:$n[4].TrendDirection,fg:"Trend",box:function($v){return H5.box($v,Dashboard.Components.TrendDirection,System.Enum.toStringFn(Dashboard.Components.TrendDirection))}},s:{a:2,n:"set_Trend",t:8,p:[$n[4].TrendDirection],rt:$n[0].Void,fs:"Trend"},fn:"Trend"},{a:2,n:"TrendValue",t:16,rt:$n[0].String,g:{a:2,n:"get_TrendValue",t:8,rt:$n[0].String,fg:"TrendValue"},s:{a:2,n:"set_TrendValue",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"TrendValue"},fn:"TrendValue"},{a:2,n:"Value",t:16,rt:$n[0].String,g:{a:2,n:"get_Value",t:8,rt:$n[0].String,fg:"Value"},s:{a:2,n:"set_Value",t:8,p:[$n[0].String],rt:$n[0].Void,fs:"Value"},fn:"Value"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:Function,sn:"Icon"},{a:1,backing:!0,n:"k__BackingField",t:4,rt:$n[0].String,sn:"IconColor"},{a:1,backing:!0,n:"