From 0f29aacf241a3c58a06737f54596f39255dd0cb4 Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Tue, 17 Sep 2024 15:51:50 +0100 Subject: [PATCH] Making SDK non-static (#116) * initial burn * fix: Minor fixes, some pending * fix: Minor fix + DeepClean target * setup things to be injected * things compile and activites are instanced * compiles except tests * tests compile * fmt * fix merge * Activities are now an interface * fmt * fully remove logging DLL * clean up * fix tests * more cleanup * Fix integration tests * clean up hash tests * clean up path provider * more cleanup for path * merge fixes * Merge fixes * remove some extra classes --------- Co-authored-by: Alan Rynne --- Directory.Build.targets | 6 + Directory.Packages.props | 11 +- Speckle.Sdk.sln | 14 - src/Speckle.Objects/packages.lock.json | 161 +++- src/Speckle.Sdk.Logging/Consts.cs | 38 - src/Speckle.Sdk.Logging/ISpeckleLogger.cs | 19 - src/Speckle.Sdk.Logging/LogBuilder.cs | 197 ----- src/Speckle.Sdk.Logging/LogExtensions.cs | 37 - .../Speckle.Sdk.Logging.csproj | 39 - src/Speckle.Sdk.Logging/SpeckleActivity.cs | 26 - .../SpeckleActivityFactory.cs | 19 - src/Speckle.Sdk.Logging/SpeckleLog.cs | 12 - .../SpeckleLogConfiguration.cs | 24 - src/Speckle.Sdk.Logging/SpeckleLogLevel.cs | 39 - src/Speckle.Sdk.Logging/SpeckleLogger.cs | 59 -- src/Speckle.Sdk.Logging/packages.lock.json | 753 ------------------ src/Speckle.Sdk/Api/GraphQL/Client.cs | 50 +- src/Speckle.Sdk/Api/GraphQL/ClientFactory.cs | 19 + .../Client.ActivityOperations.cs | 65 -- .../Client.BranchOperations.cs | 238 ------ .../Client.CommentOperations.cs | 106 --- .../Client.CommitOperations.cs | 171 ---- .../Client.ObjectOperations.cs | 69 -- .../Client.ServerOperations.cs | 39 - .../Client.StreamOperations.cs | 376 --------- .../Client.UserOperations.cs | 50 -- .../Client.Subscriptions.Branch.cs | 16 - .../Client.Subscriptions.Commit.cs | 25 - .../Client.Subscriptions.Stream.cs | 22 - .../Api/GraphQL/Legacy/LegacyGraphQLModels.cs | 367 --------- .../Api/GraphQL/Legacy/SubscriptionModels.cs | 100 --- .../Models/PendingStreamCollaborator.cs | 6 - .../Api/GraphQL/Models/ServerInfo.cs | 6 +- src/Speckle.Sdk/Api/GraphQL/Models/User.cs | 2 - src/Speckle.Sdk/Api/Helpers.cs | 75 -- .../Api/Operations/Operations.Receive.cs | 23 +- .../Api/Operations/Operations.Send.cs | 20 +- .../Api/Operations/Operations.Serialize.cs | 10 +- src/Speckle.Sdk/Api/Operations/Operations.cs | 6 +- src/Speckle.Sdk/Credentials/Account.cs | 6 - src/Speckle.Sdk/Credentials/AccountManager.cs | 121 +-- src/Speckle.Sdk/Credentials/Responses.cs | 3 - src/Speckle.Sdk/Credentials/StreamWrapper.cs | 506 ------------ src/Speckle.Sdk/Helpers/Http.cs | 152 +--- .../Helpers/SpeckleHttpClientHandler.cs | 12 +- .../SpeckleHttpClientHandlerFactory.cs | 51 ++ src/Speckle.Sdk/Logging/Analytics.cs | 344 -------- .../Logging/ISdkActivity.cs} | 6 +- .../Logging/ISdkActivityFactory.cs | 13 + .../Logging/SpecklePathProvider.cs} | 96 +-- src/Speckle.Sdk/Models/Base.cs | 20 +- src/Speckle.Sdk/Models/CommitObjectBuilder.cs | 170 ---- src/Speckle.Sdk/Models/DynamicBase.cs | 12 +- src/Speckle.Sdk/ScrutorFunctions.cs | 113 +++ .../SpeckleObjectDeserializer.cs | 2 +- .../Serialisation/SpeckleObjectSerializer.cs | 29 +- .../Serialisation/Utilities/ValueConverter.cs | 29 +- src/Speckle.Sdk/ServiceRegistration.cs | 59 ++ src/Speckle.Sdk/Setup.cs | 93 --- src/Speckle.Sdk/Speckle.Sdk.csproj | 9 +- src/Speckle.Sdk/SpeckleConfiguration.cs | 11 - src/Speckle.Sdk/Transports/MemoryTransport.cs | 1 - src/Speckle.Sdk/Transports/ServerTransport.cs | 29 +- .../Transports/ServerTransportFactory.cs | 8 +- .../ServerUtils/ParallelServerAPI.cs | 10 +- .../Transports/ServerUtils/ServerAPI.cs | 26 +- src/Speckle.Sdk/packages.lock.json | 149 ++++ tests/Speckle.LongSendProblem/Program.cs | 70 -- .../Speckle.LongSendProblem.csproj | 14 - .../packages.lock.json | 204 ----- .../packages.lock.json | 75 +- .../SerializationTests.cs | 3 +- .../packages.lock.json | 75 +- .../Api/GraphQL/Legacy/LegacyAPITests.cs | 495 ------------ .../Credentials/UserServerInfoTests.cs | 32 +- .../Speckle.Sdk.Tests.Integration/Fixtures.cs | 35 +- .../GraphQLCLient.cs | 14 +- .../MemoryTransportTests.cs | 10 +- .../ServerTransportTests.cs | 175 ---- .../packages.lock.json | 75 +- .../Benchmarks/GeneralDeserializerTest.cs | 13 +- .../Benchmarks/GeneralSerializerTest.cs | 17 +- .../Speckle.Sdk.Tests.Performance.csproj | 4 +- .../TestDataHelper.cs | 33 +- .../packages.lock.json | 125 ++- .../Api/GraphQLClient.cs | 21 +- .../Api/HelpersTests.cs | 35 - .../Api/Operations/ClosureTests.cs | 12 +- .../OperationsReceiveTests.Exceptional.cs | 12 +- .../Api/Operations/OperationsReceiveTests.cs | 26 +- .../Api/Operations/SendObjectReferences.cs | 22 +- .../Api/Operations/SendReceiveLocal.cs | 40 +- .../Api/Operations/SerializationTests.cs | 60 +- .../AccountServerMigrationTests.cs | 7 +- .../Credentials/Accounts.cs | 22 +- .../Credentials/FE2WrapperTests.cs | 68 -- .../Credentials/StreamWrapperTests.cs | 82 -- tests/Speckle.Sdk.Tests.Unit/Helpers/Path.cs | 9 - .../Models/UtilitiesTests.cs | 23 +- .../SerializerBreakingChanges.cs | 18 +- .../SerializerNonBreakingChanges.cs | 65 +- .../Serialisation/SimpleRoundTripTests.cs | 18 +- .../Speckle.Sdk.Tests.Unit/packages.lock.json | 75 +- 103 files changed, 1485 insertions(+), 5994 deletions(-) delete mode 100644 src/Speckle.Sdk.Logging/Consts.cs delete mode 100644 src/Speckle.Sdk.Logging/ISpeckleLogger.cs delete mode 100644 src/Speckle.Sdk.Logging/LogBuilder.cs delete mode 100644 src/Speckle.Sdk.Logging/LogExtensions.cs delete mode 100644 src/Speckle.Sdk.Logging/Speckle.Sdk.Logging.csproj delete mode 100644 src/Speckle.Sdk.Logging/SpeckleActivity.cs delete mode 100644 src/Speckle.Sdk.Logging/SpeckleActivityFactory.cs delete mode 100644 src/Speckle.Sdk.Logging/SpeckleLog.cs delete mode 100644 src/Speckle.Sdk.Logging/SpeckleLogConfiguration.cs delete mode 100644 src/Speckle.Sdk.Logging/SpeckleLogLevel.cs delete mode 100644 src/Speckle.Sdk.Logging/SpeckleLogger.cs delete mode 100644 src/Speckle.Sdk.Logging/packages.lock.json create mode 100644 src/Speckle.Sdk/Api/GraphQL/ClientFactory.cs delete mode 100644 src/Speckle.Sdk/Api/GraphQL/Legacy/Client.GraphqlCleintOperations/Client.ActivityOperations.cs delete mode 100644 src/Speckle.Sdk/Api/GraphQL/Legacy/Client.GraphqlCleintOperations/Client.BranchOperations.cs delete mode 100644 src/Speckle.Sdk/Api/GraphQL/Legacy/Client.GraphqlCleintOperations/Client.CommentOperations.cs delete mode 100644 src/Speckle.Sdk/Api/GraphQL/Legacy/Client.GraphqlCleintOperations/Client.CommitOperations.cs delete mode 100644 src/Speckle.Sdk/Api/GraphQL/Legacy/Client.GraphqlCleintOperations/Client.ObjectOperations.cs delete mode 100644 src/Speckle.Sdk/Api/GraphQL/Legacy/Client.GraphqlCleintOperations/Client.ServerOperations.cs delete mode 100644 src/Speckle.Sdk/Api/GraphQL/Legacy/Client.GraphqlCleintOperations/Client.StreamOperations.cs delete mode 100644 src/Speckle.Sdk/Api/GraphQL/Legacy/Client.GraphqlCleintOperations/Client.UserOperations.cs delete mode 100644 src/Speckle.Sdk/Api/GraphQL/Legacy/Client.Subscriptions/Client.Subscriptions.Branch.cs delete mode 100644 src/Speckle.Sdk/Api/GraphQL/Legacy/Client.Subscriptions/Client.Subscriptions.Commit.cs delete mode 100644 src/Speckle.Sdk/Api/GraphQL/Legacy/Client.Subscriptions/Client.Subscriptions.Stream.cs delete mode 100644 src/Speckle.Sdk/Api/GraphQL/Legacy/LegacyGraphQLModels.cs delete mode 100644 src/Speckle.Sdk/Api/GraphQL/Legacy/SubscriptionModels.cs delete mode 100644 src/Speckle.Sdk/Api/Helpers.cs delete mode 100644 src/Speckle.Sdk/Credentials/StreamWrapper.cs create mode 100644 src/Speckle.Sdk/Helpers/SpeckleHttpClientHandlerFactory.cs delete mode 100644 src/Speckle.Sdk/Logging/Analytics.cs rename src/{Speckle.Sdk.Logging/ISpeckleActivity.cs => Speckle.Sdk/Logging/ISdkActivity.cs} (78%) create mode 100644 src/Speckle.Sdk/Logging/ISdkActivityFactory.cs rename src/{Speckle.Sdk.Logging/Path.cs => Speckle.Sdk/Logging/SpecklePathProvider.cs} (53%) delete mode 100644 src/Speckle.Sdk/Models/CommitObjectBuilder.cs create mode 100644 src/Speckle.Sdk/ScrutorFunctions.cs create mode 100644 src/Speckle.Sdk/ServiceRegistration.cs delete mode 100644 src/Speckle.Sdk/Setup.cs delete mode 100644 src/Speckle.Sdk/SpeckleConfiguration.cs delete mode 100644 tests/Speckle.LongSendProblem/Program.cs delete mode 100644 tests/Speckle.LongSendProblem/Speckle.LongSendProblem.csproj delete mode 100644 tests/Speckle.LongSendProblem/packages.lock.json delete mode 100644 tests/Speckle.Sdk.Tests.Integration/Api/GraphQL/Legacy/LegacyAPITests.cs delete mode 100644 tests/Speckle.Sdk.Tests.Integration/ServerTransportTests.cs delete mode 100644 tests/Speckle.Sdk.Tests.Unit/Api/HelpersTests.cs delete mode 100644 tests/Speckle.Sdk.Tests.Unit/Credentials/FE2WrapperTests.cs delete mode 100644 tests/Speckle.Sdk.Tests.Unit/Credentials/StreamWrapperTests.cs diff --git a/Directory.Build.targets b/Directory.Build.targets index 8b4299de..db7cc978 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -11,4 +11,10 @@ false + + + + + + diff --git a/Directory.Packages.props b/Directory.Packages.props index 3f941964..a52bde2e 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -5,27 +5,20 @@ - + + - - - - - - - - diff --git a/Speckle.Sdk.sln b/Speckle.Sdk.sln index b2d90631..bb0e5bbd 100644 --- a/Speckle.Sdk.sln +++ b/Speckle.Sdk.sln @@ -40,12 +40,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{ .github\workflows\ci.yml = .github\workflows\ci.yml EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Speckle.Sdk.Logging", "src\Speckle.Sdk.Logging\Speckle.Sdk.Logging.csproj", "{156313B4-B588-4363-A0ED-5AB3A55AA4E8}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Speckle.Sdk.Tests.Performance", "tests\Speckle.Sdk.Tests.Performance\Speckle.Sdk.Tests.Performance.csproj", "{870E3396-E6F7-43AE-B120-E651FA4F46BD}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Speckle.LongSendProblem", "tests\Speckle.LongSendProblem\Speckle.LongSendProblem.csproj", "{6B8D2DD8-AD20-4021-975C-6FDE71DC425B}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -84,14 +80,6 @@ Global {4FB41A6D-D139-4111-8115-E3F9F6BEAF24}.Debug|Any CPU.Build.0 = Debug|Any CPU {4FB41A6D-D139-4111-8115-E3F9F6BEAF24}.Release|Any CPU.ActiveCfg = Release|Any CPU {4FB41A6D-D139-4111-8115-E3F9F6BEAF24}.Release|Any CPU.Build.0 = Release|Any CPU - {156313B4-B588-4363-A0ED-5AB3A55AA4E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {156313B4-B588-4363-A0ED-5AB3A55AA4E8}.Debug|Any CPU.Build.0 = Debug|Any CPU - {156313B4-B588-4363-A0ED-5AB3A55AA4E8}.Release|Any CPU.ActiveCfg = Release|Any CPU - {156313B4-B588-4363-A0ED-5AB3A55AA4E8}.Release|Any CPU.Build.0 = Release|Any CPU - {6B8D2DD8-AD20-4021-975C-6FDE71DC425B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6B8D2DD8-AD20-4021-975C-6FDE71DC425B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6B8D2DD8-AD20-4021-975C-6FDE71DC425B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6B8D2DD8-AD20-4021-975C-6FDE71DC425B}.Release|Any CPU.Build.0 = Release|Any CPU {870E3396-E6F7-43AE-B120-E651FA4F46BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {870E3396-E6F7-43AE-B120-E651FA4F46BD}.Debug|Any CPU.Build.0 = Debug|Any CPU {870E3396-E6F7-43AE-B120-E651FA4F46BD}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -106,8 +94,6 @@ Global {AA1E1E51-49AE-4F71-84B1-938E19695BE0} = {35047EE7-AD1D-4741-80A7-8F0E874718E9} {4FB41A6D-D139-4111-8115-E3F9F6BEAF24} = {35047EE7-AD1D-4741-80A7-8F0E874718E9} {B623BD21-5CAA-43F9-A539-1835276C220E} = {DA2AED52-58F9-471E-8AD8-102FD36129E3} - {156313B4-B588-4363-A0ED-5AB3A55AA4E8} = {5CB96C27-FC5B-4A41-86B6-951AF99B8116} - {6B8D2DD8-AD20-4021-975C-6FDE71DC425B} = {35047EE7-AD1D-4741-80A7-8F0E874718E9} {870E3396-E6F7-43AE-B120-E651FA4F46BD} = {35047EE7-AD1D-4741-80A7-8F0E874718E9} EndGlobalSection EndGlobal diff --git a/src/Speckle.Objects/packages.lock.json b/src/Speckle.Objects/packages.lock.json index 97bb9b1d..6e39cf83 100644 --- a/src/Speckle.Objects/packages.lock.json +++ b/src/Speckle.Objects/packages.lock.json @@ -81,6 +81,63 @@ "SQLitePCLRaw.core": "2.1.4" } }, + "Microsoft.Extensions.Configuration": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "Lu41BWNmwhKr6LgyQvcYBOge0pPvmiaK8R5UHXX4//wBhonJyWcT2OK1mqYfEM5G7pTf31fPrpIHOT6sN7EGOA==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "3.1.0" + } + }, + "Microsoft.Extensions.Configuration.Abstractions": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "ESz6bVoDQX7sgWdKHF6G9Pq672T8k+19AFb/txDXwdz7MoqaNQj2/in3agm/3qae9V+WvQZH86LLTNVo0it8vQ==", + "dependencies": { + "Microsoft.Extensions.Primitives": "3.1.0" + } + }, + "Microsoft.Extensions.Configuration.Binder": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "o9eELDBfNkR7sUtYysFZ1Q7BQ1mYt27DMkups/3vu7xgPyOpMD+iAfrBZFzUXT2iw0fmFb8s1gfNBZS+IgjKdQ==", + "dependencies": { + "Microsoft.Extensions.Configuration": "3.1.0" + } + }, + "Microsoft.Extensions.DependencyInjection": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "KVkv3aF2MQpmGFRh4xRx2CNbc2sjDFk+lH4ySrjWSOS+XoY1Xc+sJphw3N0iYOpoeCCq8976ceVYDH8sdx2qIQ==", + "dependencies": { + "Microsoft.Bcl.AsyncInterfaces": "1.1.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.0" + } + }, + "Microsoft.Extensions.Logging.Abstractions": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "jjo4YXRx6MIpv6DiRxJjSpl+sPP0+5VW0clMEdLyIAz44PPwrDTFrd5PZckIxIXl1kKZ2KK6IL2nkt0+ug2MQg==" + }, + "Microsoft.Extensions.Options": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "9b6JHY7TAXrSfZ6EEGf+j8XnqKIiMPErfmaNXhJYSCb+BUW2H4RtzkNJvwLJzwgzqBP0wtTjyA6Uw4BPPdmkMw==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.0", + "Microsoft.Extensions.Primitives": "3.1.0", + "System.ComponentModel.Annotations": "4.7.0" + } + }, + "Microsoft.Extensions.Primitives": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "LEKAnX7lhUhSoIc2XraCTK3M4IU/LdVUzCe464Sa4+7F4ZJuXHHRzZli2mDbiT4xzAZhgqXbvfnb5+CNDcQFfg==", + "dependencies": { + "System.Memory": "4.5.2", + "System.Runtime.CompilerServices.Unsafe": "4.7.0" + } + }, "Microsoft.NETCore.Platforms": { "type": "Transitive", "resolved": "1.1.0", @@ -131,6 +188,11 @@ "resolved": "4.5.1", "contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg==" }, + "System.ComponentModel.Annotations": { + "type": "Transitive", + "resolved": "4.7.0", + "contentHash": "0YFqjhp/mYkDGpU0Ye1GjE53HMp9UVfGN7seGpAMttAC0C40v5gw598jCgpbBLMmCo0E5YRLBv5Z2doypO49ZQ==" + }, "System.Memory": { "type": "Transitive", "resolved": "4.5.4", @@ -200,18 +262,16 @@ "GraphQL.Client": "[6.0.0, )", "Microsoft.CSharp": "[4.7.0, )", "Microsoft.Data.Sqlite": "[7.0.7, )", + "Microsoft.Extensions.DependencyInjection.Abstractions": "[3.1.0, )", + "Microsoft.Extensions.Logging": "[3.1.0, )", "Polly": "[7.2.3, )", "Polly.Contrib.WaitAndRetry": "[1.1.1, )", "Polly.Extensions.Http": "[3.0.0, )", "Speckle.DoubleNumerics": "[4.0.1, )", "Speckle.Newtonsoft.Json": "[13.0.2, )", - "Speckle.Sdk.Logging": "[1.0.0, )", "System.Text.Json": "[5.0.2, )" } }, - "speckle.sdk.logging": { - "type": "Project" - }, "GraphQL.Client": { "type": "CentralTransitive", "requested": "[6.0.0, )", @@ -239,6 +299,24 @@ "SQLitePCLRaw.bundle_e_sqlite3": "2.1.4" } }, + "Microsoft.Extensions.DependencyInjection.Abstractions": { + "type": "CentralTransitive", + "requested": "[3.1.0, )", + "resolved": "3.1.0", + "contentHash": "44rDtOf1JXXAFpNT2EXMExaDm/4OJ2RXOL9i9lE4bK427nzC7Exphv+beB6IgluyE2GIoo8zezTStMXI7MQ8WA==" + }, + "Microsoft.Extensions.Logging": { + "type": "CentralTransitive", + "requested": "[3.1.0, )", + "resolved": "3.1.0", + "contentHash": "P+8sKQ8L4ooL79sxxqwFPxGGC3aBrUDLB/dZqhs4J0XjTyrkeeyJQ4D4nzJB6OnAhy78HIIgQ/RbD6upOXLynw==", + "dependencies": { + "Microsoft.Extensions.Configuration.Binder": "3.1.0", + "Microsoft.Extensions.DependencyInjection": "3.1.0", + "Microsoft.Extensions.Logging.Abstractions": "3.1.0", + "Microsoft.Extensions.Options": "3.1.0" + } + }, "Polly": { "type": "CentralTransitive", "requested": "[7.2.3, )", @@ -351,6 +429,57 @@ "SQLitePCLRaw.core": "2.1.4" } }, + "Microsoft.Extensions.Configuration": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "Lu41BWNmwhKr6LgyQvcYBOge0pPvmiaK8R5UHXX4//wBhonJyWcT2OK1mqYfEM5G7pTf31fPrpIHOT6sN7EGOA==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "3.1.0" + } + }, + "Microsoft.Extensions.Configuration.Abstractions": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "ESz6bVoDQX7sgWdKHF6G9Pq672T8k+19AFb/txDXwdz7MoqaNQj2/in3agm/3qae9V+WvQZH86LLTNVo0it8vQ==", + "dependencies": { + "Microsoft.Extensions.Primitives": "3.1.0" + } + }, + "Microsoft.Extensions.Configuration.Binder": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "o9eELDBfNkR7sUtYysFZ1Q7BQ1mYt27DMkups/3vu7xgPyOpMD+iAfrBZFzUXT2iw0fmFb8s1gfNBZS+IgjKdQ==", + "dependencies": { + "Microsoft.Extensions.Configuration": "3.1.0" + } + }, + "Microsoft.Extensions.DependencyInjection": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "KVkv3aF2MQpmGFRh4xRx2CNbc2sjDFk+lH4ySrjWSOS+XoY1Xc+sJphw3N0iYOpoeCCq8976ceVYDH8sdx2qIQ==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.0" + } + }, + "Microsoft.Extensions.Logging.Abstractions": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "jjo4YXRx6MIpv6DiRxJjSpl+sPP0+5VW0clMEdLyIAz44PPwrDTFrd5PZckIxIXl1kKZ2KK6IL2nkt0+ug2MQg==" + }, + "Microsoft.Extensions.Options": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "9b6JHY7TAXrSfZ6EEGf+j8XnqKIiMPErfmaNXhJYSCb+BUW2H4RtzkNJvwLJzwgzqBP0wtTjyA6Uw4BPPdmkMw==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.0", + "Microsoft.Extensions.Primitives": "3.1.0" + } + }, + "Microsoft.Extensions.Primitives": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "LEKAnX7lhUhSoIc2XraCTK3M4IU/LdVUzCe464Sa4+7F4ZJuXHHRzZli2mDbiT4xzAZhgqXbvfnb5+CNDcQFfg==" + }, "Microsoft.SourceLink.Common": { "type": "Transitive", "resolved": "8.0.0", @@ -402,18 +531,16 @@ "GraphQL.Client": "[6.0.0, )", "Microsoft.CSharp": "[4.7.0, )", "Microsoft.Data.Sqlite": "[7.0.7, )", + "Microsoft.Extensions.DependencyInjection.Abstractions": "[3.1.0, )", + "Microsoft.Extensions.Logging": "[3.1.0, )", "Polly": "[7.2.3, )", "Polly.Contrib.WaitAndRetry": "[1.1.1, )", "Polly.Extensions.Http": "[3.0.0, )", "Speckle.DoubleNumerics": "[4.0.1, )", "Speckle.Newtonsoft.Json": "[13.0.2, )", - "Speckle.Sdk.Logging": "[1.0.0, )", "System.Text.Json": "[5.0.2, )" } }, - "speckle.sdk.logging": { - "type": "Project" - }, "GraphQL.Client": { "type": "CentralTransitive", "requested": "[6.0.0, )", @@ -441,6 +568,24 @@ "SQLitePCLRaw.bundle_e_sqlite3": "2.1.4" } }, + "Microsoft.Extensions.DependencyInjection.Abstractions": { + "type": "CentralTransitive", + "requested": "[3.1.0, )", + "resolved": "3.1.0", + "contentHash": "44rDtOf1JXXAFpNT2EXMExaDm/4OJ2RXOL9i9lE4bK427nzC7Exphv+beB6IgluyE2GIoo8zezTStMXI7MQ8WA==" + }, + "Microsoft.Extensions.Logging": { + "type": "CentralTransitive", + "requested": "[3.1.0, )", + "resolved": "3.1.0", + "contentHash": "P+8sKQ8L4ooL79sxxqwFPxGGC3aBrUDLB/dZqhs4J0XjTyrkeeyJQ4D4nzJB6OnAhy78HIIgQ/RbD6upOXLynw==", + "dependencies": { + "Microsoft.Extensions.Configuration.Binder": "3.1.0", + "Microsoft.Extensions.DependencyInjection": "3.1.0", + "Microsoft.Extensions.Logging.Abstractions": "3.1.0", + "Microsoft.Extensions.Options": "3.1.0" + } + }, "Polly": { "type": "CentralTransitive", "requested": "[7.2.3, )", diff --git a/src/Speckle.Sdk.Logging/Consts.cs b/src/Speckle.Sdk.Logging/Consts.cs deleted file mode 100644 index 882153b2..00000000 --- a/src/Speckle.Sdk.Logging/Consts.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System.Reflection; - -namespace Speckle.Sdk.Logging; - -public static class Consts -{ - public const string SERVICE_NAME = "connector.name"; - public const string SERVICE_SLUG = "connector.slug"; - public const string OS_NAME = "os.name"; - public const string OS_TYPE = "os.type"; - public const string OS_SLUG = "os.slug"; - public const string RUNTIME_NAME = "runtime.name"; - - public static readonly string Application = "speckle-connectors"; - public static string Version => Assembly.GetExecutingAssembly().GetPackageVersion(); - - public static string GetPackageVersion(this Assembly assembly) - { - // MinVer https://github.com/adamralph/minver?tab=readme-ov-file#version-numbers - // together with Microsoft.SourceLink.GitHub https://github.com/dotnet/sourcelink - // fills AssemblyInformationalVersionAttribute by - // {majorVersion}.{minorVersion}.{patchVersion}.{pre-release label}.{pre-release version}.{gitHeight}+{Git SHA of current commit} - // Ex: 1.5.0-alpha.1.40+807f703e1b4d9874a92bd86d9f2d4ebe5b5d52e4 - // The following parts are optional: pre-release label, pre-release version, git height, Git SHA of current commit - // For package version, value of AssemblyInformationalVersionAttribute without commit hash is returned. - - var informationalVersion = assembly - .GetCustomAttribute() - ?.InformationalVersion; - if (informationalVersion is null) - { - return String.Empty; - } - - var indexOfPlusSign = informationalVersion.IndexOf('+'); - return indexOfPlusSign > 0 ? informationalVersion[..indexOfPlusSign] : informationalVersion; - } -} diff --git a/src/Speckle.Sdk.Logging/ISpeckleLogger.cs b/src/Speckle.Sdk.Logging/ISpeckleLogger.cs deleted file mode 100644 index 3df1a4af..00000000 --- a/src/Speckle.Sdk.Logging/ISpeckleLogger.cs +++ /dev/null @@ -1,19 +0,0 @@ -namespace Speckle.Sdk.Logging; - -public interface ISpeckleLogger -{ - void Write(SpeckleLogLevel speckleLogLevel, string message, params object?[] arguments); - void Write(SpeckleLogLevel speckleLogLevel, Exception? exception, string message, params object?[] arguments); - - void Debug(string message, params object?[] arguments); - void Debug(Exception? exception, string message, params object?[] arguments); - void Warning(string message, params object?[] arguments); - void Warning(Exception? exception, string message, params object?[] arguments); - void Information(string message, params object?[] arguments); - - void Information(Exception? exception, string message, params object?[] arguments); - - void Error(string message, params object?[] arguments); - void Error(Exception? exception, string message, params object?[] arguments); - void Fatal(Exception? exception, string message, params object?[] arguments); -} diff --git a/src/Speckle.Sdk.Logging/LogBuilder.cs b/src/Speckle.Sdk.Logging/LogBuilder.cs deleted file mode 100644 index 54ed1845..00000000 --- a/src/Speckle.Sdk.Logging/LogBuilder.cs +++ /dev/null @@ -1,197 +0,0 @@ -using System.Diagnostics; -using System.Reflection; -using System.Runtime.InteropServices; -using OpenTelemetry.Exporter; -using OpenTelemetry.Resources; -using OpenTelemetry.Trace; -using Serilog; -using Serilog.Exceptions; -using Serilog.Sinks.OpenTelemetry; - -namespace Speckle.Sdk.Logging; - -public static class LogBuilder -{ - public static IDisposable? Initialize( - string userId, - string applicationAndVersion, - string slug, - SpeckleLogging? speckleLogging, - SpeckleTracing? speckleTracing - ) - { - var resourceBuilder = ResourceBuilder - .CreateEmpty() - .AddService(serviceName: Consts.Application, serviceVersion: Consts.Version) - .AddAttributes( - new List> - { - new(Consts.SERVICE_NAME, applicationAndVersion), - new(Consts.SERVICE_SLUG, slug), - new(Consts.OS_NAME, Environment.OSVersion.ToString()), - new(Consts.OS_TYPE, RuntimeInformation.ProcessArchitecture.ToString()), - new(Consts.OS_SLUG, DetermineHostOsSlug()), - new(Consts.RUNTIME_NAME, RuntimeInformation.FrameworkDescription) - } - ); - var fileVersionInfo = GetFileVersionInfo(); - var serilogLogConfiguration = new LoggerConfiguration() - .MinimumLevel.Is(SpeckleLogger.GetLevel(speckleLogging?.MinimumLevel ?? SpeckleLogLevel.Warning)) - .Enrich.FromLogContext() - .Enrich.WithProperty("id", userId) - .Enrich.WithProperty("version", fileVersionInfo.FileVersion) - .Enrich.WithProperty("productVersion", fileVersionInfo.ProductVersion) - .Enrich.WithProperty("hostOs", DetermineHostOsSlug()) - .Enrich.WithProperty("hostOsVersion", Environment.OSVersion) - .Enrich.WithProperty("hostOsArchitecture", RuntimeInformation.ProcessArchitecture.ToString()) - .Enrich.WithProperty("runtime", RuntimeInformation.FrameworkDescription) - .Enrich.WithExceptionDetails(); - - if (speckleLogging?.File is not null) - { - // TODO: check if we have write permissions to the file. - var logFilePath = SpecklePathProvider.LogFolderPath(applicationAndVersion); - logFilePath = Path.Combine(logFilePath, speckleLogging.File.Path ?? "SpeckleCoreLog.txt"); - serilogLogConfiguration = serilogLogConfiguration.WriteTo.File( - logFilePath, - rollingInterval: RollingInterval.Day, - retainedFileCountLimit: 10 - ); - } - - if (speckleLogging?.Console ?? false) - { - serilogLogConfiguration = serilogLogConfiguration.WriteTo.Console(); - } - - if (speckleLogging?.Otel is not null) - { - serilogLogConfiguration = InitializeOtelLogging(serilogLogConfiguration, speckleLogging.Otel, resourceBuilder); - } - var logger = serilogLogConfiguration.CreateLogger(); - SpeckleLog.SpeckleLogger = logger; - - logger - .ForContext("hostApplication", applicationAndVersion) - .ForContext("userApplicationDataPath", SpecklePathProvider.UserApplicationDataPath()) - .ForContext("installApplicationDataPath", SpecklePathProvider.InstallApplicationDataPath) - .Information( - "Initialized logger inside {hostApplication}/{productVersion}/{version} for user {id}. Path info {userApplicationDataPath} {installApplicationDataPath}." - ); - return InitializeOtelTracing(speckleTracing, resourceBuilder); - } - - private static FileVersionInfo GetFileVersionInfo() - { - var assembly = Assembly.GetExecutingAssembly().Location; - return FileVersionInfo.GetVersionInfo(assembly); - } - - private static string DetermineHostOsSlug() - { - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - return "Windows"; - } - - if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) - { - return "MacOS"; - } - - if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) - { - return "Linux"; - } - - return RuntimeInformation.OSDescription; - } - - private static LoggerConfiguration InitializeOtelLogging( - LoggerConfiguration serilogLogConfiguration, - SpeckleOtelLogging speckleOtelLogging, - ResourceBuilder resourceBuilder - ) => - serilogLogConfiguration.WriteTo.OpenTelemetry(o => - { - o.Protocol = OtlpProtocol.HttpProtobuf; - o.LogsEndpoint = speckleOtelLogging.Endpoint; - o.Headers = speckleOtelLogging.Headers ?? o.Headers; - o.ResourceAttributes = resourceBuilder.Build().Attributes.ToDictionary(x => x.Key, x => x.Value); - }); - - private static IDisposable? InitializeOtelTracing(SpeckleTracing? logConfiguration, ResourceBuilder resourceBuilder) - { - var consoleEnabled = logConfiguration?.Console ?? false; - var otelEnabled = logConfiguration?.Otel?.Enabled ?? false; - if (!consoleEnabled && !otelEnabled) - { - return null; - } - - var tracerProviderBuilder = OpenTelemetry.Sdk.CreateTracerProviderBuilder().AddSource(Consts.Application); - tracerProviderBuilder = tracerProviderBuilder.AddHttpClientInstrumentation( - (options) => - { - options.FilterHttpWebRequest = (httpWebRequest) => - { - // Example: Only collect telemetry about HTTP GET requests. - return httpWebRequest.Method.Equals(HttpMethod.Get.Method); - }; - options.EnrichWithHttpWebRequest = (activity, httpWebRequest) => - { - activity.SetTag("requestVersion", httpWebRequest.ProtocolVersion); - }; - // Note: Only called on .NET Framework. - options.EnrichWithHttpWebResponse = (activity, httpWebResponse) => - { - activity.SetTag("responseVersion", httpWebResponse.ProtocolVersion); - }; - // Note: Only called on .NET & .NET Core runtimes. - options.EnrichWithHttpRequestMessage = (activity, httpRequestMessage) => - { - activity.SetTag("requestVersion", httpRequestMessage.Version); - }; - // Note: Only called on .NET & .NET Core runtimes. - options.EnrichWithHttpResponseMessage = (activity, httpResponseMessage) => - { - activity.SetTag("responseVersion", httpResponseMessage.Version); - }; - // Note: Called for all runtimes. - options.EnrichWithException = (activity, exception) => - { - activity.SetTag("stackTrace", exception.StackTrace); - }; - options.RecordException = true; - } - ); - if (otelEnabled) - { - tracerProviderBuilder = tracerProviderBuilder.AddOtlpExporter(x => ProcessOptions(logConfiguration!, x)); - } - - if (consoleEnabled) - { - tracerProviderBuilder = tracerProviderBuilder.AddConsoleExporter(); - } - - tracerProviderBuilder = tracerProviderBuilder.SetResourceBuilder(resourceBuilder).SetSampler(); - - return tracerProviderBuilder.Build(); - } - - private static void ProcessOptions(SpeckleTracing logConfiguration, OtlpExporterOptions options) - { - options.Protocol = OtlpExportProtocol.HttpProtobuf; - var headers = string.Join(",", logConfiguration.Otel?.Headers?.Select(x => x.Key + "=" + x.Value) ?? []); - if (headers.Length != 0) - { - options.Headers = headers; - } - - if (logConfiguration.Otel?.Endpoint is not null) - { - options.Endpoint = new Uri(logConfiguration.Otel.Endpoint); - } - } -} diff --git a/src/Speckle.Sdk.Logging/LogExtensions.cs b/src/Speckle.Sdk.Logging/LogExtensions.cs deleted file mode 100644 index 71ce99e2..00000000 --- a/src/Speckle.Sdk.Logging/LogExtensions.cs +++ /dev/null @@ -1,37 +0,0 @@ -using Microsoft.Extensions.Logging; - -namespace Speckle.Sdk.Logging; - -public static class LogExtensions -{ - public static void Debug(this ILogger logger, string message, params object?[] arguments) => - logger.LogDebug(message, arguments); - - public static void Debug(this ILogger logger, Exception exception, string message, params object?[] arguments) => - logger.LogDebug(exception, message, arguments); - - public static void Warning(this ILogger logger, string message, params object?[] arguments) => - logger.LogWarning(message, arguments); - - public static void Warning(this ILogger logger, Exception exception, string message, params object?[] arguments) => - logger.LogWarning(exception, message, arguments); - - public static void Information(this ILogger logger, string message, params object?[] arguments) => - logger.LogInformation(message, arguments); - - public static void Information( - this ILogger logger, - Exception exception, - string message, - params object?[] arguments - ) => logger.LogInformation(exception, message, arguments); - - public static void Error(this ILogger logger, string message, params object?[] arguments) => - logger.LogError(message, arguments); - - public static void Error(this ILogger logger, Exception exception, string message, params object?[] arguments) => - logger.LogError(exception, message, arguments); - - public static void Fatal(this ILogger logger, Exception exception, string message, params object?[] arguments) => - logger.LogCritical(exception, message, arguments); -} diff --git a/src/Speckle.Sdk.Logging/Speckle.Sdk.Logging.csproj b/src/Speckle.Sdk.Logging/Speckle.Sdk.Logging.csproj deleted file mode 100644 index 1febf25c..00000000 --- a/src/Speckle.Sdk.Logging/Speckle.Sdk.Logging.csproj +++ /dev/null @@ -1,39 +0,0 @@ - - - - - netstandard2.0;net8.0 - Debug;Release;Local - - - - Debug;Release;Local - true - - - - Speckle.Sdk.Logging - The .NET Logging SDK for Speckle - $(PackageTags) core sdk - - - - true - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - - - - - - diff --git a/src/Speckle.Sdk.Logging/SpeckleActivity.cs b/src/Speckle.Sdk.Logging/SpeckleActivity.cs deleted file mode 100644 index 0f992583..00000000 --- a/src/Speckle.Sdk.Logging/SpeckleActivity.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System.Diagnostics; -using OpenTelemetry.Trace; - -namespace Speckle.Sdk.Logging; - -public sealed class SpeckleActivity(Activity activity) : ISpeckleActivity -{ - public void Dispose() => activity.Dispose(); - - public void SetTag(string key, object? value) => activity.SetTag(key, value); - - public void RecordException(Exception e) => activity.RecordException(e); - - public string TraceId => activity.TraceId.ToString(); - - public void SetStatus(SpeckleActivityStatusCode code) => - activity.SetStatus( - code switch - { - SpeckleActivityStatusCode.Error => ActivityStatusCode.Error, - SpeckleActivityStatusCode.Unset => ActivityStatusCode.Unset, - SpeckleActivityStatusCode.Ok => ActivityStatusCode.Ok, - _ => throw new ArgumentOutOfRangeException(nameof(code), code, null) - } - ); -} diff --git a/src/Speckle.Sdk.Logging/SpeckleActivityFactory.cs b/src/Speckle.Sdk.Logging/SpeckleActivityFactory.cs deleted file mode 100644 index 855fa300..00000000 --- a/src/Speckle.Sdk.Logging/SpeckleActivityFactory.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System.Diagnostics; -using System.Runtime.CompilerServices; - -namespace Speckle.Sdk.Logging; - -public static class SpeckleActivityFactory -{ - private static readonly ActivitySource? s_activitySource = new(Consts.Application, Consts.Version); - - public static ISpeckleActivity? Start(string? name = null, [CallerMemberName] string source = "") - { - var activity = s_activitySource?.StartActivity(name ?? source, ActivityKind.Client); - if (activity is null) - { - return null; - } - return new SpeckleActivity(activity); - } -} diff --git a/src/Speckle.Sdk.Logging/SpeckleLog.cs b/src/Speckle.Sdk.Logging/SpeckleLog.cs deleted file mode 100644 index c5f02ea1..00000000 --- a/src/Speckle.Sdk.Logging/SpeckleLog.cs +++ /dev/null @@ -1,12 +0,0 @@ -using Serilog.Core; - -namespace Speckle.Sdk.Logging; - -public static class SpeckleLog -{ - internal static Serilog.ILogger SpeckleLogger { get; set; } = Serilog.Core.Logger.None; - public static ISpeckleLogger Logger => new SpeckleLogger(SpeckleLogger); - - public static ISpeckleLogger Create(string name) => - new SpeckleLogger(SpeckleLogger.ForContext(Constants.SourceContextPropertyName, name)); -} diff --git a/src/Speckle.Sdk.Logging/SpeckleLogConfiguration.cs b/src/Speckle.Sdk.Logging/SpeckleLogConfiguration.cs deleted file mode 100644 index 9f2d6561..00000000 --- a/src/Speckle.Sdk.Logging/SpeckleLogConfiguration.cs +++ /dev/null @@ -1,24 +0,0 @@ -namespace Speckle.Sdk.Logging; - -/// -/// Configuration object for the Speckle logging system. -/// - -public record SpeckleLogging( - SpeckleLogLevel MinimumLevel = SpeckleLogLevel.Warning, - bool Console = true, - SpeckleFileLogging? File = null, - SpeckleOtelLogging? Otel = null -); - -public record SpeckleFileLogging(string? Path = null, bool Enabled = true); - -public record SpeckleOtelLogging(string Endpoint, bool Enabled = true, Dictionary? Headers = null); - -public record SpeckleTracing(bool Console = false, SpeckleOtelTracing? Otel = null); - -public record SpeckleOtelTracing( - string? Endpoint = null, - bool Enabled = true, - Dictionary? Headers = null -); diff --git a/src/Speckle.Sdk.Logging/SpeckleLogLevel.cs b/src/Speckle.Sdk.Logging/SpeckleLogLevel.cs deleted file mode 100644 index e84ca64e..00000000 --- a/src/Speckle.Sdk.Logging/SpeckleLogLevel.cs +++ /dev/null @@ -1,39 +0,0 @@ -namespace Speckle.Sdk.Logging; - -public enum SpeckleLogLevel -{ - /// - /// Anything and everything you might want to know about - /// a running block of code. - /// - Verbose, - - /// - /// Internal system events that aren't necessarily - /// observable from the outside. - /// - Debug, - - /// - /// The lifeblood of operational intelligence - things - /// happen. - /// - Information, - - /// - /// Service is degraded or endangered. - /// - Warning, - - /// - /// Functionality is unavailable, invariants are broken - /// or data is lost. - /// - Error, - - /// - /// If you have a pager, it goes off when one of these - /// occurs. - /// - Fatal -} diff --git a/src/Speckle.Sdk.Logging/SpeckleLogger.cs b/src/Speckle.Sdk.Logging/SpeckleLogger.cs deleted file mode 100644 index 326fb238..00000000 --- a/src/Speckle.Sdk.Logging/SpeckleLogger.cs +++ /dev/null @@ -1,59 +0,0 @@ -using Serilog; -using Serilog.Events; - -namespace Speckle.Sdk.Logging; - -internal sealed class SpeckleLogger : ISpeckleLogger -{ - private readonly Serilog.ILogger _logger; - - public SpeckleLogger(ILogger logger) - { - _logger = logger; - } - - internal static LogEventLevel GetLevel(SpeckleLogLevel speckleLogLevel) => - speckleLogLevel switch - { - SpeckleLogLevel.Debug => LogEventLevel.Debug, - SpeckleLogLevel.Verbose => LogEventLevel.Verbose, - SpeckleLogLevel.Information => LogEventLevel.Information, - SpeckleLogLevel.Warning => LogEventLevel.Warning, - SpeckleLogLevel.Error => LogEventLevel.Error, - SpeckleLogLevel.Fatal => LogEventLevel.Fatal, - _ => throw new ArgumentOutOfRangeException(nameof(speckleLogLevel), speckleLogLevel, null) - }; - - public void Write(SpeckleLogLevel speckleLogLevel, string message, params object?[] arguments) => - _logger.Write(GetLevel(speckleLogLevel), message, arguments); - - public void Write( - SpeckleLogLevel speckleLogLevel, - Exception? exception, - string message, - params object?[] arguments - ) => _logger.Write(GetLevel(speckleLogLevel), exception, message, arguments); - - public void Debug(string message, params object?[] arguments) => _logger.Debug(message, arguments); - - public void Debug(Exception? exception, string message, params object?[] arguments) => - _logger.Debug(exception, message, arguments); - - public void Warning(string message, params object?[] arguments) => _logger.Warning(message, arguments); - - public void Warning(Exception? exception, string message, params object?[] arguments) => - _logger.Warning(exception, message, arguments); - - public void Information(string message, params object?[] arguments) => _logger.Information(message, arguments); - - public void Information(Exception? exception, string message, params object?[] arguments) => - _logger.Information(exception, message, arguments); - - public void Error(string message, params object?[] arguments) => _logger.Error(message, arguments); - - public void Error(Exception? exception, string message, params object?[] arguments) => - _logger.Error(exception, message, arguments); - - public void Fatal(Exception? exception, string message, params object?[] arguments) => - _logger.Fatal(exception, message, arguments); -} diff --git a/src/Speckle.Sdk.Logging/packages.lock.json b/src/Speckle.Sdk.Logging/packages.lock.json deleted file mode 100644 index 855713a7..00000000 --- a/src/Speckle.Sdk.Logging/packages.lock.json +++ /dev/null @@ -1,753 +0,0 @@ -{ - "version": 2, - "dependencies": { - ".NETStandard,Version=v2.0": { - "GitVersion.MsBuild": { - "type": "Direct", - "requested": "[5.12.0, )", - "resolved": "5.12.0", - "contentHash": "dJuigXycpJNOiLT9or7mkHSkGFHgGW3/p6cNNYEKZBa7Hhp1FdX/cvqYWWYhRLpfoZOedeA7aRbYiOB3vW/dvA==" - }, - "ILRepack.FullAuto": { - "type": "Direct", - "requested": "[1.6.0, )", - "resolved": "1.6.0", - "contentHash": "34qp/HQ0XRIWCjtNGUOslJ6p9eNWqHXZQ+xx1iBCvXy3mj8tEiqIwRG+LubFyKCJITqMh5cpFvFl20/6+Dmy+g==", - "dependencies": { - "ILRepack": "2.0.33" - } - }, - "Microsoft.SourceLink.GitHub": { - "type": "Direct", - "requested": "[8.0.0, )", - "resolved": "8.0.0", - "contentHash": "G5q7OqtwIyGTkeIOAc3u2ZuV/kicQaec5EaRnc0pIeSnh9LUjj+PYQrJYBURvDt7twGl2PKA7nSN0kz1Zw5bnQ==", - "dependencies": { - "Microsoft.Build.Tasks.Git": "8.0.0", - "Microsoft.SourceLink.Common": "8.0.0" - } - }, - "NETStandard.Library": { - "type": "Direct", - "requested": "[2.0.3, )", - "resolved": "2.0.3", - "contentHash": "st47PosZSHrjECdjeIzZQbzivYBJFv6P2nv4cj2ypdI204DO+vZ7l5raGMiX4eXMJ53RfOIg+/s4DHVZ54Nu2A==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0" - } - }, - "OpenTelemetry.Exporter.Console": { - "type": "Direct", - "requested": "[1.9.0, )", - "resolved": "1.9.0", - "contentHash": "TbScDLSc6kcji+/wZYIf8/HBV2SnttzN7PNxr3TYczlmGlU4K2ugujp6seSktEO4OaAvKRd7Y3CG3SKNj0C+1Q==", - "dependencies": { - "OpenTelemetry": "1.9.0", - "System.Text.Encodings.Web": "4.7.2", - "System.Text.Json": "4.7.2" - } - }, - "OpenTelemetry.Exporter.OpenTelemetryProtocol": { - "type": "Direct", - "requested": "[1.9.0, )", - "resolved": "1.9.0", - "contentHash": "qzFOP3V2eYIVbug3U4BJzzidHe9JhAJ42WZ/H8pUp/45Ry3MQQg/+e/ZieClJcxKnpbkXi7dUq1rpvuNp+yBYA==", - "dependencies": { - "Google.Protobuf": "[3.22.5, 4.0.0)", - "Grpc": "[2.44.0, 3.0.0)", - "Microsoft.Extensions.Configuration.Binder": "8.0.1", - "OpenTelemetry": "1.9.0" - } - }, - "OpenTelemetry.Instrumentation.Http": { - "type": "Direct", - "requested": "[1.9.0, )", - "resolved": "1.9.0", - "contentHash": "+ZXppf8Qxz3OdC803T8fB6i8iSscc8PsxMnM/JizSOYmkz+8vGiScEiaBBBFNZtMh2KpA0q+qxwnSwQUkbvzog==", - "dependencies": { - "Microsoft.Extensions.Configuration": "8.0.0", - "Microsoft.Extensions.Options": "8.0.0", - "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.9.0, 2.0.0)" - } - }, - "PolySharp": { - "type": "Direct", - "requested": "[1.14.1, )", - "resolved": "1.14.1", - "contentHash": "mOOmFYwad3MIOL14VCjj02LljyF1GNw1wP0YVlxtcPvqdxjGGMNdNJJxHptlry3MOd8b40Flm8RPOM8JOlN2sQ==" - }, - "Serilog": { - "type": "Direct", - "requested": "[4.0.1, )", - "resolved": "4.0.1", - "contentHash": "pzeDRXdpSLSsgBHpZcmpIDxqMy845Ab4s+dfnBg0sN9h8q/4Wo3vAoe0QCGPze1Q06EVtEPupS+UvLm8iXQmTQ==", - "dependencies": { - "System.Diagnostics.DiagnosticSource": "8.0.1", - "System.Threading.Channels": "8.0.0" - } - }, - "Serilog.Exceptions": { - "type": "Direct", - "requested": "[8.4.0, )", - "resolved": "8.4.0", - "contentHash": "nc/+hUw3lsdo0zCj0KMIybAu7perMx79vu72w0za9Nsi6mWyNkGXxYxakAjWB7nEmYL6zdmhEQRB4oJ2ALUeug==", - "dependencies": { - "Serilog": "2.8.0", - "System.Reflection.TypeExtensions": "4.7.0" - } - }, - "Serilog.Sinks.Console": { - "type": "Direct", - "requested": "[6.0.0, )", - "resolved": "6.0.0", - "contentHash": "fQGWqVMClCP2yEyTXPIinSr5c+CBGUvBybPxjAGcf7ctDhadFhrQw03Mv8rJ07/wR5PDfFjewf2LimvXCDzpbA==", - "dependencies": { - "Serilog": "4.0.0" - } - }, - "Serilog.Sinks.File": { - "type": "Direct", - "requested": "[6.0.0, )", - "resolved": "6.0.0", - "contentHash": "lxjg89Y8gJMmFxVkbZ+qDgjl+T4yC5F7WSLTvA+5q0R04tfKVLRL/EHpYoJ/MEQd2EeCKDuylBIVnAYMotmh2A==", - "dependencies": { - "Serilog": "4.0.0" - } - }, - "Serilog.Sinks.OpenTelemetry": { - "type": "Direct", - "requested": "[4.0.0, )", - "resolved": "4.0.0", - "contentHash": "M4WKDojg8a+msY5qhNGg5PYZ9ZVelcqipkP/CrfDAOvGCZ3MYj+cGXgnTanffYyIoC2onabaOtydqW6lqT/P/w==", - "dependencies": { - "Google.Protobuf": "3.26.1", - "Grpc.Net.Client": "2.62.0", - "Serilog": "4.0.0" - } - }, - "Speckle.InterfaceGenerator": { - "type": "Direct", - "requested": "[0.9.6, )", - "resolved": "0.9.6", - "contentHash": "HKH7tYrYYlCK1ct483hgxERAdVdMtl7gUKW9ijWXxA1UsYR4Z+TrRHYmzZ9qmpu1NnTycSrp005NYM78GDKV1w==" - }, - "Google.Protobuf": { - "type": "Transitive", - "resolved": "3.26.1", - "contentHash": "CHZX8zXqhF/fdUtd+AYzew8T2HFkAoe5c7lbGxZY/qryAlQXckDvM5BfOJjXlMS7kyICqQTMszj4w1bX5uBJ/w==", - "dependencies": { - "System.Memory": "4.5.3", - "System.Runtime.CompilerServices.Unsafe": "4.5.2" - } - }, - "Grpc": { - "type": "Transitive", - "resolved": "2.44.0", - "contentHash": "9a6FybBPcVMAxSXMTbwYxBmAe7dG+hMMSTrar4lccIXZxUNQM9zMEMzMqih1QTypdLv6udf1+oVOTf11T4c/sQ==", - "dependencies": { - "Grpc.Core": "2.44.0" - } - }, - "Grpc.Core": { - "type": "Transitive", - "resolved": "2.44.0", - "contentHash": "H2rTNePSYeEqUgBBqiE5KZ/yOX7jEtETjWjv4gGtnYxrlpZ79VAHe+4KtZAnt2KJMiGvqTm7eo1SPk+QpiPfaw==", - "dependencies": { - "Grpc.Core.Api": "2.44.0", - "System.Memory": "4.5.3" - } - }, - "Grpc.Core.Api": { - "type": "Transitive", - "resolved": "2.62.0", - "contentHash": "q4Jj6bRZHNnE4CMLqgjiBUCKLit+tRr0simZsS2W6U++akd7CzXByeKy2tddqT68hFzP2XzceXA2YtBTfWtixA==", - "dependencies": { - "System.Memory": "4.5.3" - } - }, - "Grpc.Net.Client": { - "type": "Transitive", - "resolved": "2.62.0", - "contentHash": "C7HxLt+wWPTpPFORRHkxxtDLL+K/jXSmZBaPLhFM8AEkN0bYjklIfCwnzajn1gcbRcEETBb0WnRgHJdVzpwbCg==", - "dependencies": { - "Grpc.Net.Common": "2.62.0", - "Microsoft.Extensions.Logging.Abstractions": "6.0.0", - "System.Diagnostics.DiagnosticSource": "6.0.1" - } - }, - "Grpc.Net.Common": { - "type": "Transitive", - "resolved": "2.62.0", - "contentHash": "eBv5I4RPWfdezGXqooU5hs3+XcfVMLk5XDlA4G/Nd9TMX78ZGrFl/lM1Ad187zgBLmH7WPAgfjKRWLBwaa1Wbw==", - "dependencies": { - "Grpc.Core.Api": "2.62.0" - } - }, - "ILRepack": { - "type": "Transitive", - "resolved": "2.0.33", - "contentHash": "xb2h1CsOepoYwdXEPui9VcQglwABQwNf9cccZbf+acarEzF5PUp8Xx71nFXIhOgEdm6wrxAoF6xAxK4m/XFRUQ==" - }, - "Microsoft.Bcl.AsyncInterfaces": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "3WA9q9yVqJp222P3x1wYIGDAkpjAku0TMUaaQV22g6L67AI0LdOIrVS7Ht2vJfLHGSPVuqN94vIr15qn+HEkHw==", - "dependencies": { - "System.Threading.Tasks.Extensions": "4.5.4" - } - }, - "Microsoft.Build.Tasks.Git": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "bZKfSIKJRXLTuSzLudMFte/8CempWjVamNUR5eHJizsy+iuOuO/k2gnh7W0dHJmYY0tBf+gUErfluCv5mySAOQ==" - }, - "Microsoft.Extensions.Configuration": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "0J/9YNXTMWSZP2p2+nvl8p71zpSwokZXZuJW+VjdErkegAnFdO1XlqtA62SJtgVYHdKu3uPxJHcMR/r35HwFBA==", - "dependencies": { - "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", - "Microsoft.Extensions.Primitives": "8.0.0" - } - }, - "Microsoft.Extensions.Configuration.Abstractions": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "3lE/iLSutpgX1CC0NOW70FJoGARRHbyKmG7dc0klnUZ9Dd9hS6N/POPWhKhMLCEuNN5nXEY5agmlFtH562vqhQ==", - "dependencies": { - "Microsoft.Extensions.Primitives": "8.0.0" - } - }, - "Microsoft.Extensions.Configuration.Binder": { - "type": "Transitive", - "resolved": "8.0.1", - "contentHash": "2UKFJnLiBt7Od6nCnTqP9rTIUNhzmn9Hv1l2FchyKbz8xieB9ULwZTbQZMw+M24Qw3F5dzzH1U9PPleN0LNLOQ==", - "dependencies": { - "Microsoft.Extensions.Configuration.Abstractions": "8.0.0" - } - }, - "Microsoft.Extensions.DependencyInjection": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "V8S3bsm50ig6JSyrbcJJ8bW2b9QLGouz+G1miK3UTaOWmMtFwNNNzUf4AleyDWUmTrWMLNnFSLEQtxmxgNQnNQ==", - "dependencies": { - "Microsoft.Bcl.AsyncInterfaces": "8.0.0", - "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", - "System.Threading.Tasks.Extensions": "4.5.4" - } - }, - "Microsoft.Extensions.DependencyInjection.Abstractions": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "cjWrLkJXK0rs4zofsK4bSdg+jhDLTaxrkXu4gS6Y7MAlCvRyNNgwY/lJi5RDlQOnSZweHqoyvgvbdvQsRIW+hg==", - "dependencies": { - "Microsoft.Bcl.AsyncInterfaces": "8.0.0", - "System.Threading.Tasks.Extensions": "4.5.4" - } - }, - "Microsoft.Extensions.Diagnostics.Abstractions": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "JHYCQG7HmugNYUhOl368g+NMxYE/N/AiclCYRNlgCY9eVyiBkOHMwK4x60RYMxv9EL3+rmj1mqHvdCiPpC+D4Q==", - "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", - "Microsoft.Extensions.Options": "8.0.0", - "System.Buffers": "4.5.1", - "System.Diagnostics.DiagnosticSource": "8.0.0", - "System.Memory": "4.5.5" - } - }, - "Microsoft.Extensions.Logging": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "tvRkov9tAJ3xP51LCv3FJ2zINmv1P8Hi8lhhtcKGqM+ImiTCC84uOPEI4z8Cdq2C3o9e+Aa0Gw0rmrsJD77W+w==", - "dependencies": { - "Microsoft.Bcl.AsyncInterfaces": "8.0.0", - "Microsoft.Extensions.DependencyInjection": "8.0.0", - "Microsoft.Extensions.Logging.Abstractions": "8.0.0", - "Microsoft.Extensions.Options": "8.0.0", - "System.Diagnostics.DiagnosticSource": "8.0.0" - } - }, - "Microsoft.Extensions.Logging.Abstractions": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "arDBqTgFCyS0EvRV7O3MZturChstm50OJ0y9bDJvAcmEPJm0FFpFyjU/JLYyStNGGey081DvnQYlncNX5SJJGA==", - "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", - "System.Buffers": "4.5.1", - "System.Memory": "4.5.5" - } - }, - "Microsoft.Extensions.Logging.Configuration": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "ixXXV0G/12g6MXK65TLngYN9V5hQQRuV+fZi882WIoVJT7h5JvoYoxTEwCgdqwLjSneqh1O+66gM8sMr9z/rsQ==", - "dependencies": { - "Microsoft.Extensions.Configuration": "8.0.0", - "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", - "Microsoft.Extensions.Configuration.Binder": "8.0.0", - "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", - "Microsoft.Extensions.Logging": "8.0.0", - "Microsoft.Extensions.Logging.Abstractions": "8.0.0", - "Microsoft.Extensions.Options": "8.0.0", - "Microsoft.Extensions.Options.ConfigurationExtensions": "8.0.0" - } - }, - "Microsoft.Extensions.Options": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "JOVOfqpnqlVLUzINQ2fox8evY2SKLYJ3BV8QDe/Jyp21u1T7r45x/R/5QdteURMR5r01GxeJSBBUOCOyaNXA3g==", - "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", - "Microsoft.Extensions.Primitives": "8.0.0", - "System.ComponentModel.Annotations": "5.0.0" - } - }, - "Microsoft.Extensions.Options.ConfigurationExtensions": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "0f4DMRqEd50zQh+UyJc+/HiBsZ3vhAQALgdkcQEalSH1L2isdC7Yj54M3cyo5e+BeO5fcBQ7Dxly8XiBBcvRgw==", - "dependencies": { - "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", - "Microsoft.Extensions.Configuration.Binder": "8.0.0", - "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", - "Microsoft.Extensions.Options": "8.0.0", - "Microsoft.Extensions.Primitives": "8.0.0" - } - }, - "Microsoft.Extensions.Primitives": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "bXJEZrW9ny8vjMF1JV253WeLhpEVzFo1lyaZu1vQ4ZxWUlVvknZ/+ftFgVheLubb4eZPSwwxBeqS1JkCOjxd8g==", - "dependencies": { - "System.Memory": "4.5.5", - "System.Runtime.CompilerServices.Unsafe": "6.0.0" - } - }, - "Microsoft.NETCore.Platforms": { - "type": "Transitive", - "resolved": "1.1.0", - "contentHash": "kz0PEW2lhqygehI/d6XsPCQzD7ff7gUJaVGPVETX611eadGsA3A877GdSlU0LRVMCTH/+P3o2iDTak+S08V2+A==" - }, - "Microsoft.SourceLink.Common": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw==" - }, - "OpenTelemetry": { - "type": "Transitive", - "resolved": "1.9.0", - "contentHash": "7scS6BUhwYeSXEDGhCxMSezmvyCoDU5kFQbmfyW9iVvVTcWhec+1KIN33/LOCdBXRkzt2y7+g03mkdAB0XZ9Fw==", - "dependencies": { - "Microsoft.Extensions.Diagnostics.Abstractions": "8.0.0", - "Microsoft.Extensions.Logging.Configuration": "8.0.0", - "OpenTelemetry.Api.ProviderBuilderExtensions": "1.9.0" - } - }, - "OpenTelemetry.Api": { - "type": "Transitive", - "resolved": "1.9.0", - "contentHash": "Xz8ZvM1Lm0m7BbtGBnw2JlPo++YKyMp08zMK5p0mf+cIi5jeMt2+QsYu9X6YEAbjCxBQYwEak5Z8sY6Ig2WcwQ==", - "dependencies": { - "System.Diagnostics.DiagnosticSource": "8.0.0" - } - }, - "OpenTelemetry.Api.ProviderBuilderExtensions": { - "type": "Transitive", - "resolved": "1.9.0", - "contentHash": "L0D4LBR5JFmwLun5MCWVGapsJLV0ANZ+XXu9NEI3JE/HRKkRuUO+J2MuHD5DBwiU//QMYYM4B22oev1hVLoHDQ==", - "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", - "OpenTelemetry.Api": "1.9.0" - } - }, - "System.Buffers": { - "type": "Transitive", - "resolved": "4.5.1", - "contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg==" - }, - "System.ComponentModel.Annotations": { - "type": "Transitive", - "resolved": "5.0.0", - "contentHash": "dMkqfy2el8A8/I76n2Hi1oBFEbG1SfxD2l5nhwXV3XjlnOmwxJlQbYpJH4W51odnU9sARCSAgv7S3CyAFMkpYg==" - }, - "System.Diagnostics.DiagnosticSource": { - "type": "Transitive", - "resolved": "8.0.1", - "contentHash": "vaoWjvkG1aenR2XdjaVivlCV9fADfgyhW5bZtXT23qaEea0lWiUljdQuze4E31vKM7ZWJaSUsbYIKE3rnzfZUg==", - "dependencies": { - "System.Memory": "4.5.5", - "System.Runtime.CompilerServices.Unsafe": "6.0.0" - } - }, - "System.Memory": { - "type": "Transitive", - "resolved": "4.5.5", - "contentHash": "XIWiDvKPXaTveaB7HVganDlOCRoj03l+jrwNvcge/t8vhGYKvqV+dMv6G4SAX2NoNmN0wZfVPTAlFwZcZvVOUw==", - "dependencies": { - "System.Buffers": "4.5.1", - "System.Numerics.Vectors": "4.4.0", - "System.Runtime.CompilerServices.Unsafe": "4.5.3" - } - }, - "System.Numerics.Vectors": { - "type": "Transitive", - "resolved": "4.5.0", - "contentHash": "QQTlPTl06J/iiDbJCiepZ4H//BVraReU4O4EoRw1U02H5TLUIT7xn3GnDp9AXPSlJUDyFs4uWjWafNX6WrAojQ==" - }, - "System.Reflection.TypeExtensions": { - "type": "Transitive", - "resolved": "4.7.0", - "contentHash": "VybpaOQQhqE6siHppMktjfGBw1GCwvCqiufqmP8F1nj7fTUNtW35LOEt3UZTEsECfo+ELAl/9o9nJx3U91i7vA==" - }, - "System.Runtime.CompilerServices.Unsafe": { - "type": "Transitive", - "resolved": "6.0.0", - "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==" - }, - "System.Text.Encodings.Web": { - "type": "Transitive", - "resolved": "4.7.2", - "contentHash": "iTUgB/WtrZ1sWZs84F2hwyQhiRH6QNjQv2DkwrH+WP6RoFga2Q1m3f9/Q7FG8cck8AdHitQkmkXSY8qylcDmuA==", - "dependencies": { - "System.Buffers": "4.5.1", - "System.Memory": "4.5.4" - } - }, - "System.Threading.Channels": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "CMaFr7v+57RW7uZfZkPExsPB6ljwzhjACWW1gfU35Y56rk72B/Wu+sTqxVmGSk4SFUlPc3cjeKND0zktziyjBA==", - "dependencies": { - "System.Threading.Tasks.Extensions": "4.5.4" - } - }, - "System.Threading.Tasks.Extensions": { - "type": "Transitive", - "resolved": "4.5.4", - "contentHash": "zteT+G8xuGu6mS+mzDzYXbzS7rd3K6Fjb9RiZlYlJPam2/hU7JCBZBVEcywNuR+oZ1ncTvc/cq0faRr3P01OVg==", - "dependencies": { - "System.Runtime.CompilerServices.Unsafe": "4.5.3" - } - }, - "System.Text.Json": { - "type": "CentralTransitive", - "requested": "[5.0.2, )", - "resolved": "4.7.2", - "contentHash": "TcMd95wcrubm9nHvJEQs70rC0H/8omiSGGpU4FQ/ZA1URIqD4pjmFJh2Mfv1yH1eHgJDWTi2hMDXwTET+zOOyg==", - "dependencies": { - "Microsoft.Bcl.AsyncInterfaces": "1.1.0", - "System.Buffers": "4.5.1", - "System.Memory": "4.5.4", - "System.Numerics.Vectors": "4.5.0", - "System.Runtime.CompilerServices.Unsafe": "4.7.1", - "System.Text.Encodings.Web": "4.7.1", - "System.Threading.Tasks.Extensions": "4.5.4" - } - } - }, - "net8.0": { - "GitVersion.MsBuild": { - "type": "Direct", - "requested": "[5.12.0, )", - "resolved": "5.12.0", - "contentHash": "dJuigXycpJNOiLT9or7mkHSkGFHgGW3/p6cNNYEKZBa7Hhp1FdX/cvqYWWYhRLpfoZOedeA7aRbYiOB3vW/dvA==" - }, - "ILRepack.FullAuto": { - "type": "Direct", - "requested": "[1.6.0, )", - "resolved": "1.6.0", - "contentHash": "34qp/HQ0XRIWCjtNGUOslJ6p9eNWqHXZQ+xx1iBCvXy3mj8tEiqIwRG+LubFyKCJITqMh5cpFvFl20/6+Dmy+g==", - "dependencies": { - "ILRepack": "2.0.33" - } - }, - "Microsoft.SourceLink.GitHub": { - "type": "Direct", - "requested": "[8.0.0, )", - "resolved": "8.0.0", - "contentHash": "G5q7OqtwIyGTkeIOAc3u2ZuV/kicQaec5EaRnc0pIeSnh9LUjj+PYQrJYBURvDt7twGl2PKA7nSN0kz1Zw5bnQ==", - "dependencies": { - "Microsoft.Build.Tasks.Git": "8.0.0", - "Microsoft.SourceLink.Common": "8.0.0" - } - }, - "OpenTelemetry.Exporter.Console": { - "type": "Direct", - "requested": "[1.9.0, )", - "resolved": "1.9.0", - "contentHash": "TbScDLSc6kcji+/wZYIf8/HBV2SnttzN7PNxr3TYczlmGlU4K2ugujp6seSktEO4OaAvKRd7Y3CG3SKNj0C+1Q==", - "dependencies": { - "OpenTelemetry": "1.9.0" - } - }, - "OpenTelemetry.Exporter.OpenTelemetryProtocol": { - "type": "Direct", - "requested": "[1.9.0, )", - "resolved": "1.9.0", - "contentHash": "qzFOP3V2eYIVbug3U4BJzzidHe9JhAJ42WZ/H8pUp/45Ry3MQQg/+e/ZieClJcxKnpbkXi7dUq1rpvuNp+yBYA==", - "dependencies": { - "Google.Protobuf": "[3.22.5, 4.0.0)", - "Grpc.Net.Client": "[2.52.0, 3.0.0)", - "Microsoft.Extensions.Configuration.Binder": "8.0.1", - "OpenTelemetry": "1.9.0" - } - }, - "OpenTelemetry.Instrumentation.Http": { - "type": "Direct", - "requested": "[1.9.0, )", - "resolved": "1.9.0", - "contentHash": "+ZXppf8Qxz3OdC803T8fB6i8iSscc8PsxMnM/JizSOYmkz+8vGiScEiaBBBFNZtMh2KpA0q+qxwnSwQUkbvzog==", - "dependencies": { - "Microsoft.Extensions.Configuration": "8.0.0", - "Microsoft.Extensions.Options": "8.0.0", - "OpenTelemetry.Api.ProviderBuilderExtensions": "[1.9.0, 2.0.0)" - } - }, - "PolySharp": { - "type": "Direct", - "requested": "[1.14.1, )", - "resolved": "1.14.1", - "contentHash": "mOOmFYwad3MIOL14VCjj02LljyF1GNw1wP0YVlxtcPvqdxjGGMNdNJJxHptlry3MOd8b40Flm8RPOM8JOlN2sQ==" - }, - "Serilog": { - "type": "Direct", - "requested": "[4.0.1, )", - "resolved": "4.0.1", - "contentHash": "pzeDRXdpSLSsgBHpZcmpIDxqMy845Ab4s+dfnBg0sN9h8q/4Wo3vAoe0QCGPze1Q06EVtEPupS+UvLm8iXQmTQ==" - }, - "Serilog.Exceptions": { - "type": "Direct", - "requested": "[8.4.0, )", - "resolved": "8.4.0", - "contentHash": "nc/+hUw3lsdo0zCj0KMIybAu7perMx79vu72w0za9Nsi6mWyNkGXxYxakAjWB7nEmYL6zdmhEQRB4oJ2ALUeug==", - "dependencies": { - "Serilog": "2.8.0", - "System.Reflection.TypeExtensions": "4.7.0" - } - }, - "Serilog.Sinks.Console": { - "type": "Direct", - "requested": "[6.0.0, )", - "resolved": "6.0.0", - "contentHash": "fQGWqVMClCP2yEyTXPIinSr5c+CBGUvBybPxjAGcf7ctDhadFhrQw03Mv8rJ07/wR5PDfFjewf2LimvXCDzpbA==", - "dependencies": { - "Serilog": "4.0.0" - } - }, - "Serilog.Sinks.File": { - "type": "Direct", - "requested": "[6.0.0, )", - "resolved": "6.0.0", - "contentHash": "lxjg89Y8gJMmFxVkbZ+qDgjl+T4yC5F7WSLTvA+5q0R04tfKVLRL/EHpYoJ/MEQd2EeCKDuylBIVnAYMotmh2A==", - "dependencies": { - "Serilog": "4.0.0" - } - }, - "Serilog.Sinks.OpenTelemetry": { - "type": "Direct", - "requested": "[4.0.0, )", - "resolved": "4.0.0", - "contentHash": "M4WKDojg8a+msY5qhNGg5PYZ9ZVelcqipkP/CrfDAOvGCZ3MYj+cGXgnTanffYyIoC2onabaOtydqW6lqT/P/w==", - "dependencies": { - "Google.Protobuf": "3.26.1", - "Grpc.Net.Client": "2.62.0", - "Serilog": "4.0.0" - } - }, - "Speckle.InterfaceGenerator": { - "type": "Direct", - "requested": "[0.9.6, )", - "resolved": "0.9.6", - "contentHash": "HKH7tYrYYlCK1ct483hgxERAdVdMtl7gUKW9ijWXxA1UsYR4Z+TrRHYmzZ9qmpu1NnTycSrp005NYM78GDKV1w==" - }, - "Google.Protobuf": { - "type": "Transitive", - "resolved": "3.26.1", - "contentHash": "CHZX8zXqhF/fdUtd+AYzew8T2HFkAoe5c7lbGxZY/qryAlQXckDvM5BfOJjXlMS7kyICqQTMszj4w1bX5uBJ/w==" - }, - "Grpc.Core.Api": { - "type": "Transitive", - "resolved": "2.62.0", - "contentHash": "q4Jj6bRZHNnE4CMLqgjiBUCKLit+tRr0simZsS2W6U++akd7CzXByeKy2tddqT68hFzP2XzceXA2YtBTfWtixA==" - }, - "Grpc.Net.Client": { - "type": "Transitive", - "resolved": "2.62.0", - "contentHash": "C7HxLt+wWPTpPFORRHkxxtDLL+K/jXSmZBaPLhFM8AEkN0bYjklIfCwnzajn1gcbRcEETBb0WnRgHJdVzpwbCg==", - "dependencies": { - "Grpc.Net.Common": "2.62.0", - "Microsoft.Extensions.Logging.Abstractions": "6.0.0" - } - }, - "Grpc.Net.Common": { - "type": "Transitive", - "resolved": "2.62.0", - "contentHash": "eBv5I4RPWfdezGXqooU5hs3+XcfVMLk5XDlA4G/Nd9TMX78ZGrFl/lM1Ad187zgBLmH7WPAgfjKRWLBwaa1Wbw==", - "dependencies": { - "Grpc.Core.Api": "2.62.0" - } - }, - "ILRepack": { - "type": "Transitive", - "resolved": "2.0.33", - "contentHash": "xb2h1CsOepoYwdXEPui9VcQglwABQwNf9cccZbf+acarEzF5PUp8Xx71nFXIhOgEdm6wrxAoF6xAxK4m/XFRUQ==" - }, - "Microsoft.Build.Tasks.Git": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "bZKfSIKJRXLTuSzLudMFte/8CempWjVamNUR5eHJizsy+iuOuO/k2gnh7W0dHJmYY0tBf+gUErfluCv5mySAOQ==" - }, - "Microsoft.Extensions.Configuration": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "0J/9YNXTMWSZP2p2+nvl8p71zpSwokZXZuJW+VjdErkegAnFdO1XlqtA62SJtgVYHdKu3uPxJHcMR/r35HwFBA==", - "dependencies": { - "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", - "Microsoft.Extensions.Primitives": "8.0.0" - } - }, - "Microsoft.Extensions.Configuration.Abstractions": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "3lE/iLSutpgX1CC0NOW70FJoGARRHbyKmG7dc0klnUZ9Dd9hS6N/POPWhKhMLCEuNN5nXEY5agmlFtH562vqhQ==", - "dependencies": { - "Microsoft.Extensions.Primitives": "8.0.0" - } - }, - "Microsoft.Extensions.Configuration.Binder": { - "type": "Transitive", - "resolved": "8.0.1", - "contentHash": "2UKFJnLiBt7Od6nCnTqP9rTIUNhzmn9Hv1l2FchyKbz8xieB9ULwZTbQZMw+M24Qw3F5dzzH1U9PPleN0LNLOQ==", - "dependencies": { - "Microsoft.Extensions.Configuration.Abstractions": "8.0.0" - } - }, - "Microsoft.Extensions.DependencyInjection": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "V8S3bsm50ig6JSyrbcJJ8bW2b9QLGouz+G1miK3UTaOWmMtFwNNNzUf4AleyDWUmTrWMLNnFSLEQtxmxgNQnNQ==", - "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0" - } - }, - "Microsoft.Extensions.DependencyInjection.Abstractions": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "cjWrLkJXK0rs4zofsK4bSdg+jhDLTaxrkXu4gS6Y7MAlCvRyNNgwY/lJi5RDlQOnSZweHqoyvgvbdvQsRIW+hg==" - }, - "Microsoft.Extensions.Diagnostics.Abstractions": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "JHYCQG7HmugNYUhOl368g+NMxYE/N/AiclCYRNlgCY9eVyiBkOHMwK4x60RYMxv9EL3+rmj1mqHvdCiPpC+D4Q==", - "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", - "Microsoft.Extensions.Options": "8.0.0", - "System.Diagnostics.DiagnosticSource": "8.0.0" - } - }, - "Microsoft.Extensions.Logging": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "tvRkov9tAJ3xP51LCv3FJ2zINmv1P8Hi8lhhtcKGqM+ImiTCC84uOPEI4z8Cdq2C3o9e+Aa0Gw0rmrsJD77W+w==", - "dependencies": { - "Microsoft.Extensions.DependencyInjection": "8.0.0", - "Microsoft.Extensions.Logging.Abstractions": "8.0.0", - "Microsoft.Extensions.Options": "8.0.0" - } - }, - "Microsoft.Extensions.Logging.Abstractions": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "arDBqTgFCyS0EvRV7O3MZturChstm50OJ0y9bDJvAcmEPJm0FFpFyjU/JLYyStNGGey081DvnQYlncNX5SJJGA==", - "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0" - } - }, - "Microsoft.Extensions.Logging.Configuration": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "ixXXV0G/12g6MXK65TLngYN9V5hQQRuV+fZi882WIoVJT7h5JvoYoxTEwCgdqwLjSneqh1O+66gM8sMr9z/rsQ==", - "dependencies": { - "Microsoft.Extensions.Configuration": "8.0.0", - "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", - "Microsoft.Extensions.Configuration.Binder": "8.0.0", - "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", - "Microsoft.Extensions.Logging": "8.0.0", - "Microsoft.Extensions.Logging.Abstractions": "8.0.0", - "Microsoft.Extensions.Options": "8.0.0", - "Microsoft.Extensions.Options.ConfigurationExtensions": "8.0.0" - } - }, - "Microsoft.Extensions.Options": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "JOVOfqpnqlVLUzINQ2fox8evY2SKLYJ3BV8QDe/Jyp21u1T7r45x/R/5QdteURMR5r01GxeJSBBUOCOyaNXA3g==", - "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", - "Microsoft.Extensions.Primitives": "8.0.0" - } - }, - "Microsoft.Extensions.Options.ConfigurationExtensions": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "0f4DMRqEd50zQh+UyJc+/HiBsZ3vhAQALgdkcQEalSH1L2isdC7Yj54M3cyo5e+BeO5fcBQ7Dxly8XiBBcvRgw==", - "dependencies": { - "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", - "Microsoft.Extensions.Configuration.Binder": "8.0.0", - "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", - "Microsoft.Extensions.Options": "8.0.0", - "Microsoft.Extensions.Primitives": "8.0.0" - } - }, - "Microsoft.Extensions.Primitives": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "bXJEZrW9ny8vjMF1JV253WeLhpEVzFo1lyaZu1vQ4ZxWUlVvknZ/+ftFgVheLubb4eZPSwwxBeqS1JkCOjxd8g==" - }, - "Microsoft.SourceLink.Common": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw==" - }, - "OpenTelemetry": { - "type": "Transitive", - "resolved": "1.9.0", - "contentHash": "7scS6BUhwYeSXEDGhCxMSezmvyCoDU5kFQbmfyW9iVvVTcWhec+1KIN33/LOCdBXRkzt2y7+g03mkdAB0XZ9Fw==", - "dependencies": { - "Microsoft.Extensions.Diagnostics.Abstractions": "8.0.0", - "Microsoft.Extensions.Logging.Configuration": "8.0.0", - "OpenTelemetry.Api.ProviderBuilderExtensions": "1.9.0" - } - }, - "OpenTelemetry.Api": { - "type": "Transitive", - "resolved": "1.9.0", - "contentHash": "Xz8ZvM1Lm0m7BbtGBnw2JlPo++YKyMp08zMK5p0mf+cIi5jeMt2+QsYu9X6YEAbjCxBQYwEak5Z8sY6Ig2WcwQ==", - "dependencies": { - "System.Diagnostics.DiagnosticSource": "8.0.0" - } - }, - "OpenTelemetry.Api.ProviderBuilderExtensions": { - "type": "Transitive", - "resolved": "1.9.0", - "contentHash": "L0D4LBR5JFmwLun5MCWVGapsJLV0ANZ+XXu9NEI3JE/HRKkRuUO+J2MuHD5DBwiU//QMYYM4B22oev1hVLoHDQ==", - "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", - "OpenTelemetry.Api": "1.9.0" - } - }, - "System.Diagnostics.DiagnosticSource": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "c9xLpVz6PL9lp/djOWtk5KPDZq3cSYpmXoJQY524EOtuFl5z9ZtsotpsyrDW40U1DRnQSYvcPKEUV0X//u6gkQ==" - }, - "System.Reflection.TypeExtensions": { - "type": "Transitive", - "resolved": "4.7.0", - "contentHash": "VybpaOQQhqE6siHppMktjfGBw1GCwvCqiufqmP8F1nj7fTUNtW35LOEt3UZTEsECfo+ELAl/9o9nJx3U91i7vA==" - } - } - } -} \ No newline at end of file diff --git a/src/Speckle.Sdk/Api/GraphQL/Client.cs b/src/Speckle.Sdk/Api/GraphQL/Client.cs index bf3300cf..d80618a5 100644 --- a/src/Speckle.Sdk/Api/GraphQL/Client.cs +++ b/src/Speckle.Sdk/Api/GraphQL/Client.cs @@ -4,6 +4,7 @@ using System.Reflection; using GraphQL; using GraphQL.Client.Http; +using Microsoft.Extensions.Logging; using Polly; using Polly.Contrib.WaitAndRetry; using Speckle.Newtonsoft.Json; @@ -17,8 +18,10 @@ namespace Speckle.Sdk.Api; [SuppressMessage("Maintainability", "CA1506:Avoid excessive class coupling", Justification = "Class needs refactor")] -public sealed partial class Client : ISpeckleGraphQLClient, IDisposable +public sealed class Client : ISpeckleGraphQLClient, IDisposable { + private readonly ILogger _logger; + private readonly ISdkActivityFactory _activityFactory; public ProjectResource Project { get; } public ModelResource Model { get; } public VersionResource Version { get; } @@ -39,8 +42,16 @@ public sealed partial class Client : ISpeckleGraphQLClient, IDisposable /// /// was null - public Client(Account account) + public Client( + ILogger logger, + ISdkActivityFactory activityFactory, + ISpeckleApplication application, + ISpeckleHttp speckleHttp, + Account account + ) { + _logger = logger; + _activityFactory = activityFactory; Account = account ?? throw new ArgumentException("Provided account is null."); Project = new(this); @@ -52,7 +63,7 @@ public Client(Account account) Comment = new(this); Subscription = new(this); - HttpClient = CreateHttpClient(account); + HttpClient = CreateHttpClient(application, speckleHttp, account); GQLClient = CreateGraphQLClient(account, HttpClient); } @@ -76,7 +87,7 @@ internal async Task ExecuteWithResiliencePolicies(Func> func) delay, (ex, timeout, _) => { - SpeckleLog.Logger.Debug( + _logger.LogDebug( ex, "The previous attempt at executing function to get {resultType} failed with {exceptionMessage}. Retrying after {timeout}", typeof(T).Name, @@ -92,7 +103,7 @@ internal async Task ExecuteWithResiliencePolicies(Func> func) /// public async Task ExecuteGraphQLRequest(GraphQLRequest request, CancellationToken cancellationToken = default) { - using var activity = SpeckleActivityFactory.Start(); + using var activity = _activityFactory.Start(); try { var ret = await ExecuteWithResiliencePolicies(async () => @@ -104,12 +115,12 @@ public async Task ExecuteGraphQLRequest(GraphQLRequest request, Cancellati return result.Data; }) .ConfigureAwait(false); - activity?.SetStatus(SpeckleActivityStatusCode.Ok); + activity?.SetStatus(SdkActivityStatusCode.Ok); return ret; } catch (Exception e) { - activity?.SetStatus(SpeckleActivityStatusCode.Error); + activity?.SetStatus(SdkActivityStatusCode.Error); activity?.RecordException(e); throw; } @@ -218,7 +229,7 @@ internal IDisposable SubscribeTo(GraphQLRequest request, Action ca else { // Serilog.Log.ForContext("graphqlResponse", response) - SpeckleLog.Logger.Error( + _logger.LogError( "Cannot execute graphql callback for {resultType}, the response has no data.", typeof(T).Name ); @@ -235,7 +246,7 @@ internal IDisposable SubscribeTo(GraphQLRequest request, Action ca /* Speckle.Sdk.Logging..ForContext("graphqlResponse", gqlException.Response) .ForContext("graphqlExtensions", gqlException.Extensions) .ForContext("graphqlErrorMessages", gqlException.ErrorMessages.ToList())*/ - SpeckleLog.Logger.Warning( + _logger.LogWarning( gqlException, "Execution of the graphql request to get {resultType} failed with {graphqlExceptionType} {exceptionMessage}.", typeof(T).Name, @@ -253,7 +264,7 @@ internal IDisposable SubscribeTo(GraphQLRequest request, Action ca { // we're logging this as an error for now, to keep track of failures // so far we've swallowed these errors - SpeckleLog.Logger.Error( + _logger.LogError( ex, "Subscription for {resultType} terminated unexpectedly with {exceptionMessage}", typeof(T).Name, @@ -266,12 +277,6 @@ internal IDisposable SubscribeTo(GraphQLRequest request, Action ca } catch (Exception ex) when (!ex.IsFatal()) { - SpeckleLog.Logger.Warning( - ex, - "Subscribing to graphql {resultType} failed without a graphql response. Cause {exceptionMessage}", - typeof(T).Name, - ex.Message - ); throw new SpeckleGraphQLException( "The graphql request failed without a graphql response", request, @@ -292,7 +297,9 @@ private static GraphQLHttpClient CreateGraphQLClient(Account account, HttpClient WebSocketProtocol = "graphql-ws", ConfigureWebSocketConnectionInitPayload = _ => { - return Http.CanAddAuth(account.token, out string? authValue) ? new { Authorization = authValue } : null; + return SpeckleHttp.CanAddAuth(account.token, out string? authValue) + ? new { Authorization = authValue } + : null; }, }, new NewtonsoftJsonSerializer(), @@ -315,14 +322,11 @@ private static GraphQLHttpClient CreateGraphQLClient(Account account, HttpClient return gQLClient; } - private static HttpClient CreateHttpClient(Account account) + private static HttpClient CreateHttpClient(ISpeckleApplication application, ISpeckleHttp speckleHttp, Account account) { - var httpClient = Http.GetHttpProxyClient( - new SpeckleHttpClientHandler(new HttpClientHandler(), Http.HttpAsyncPolicy(timeoutSeconds: 30)) - ); - Http.AddAuthHeader(httpClient, account.token); + var httpClient = speckleHttp.CreateHttpClient(timeoutSeconds: 30, authorizationToken: account.token); - httpClient.DefaultRequestHeaders.Add("apollographql-client-name", Setup.ApplicationVersion); + httpClient.DefaultRequestHeaders.Add("apollographql-client-name", application.ApplicationVersion); httpClient.DefaultRequestHeaders.Add( "apollographql-client-version", Assembly.GetExecutingAssembly().GetName().Version?.ToString() diff --git a/src/Speckle.Sdk/Api/GraphQL/ClientFactory.cs b/src/Speckle.Sdk/Api/GraphQL/ClientFactory.cs new file mode 100644 index 00000000..c2af3e78 --- /dev/null +++ b/src/Speckle.Sdk/Api/GraphQL/ClientFactory.cs @@ -0,0 +1,19 @@ +using Microsoft.Extensions.Logging; +using Speckle.InterfaceGenerator; +using Speckle.Sdk.Credentials; +using Speckle.Sdk.Helpers; +using Speckle.Sdk.Logging; + +namespace Speckle.Sdk.Api; + +[GenerateAutoInterface] +public class ClientFactory( + ILoggerFactory loggerFactory, + ISdkActivityFactory activityFactory, + ISpeckleApplication application, + ISpeckleHttp speckleHttp +) : IClientFactory +{ + public Client Create(Account account) => + new(loggerFactory.CreateLogger(), activityFactory, application, speckleHttp, account); +} diff --git a/src/Speckle.Sdk/Api/GraphQL/Legacy/Client.GraphqlCleintOperations/Client.ActivityOperations.cs b/src/Speckle.Sdk/Api/GraphQL/Legacy/Client.GraphqlCleintOperations/Client.ActivityOperations.cs deleted file mode 100644 index e2d6ece1..00000000 --- a/src/Speckle.Sdk/Api/GraphQL/Legacy/Client.GraphqlCleintOperations/Client.ActivityOperations.cs +++ /dev/null @@ -1,65 +0,0 @@ -using GraphQL; -using Speckle.Sdk.Api.GraphQL.Models; - -namespace Speckle.Sdk.Api; - -public partial class Client -{ - //TODO: API gap - /// - /// Gets the activity of a stream - /// - /// Id of the stream to get the activity from - /// Only show activity after this DateTime - /// Only show activity before this DateTime - /// Time to filter the activity with - /// Time to filter the activity with - /// Max number of activity items to get - /// - /// - public async Task> StreamGetActivity( - string id, - DateTime? after = null, - DateTime? before = null, - DateTime? cursor = null, - string actionType = "", - int limit = ServerLimits.DEFAULT_PAGINATION_REQUEST, - CancellationToken cancellationToken = default - ) - { - var request = new GraphQLRequest - { - Query = - @"query Stream($id: String!, $before: DateTime,$after: DateTime, $cursor: DateTime, $activity: String, $limit: Int!) { - stream(id: $id) { - activity (actionType: $activity, after: $after, before: $before, cursor: $cursor, limit: $limit) { - totalCount - cursor - items { - actionType - userId - streamId - resourceId - resourceType - time - info - message - } - } - } - }", - Variables = new - { - id, - limit, - actionType, - after, - before, - cursor - } - }; - - var res = await ExecuteGraphQLRequest(request, cancellationToken).ConfigureAwait(false); - return res.stream.activity.items; - } -} diff --git a/src/Speckle.Sdk/Api/GraphQL/Legacy/Client.GraphqlCleintOperations/Client.BranchOperations.cs b/src/Speckle.Sdk/Api/GraphQL/Legacy/Client.GraphqlCleintOperations/Client.BranchOperations.cs deleted file mode 100644 index ff1921b1..00000000 --- a/src/Speckle.Sdk/Api/GraphQL/Legacy/Client.GraphqlCleintOperations/Client.BranchOperations.cs +++ /dev/null @@ -1,238 +0,0 @@ -using GraphQL; -using Speckle.Sdk.Api.GraphQL.Resources; - -namespace Speckle.Sdk.Api; - -public partial class Client -{ - /// - /// Get branches from a given stream, first with a max of 500 and then with a max of 100. - /// This ensures that if the server API is limiting to 100 branches, that any failure will try again at the lower value. - /// - /// Id of the stream to get the branches from - /// Max number of commits to retrieve - /// - /// - /// - [Obsolete($"Use client.{nameof(Model)}.{nameof(ModelResource.GetModels)}")] - public async Task> StreamGetBranchesWithLimitRetry(string streamId, int commitsLimit = 10) - { - List branches; - try - { - branches = await StreamGetBranches(streamId, ServerLimits.BRANCH_GET_LIMIT, commitsLimit).ConfigureAwait(true); - } - catch (SpeckleGraphQLException) - { - branches = await StreamGetBranches(streamId, ServerLimits.OLD_BRANCH_GET_LIMIT, commitsLimit) - .ConfigureAwait(true); - } - - return branches; - } - - /// - /// Get branches from a given stream - /// - /// Id of the stream to get the branches from - /// Max number of branches to retrieve - /// Max number of commits to retrieve - /// - /// - /// - /// - [Obsolete($"Use client.{nameof(Model)}.{nameof(ModelResource.GetModels)}")] - public async Task> StreamGetBranches( - string streamId, - int branchesLimit = 10, - int commitsLimit = 10, - CancellationToken cancellationToken = default - ) - { - var request = new GraphQLRequest - { - Query = - $@"query Stream ($streamId: String!) {{ - stream(id: $streamId) {{ - branches(limit: {branchesLimit}) {{ - items {{ - id - name - description - commits (limit: {commitsLimit}) {{ - totalCount - cursor - items {{ - id - referencedObject - sourceApplication - message - authorName - authorId - branchName - parents - createdAt - }} - }} - }} - }} - }} - }}", - Variables = new { streamId } - }; - var res = await ExecuteGraphQLRequest(request, cancellationToken).ConfigureAwait(false); - return res.stream.branches.items; - } - - /// - /// Creates a branch on a stream. - /// - /// - /// - /// The branch id. - /// - [Obsolete($"Use client.{nameof(Model)}.{nameof(ModelResource.Create)}")] - public async Task BranchCreate(BranchCreateInput branchInput, CancellationToken cancellationToken = default) - { - var request = new GraphQLRequest - { - Query = @"mutation branchCreate($myBranch: BranchCreateInput!){ branchCreate(branch: $myBranch)}", - Variables = new { myBranch = branchInput } - }; - - var res = await ExecuteGraphQLRequest>(request, cancellationToken).ConfigureAwait(false); - return (string)res["branchCreate"]; - } - - /// - /// Gets a given branch from a stream. - /// - /// Id of the stream to get the branch from - /// Name of the branch to get - /// - /// The requested branch - /// Updated to Model.GetWithVersions - /// - /// - [Obsolete($"Use client.{nameof(Model)}.{nameof(ModelResource.Get)}")] - public async Task BranchGet( - string streamId, - string branchName, - int commitsLimit = 10, - CancellationToken cancellationToken = default - ) - { - var request = new GraphQLRequest - { - Query = - $@"query Stream($streamId: String!, $branchName: String!) {{ - stream(id: $streamId) {{ - branch(name: $branchName){{ - id, - name, - description, - commits (limit: {commitsLimit}) {{ - totalCount, - cursor, - items {{ - id, - referencedObject, - sourceApplication, - totalChildrenCount, - message, - authorName, - authorId, - branchName, - parents, - createdAt - }} - }} - }} - }} - }}", - Variables = new { streamId, branchName } - }; - - var res = await ExecuteGraphQLRequest(request, cancellationToken).ConfigureAwait(false); - return res.stream.branch; - } - - /// - /// Gets a given model from a project. - /// - /// - /// Id of the project to get the model from - /// Id of the model - /// - /// - [Obsolete($"Use client.{nameof(Model)}.{nameof(ModelResource.Get)}")] - public async Task ModelGet(string projectId, string modelId, CancellationToken cancellationToken = default) - { - var request = new GraphQLRequest - { - Query = - $@"query ProjectModel($projectId: String!, $modelId: String!) {{ - project(id: $projectId) {{ - model(id: $modelId){{ - id, - name, - description - }} - }} - }}", - Variables = new { projectId, modelId } - }; - - var res = await ExecuteGraphQLRequest>>>( - request, - cancellationToken - ) - .ConfigureAwait(false); - var branch = new Branch - { - description = res["project"]["model"]["description"], - id = res["project"]["model"]["id"], - name = res["project"]["model"]["name"] - }; - return branch; - } - - /// - /// Updates a branch. - /// - /// - /// The stream's id. - /// - [Obsolete($"Use client.{nameof(Model)}.{nameof(ModelResource.Update)}")] - public async Task BranchUpdate(BranchUpdateInput branchInput, CancellationToken cancellationToken = default) - { - var request = new GraphQLRequest - { - Query = @"mutation branchUpdate($myBranch: BranchUpdateInput!){ branchUpdate(branch: $myBranch)}", - Variables = new { myBranch = branchInput } - }; - - var res = await ExecuteGraphQLRequest>(request, cancellationToken).ConfigureAwait(false); - return (bool)res["branchUpdate"]; - } - - /// - /// Deletes a stream. - /// - /// - /// - /// - /// - [Obsolete($"Use client.{nameof(Model)}.{nameof(ModelResource.Delete)}")] - public async Task BranchDelete(BranchDeleteInput branchInput, CancellationToken cancellationToken = default) - { - var request = new GraphQLRequest - { - Query = @"mutation branchDelete($myBranch: BranchDeleteInput!){ branchDelete(branch: $myBranch)}", - Variables = new { myBranch = branchInput } - }; - - var res = await ExecuteGraphQLRequest>(request, cancellationToken).ConfigureAwait(false); - return (bool)res["branchDelete"]; - } -} diff --git a/src/Speckle.Sdk/Api/GraphQL/Legacy/Client.GraphqlCleintOperations/Client.CommentOperations.cs b/src/Speckle.Sdk/Api/GraphQL/Legacy/Client.GraphqlCleintOperations/Client.CommentOperations.cs deleted file mode 100644 index e71ee87e..00000000 --- a/src/Speckle.Sdk/Api/GraphQL/Legacy/Client.GraphqlCleintOperations/Client.CommentOperations.cs +++ /dev/null @@ -1,106 +0,0 @@ -using GraphQL; -using Speckle.Sdk.Api.GraphQL.Resources; - -namespace Speckle.Sdk.Api; - -public partial class Client -{ - /// - /// Gets the comments on a Stream - /// - /// Id of the stream to get the comments from - /// The number of comments to get - /// Time to filter the comments with - /// - /// - /// - [Obsolete($"Use client.{nameof(CommentResource)}.{nameof(CommentResource.GetProjectComments)}")] - public async Task StreamGetComments( - string streamId, - int limit = 25, - string? cursor = null, - CancellationToken cancellationToken = default - ) - { - var request = new GraphQLRequest - { - Query = - @"query Comments($streamId: String!, $cursor: String, $limit: Int!) { - comments(streamId: $streamId, cursor: $cursor, limit: $limit) { - totalCount - cursor - items { - id - authorId - archived - rawText - data - createdAt - updatedAt - viewedAt - reactions - resources { - resourceId - resourceType - } - replies { - totalCount - cursor - items { - id - authorId - archived - rawText - data - createdAt - updatedAt - viewedAt - } - } - } - } - }", - Variables = new - { - streamId, - cursor, - limit - } - }; - - var res = await ExecuteGraphQLRequest(request, cancellationToken).ConfigureAwait(false); - return res.comments; - } - - /// - /// Gets the screenshot of a Comment - /// - /// Id of the comment - /// Id of the stream to get the comment from - /// - /// - /// - [Obsolete($"Use client.{nameof(CommentResource)}.{nameof(CommentResource.GetProjectComments)}")] - public async Task StreamGetCommentScreenshot( - string id, - string streamId, - CancellationToken cancellationToken = default - ) - { - var request = new GraphQLRequest - { - Query = - @"query Comment($id: String!, $streamId: String!) { - comment(id: $id, streamId: $streamId) { - id - screenshot - } - } - ", - Variables = new { id, streamId } - }; - - var res = await ExecuteGraphQLRequest(request, cancellationToken).ConfigureAwait(false); - return res.comment.screenshot; - } -} diff --git a/src/Speckle.Sdk/Api/GraphQL/Legacy/Client.GraphqlCleintOperations/Client.CommitOperations.cs b/src/Speckle.Sdk/Api/GraphQL/Legacy/Client.GraphqlCleintOperations/Client.CommitOperations.cs deleted file mode 100644 index 4d91be15..00000000 --- a/src/Speckle.Sdk/Api/GraphQL/Legacy/Client.GraphqlCleintOperations/Client.CommitOperations.cs +++ /dev/null @@ -1,171 +0,0 @@ -using GraphQL; -using Speckle.Sdk.Api.GraphQL.Resources; - -namespace Speckle.Sdk.Api; - -public partial class Client -{ - /// - /// Gets a given commit from a stream. - /// - /// Id of the stream to get the commit from - /// Id of the commit to get - /// - /// - /// - [Obsolete($"Use client.{nameof(Version)}.{nameof(VersionResource.Get)}")] - public async Task CommitGet(string streamId, string commitId, CancellationToken cancellationToken = default) - { - var request = new GraphQLRequest - { - Query = - @"query Stream($streamId: String!, $commitId: String!) { - stream(id: $streamId) { - commit(id: $commitId){ - id, - message, - sourceApplication, - totalChildrenCount, - referencedObject, - branchName, - createdAt, - parents, - authorName - } - } - }", - Variables = new { streamId, commitId } - }; - - var res = await ExecuteGraphQLRequest(request, cancellationToken).ConfigureAwait(false); - return res.stream.commit; - } - - /// - /// Gets the latest commits from a stream - /// - /// Id of the stream to get the commits from - /// Max number of commits to get - /// - /// The requested commits - /// - [Obsolete($"Use client.{nameof(Version)}.{nameof(VersionResource.GetVersions)}")] - public async Task> StreamGetCommits( - string streamId, - int limit = 10, - CancellationToken cancellationToken = default - ) - { - var request = new GraphQLRequest - { - Query = - @"query Stream($streamId: String!, $limit: Int!) { - stream(id: $streamId) { - commits(limit: $limit) { - items { - id, - message, - branchName, - sourceApplication, - totalChildrenCount, - referencedObject, - createdAt, - parents, - authorName, - authorId, - authorAvatar - } - } - } - }", - Variables = new { streamId, limit } - }; - - var res = await ExecuteGraphQLRequest(request, cancellationToken).ConfigureAwait(false); - return res.stream.commits.items; - } - - /// - /// Creates a commit on a branch. - /// - /// - /// The commit id. - /// - [Obsolete($"Use client.{nameof(VersionResource)}.{nameof(VersionResource.Create)}")] - public async Task CommitCreate(CommitCreateInput commitInput, CancellationToken cancellationToken = default) - { - var request = new GraphQLRequest - { - Query = @"mutation commitCreate($myCommit: CommitCreateInput!){ commitCreate(commit: $myCommit)}", - Variables = new { myCommit = commitInput } - }; - - var res = await ExecuteGraphQLRequest>(request, cancellationToken).ConfigureAwait(false); - return (string)res["commitCreate"]; - } - - /// - /// Updates a commit. - /// - /// - /// - /// The stream's id. - /// - [Obsolete($"Use client.{nameof(VersionResource)}.{nameof(VersionResource.Update)}")] - public async Task CommitUpdate(CommitUpdateInput commitInput, CancellationToken cancellationToken = default) - { - var request = new GraphQLRequest - { - Query = @"mutation commitUpdate($myCommit: CommitUpdateInput!){ commitUpdate(commit: $myCommit)}", - Variables = new { myCommit = commitInput } - }; - - var res = await ExecuteGraphQLRequest>(request, cancellationToken).ConfigureAwait(false); - return (bool)res["commitUpdate"]; - } - - /// - /// Deletes a commit. - /// - /// - /// - /// - /// - [Obsolete($"Use client.{nameof(VersionResource)}.{nameof(VersionResource.Delete)}")] - public async Task CommitDelete(CommitDeleteInput commitInput, CancellationToken cancellationToken = default) - { - var request = new GraphQLRequest - { - Query = @"mutation commitDelete($myCommit: CommitDeleteInput!){ commitDelete(commit: $myCommit)}", - Variables = new { myCommit = commitInput } - }; - - var res = await ExecuteGraphQLRequest>(request, cancellationToken).ConfigureAwait(false); - return (bool)res["commitDelete"]; - } - - /// - /// Sends a commitReceived mutation, affirming a commit has been received. - /// - /// Used for read receipts - /// - /// - /// - /// - [Obsolete($"Use client.{nameof(VersionResource)}.{nameof(VersionResource.Received)}")] - public async Task CommitReceived( - CommitReceivedInput commitReceivedInput, - CancellationToken cancellationToken = default - ) - { - var request = new GraphQLRequest - { - Query = @"mutation($myInput:CommitReceivedInput!){ commitReceive(input:$myInput) }", - Variables = new { myInput = commitReceivedInput } - }; - - var res = await ExecuteGraphQLRequest>(request, cancellationToken).ConfigureAwait(false); - - return (bool)res["commitReceive"]; - } -} diff --git a/src/Speckle.Sdk/Api/GraphQL/Legacy/Client.GraphqlCleintOperations/Client.ObjectOperations.cs b/src/Speckle.Sdk/Api/GraphQL/Legacy/Client.GraphqlCleintOperations/Client.ObjectOperations.cs deleted file mode 100644 index 2e900988..00000000 --- a/src/Speckle.Sdk/Api/GraphQL/Legacy/Client.GraphqlCleintOperations/Client.ObjectOperations.cs +++ /dev/null @@ -1,69 +0,0 @@ -using GraphQL; - -namespace Speckle.Sdk.Api; - -public partial class Client -{ - /// - /// Gets data about the requested Speckle object from a stream. - /// - /// Id of the stream to get the object from - /// Id of the object to get - /// - /// - public async Task ObjectGet( - string streamId, - string objectId, - CancellationToken cancellationToken = default - ) - { - var request = new GraphQLRequest - { - Query = - @"query Stream($streamId: String!, $objectId: String!) { - stream(id: $streamId) { - object(id: $objectId){ - id - applicationId - createdAt - totalChildrenCount - } - } - }", - Variables = new { streamId, objectId } - }; - - var res = await ExecuteGraphQLRequest(request, cancellationToken).ConfigureAwait(false); - return res.stream.@object; - } - - /// - /// Gets a given object from a stream. - /// - /// - /// - /// - /// - public async Task ObjectCountGet( - string streamId, - string objectId, - CancellationToken cancellationToken = default - ) - { - var request = new GraphQLRequest - { - Query = - @"query Stream($streamId: String!, $objectId: String!) { - stream(id: $streamId) { - object(id: $objectId){ - totalChildrenCount - } - } - }", - Variables = new { streamId, objectId } - }; - - var res = await ExecuteGraphQLRequest(request, cancellationToken).ConfigureAwait(false); - return res.stream.@object; - } -} diff --git a/src/Speckle.Sdk/Api/GraphQL/Legacy/Client.GraphqlCleintOperations/Client.ServerOperations.cs b/src/Speckle.Sdk/Api/GraphQL/Legacy/Client.GraphqlCleintOperations/Client.ServerOperations.cs deleted file mode 100644 index 1ba3d295..00000000 --- a/src/Speckle.Sdk/Api/GraphQL/Legacy/Client.GraphqlCleintOperations/Client.ServerOperations.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System.Text.RegularExpressions; -using GraphQL; -using Speckle.Sdk.Api.GraphQL.Models.Responses; -using Speckle.Sdk.Common; - -namespace Speckle.Sdk.Api; - -public partial class Client -{ - /// - /// Gets the version of the current server. Useful for guarding against unsupported api calls on newer or older servers. - /// - /// [Optional] defaults to an empty cancellation token - /// object excluding any strings (eg "2.7.2-alpha.6995" becomes "2.7.2.6995") - /// - [Obsolete("Use GraphQLHttpClient.GetServerVersion instead")] - public async Task GetServerVersion(CancellationToken cancellationToken = default) - { - var request = new GraphQLRequest - { - Query = - @"query Server { - serverInfo { - version - } - }" - }; - - var res = await ExecuteGraphQLRequest(request, cancellationToken).ConfigureAwait(false); - - if (res.serverInfo.version.NotNull().Contains("dev")) - { - return new System.Version(999, 999, 999); - } - - var serverVersion = new System.Version(Regex.Replace(res.serverInfo.version, "[-a-zA-Z]+", "")); - return serverVersion; - } -} diff --git a/src/Speckle.Sdk/Api/GraphQL/Legacy/Client.GraphqlCleintOperations/Client.StreamOperations.cs b/src/Speckle.Sdk/Api/GraphQL/Legacy/Client.GraphqlCleintOperations/Client.StreamOperations.cs deleted file mode 100644 index e4c1631a..00000000 --- a/src/Speckle.Sdk/Api/GraphQL/Legacy/Client.GraphqlCleintOperations/Client.StreamOperations.cs +++ /dev/null @@ -1,376 +0,0 @@ -#nullable disable -using GraphQL; -using Speckle.Sdk.Api.GraphQL.Models; -using Speckle.Sdk.Api.GraphQL.Resources; - -namespace Speckle.Sdk.Api; - -public partial class Client -{ - /// - /// Checks if a stream exists by id. - /// - /// Id of the stream to get - /// - /// - public async Task IsStreamAccessible(string id, CancellationToken cancellationToken = default) - { - try - { - var request = new GraphQLRequest - { - Query = - $@"query Stream($id: String!) {{ - stream(id: $id) {{ - id - }} - }}", - Variables = new { id } - }; - var stream = (await ExecuteGraphQLRequest(request, cancellationToken).ConfigureAwait(false)).stream; - - return stream.id == id; - } - catch (SpeckleGraphQLForbiddenException) - { - return false; - } - catch (SpeckleGraphQLStreamNotFoundException) - { - return false; - } - } - - /// - /// Gets a stream by id including basic branch info (id, name, description, and total commit count). - /// For detailed commit and branch info, use and respectively. - /// - /// Id of the stream to get - /// Max number of branches to retrieve - /// - /// - /// - /// - [Obsolete($"Use client.{nameof(Project)}.{nameof(ProjectResource.GetWithModels)}")] - public async Task StreamGet(string id, int branchesLimit = 10, CancellationToken cancellationToken = default) - { - var request = new GraphQLRequest - { - Query = - $@"query Stream($id: String!) {{ - stream(id: $id) {{ - id - name - description - isPublic - role - createdAt - updatedAt - commentCount - favoritedDate - favoritesCount - collaborators {{ - id - name - role - avatar - }}, - branches (limit: {branchesLimit}){{ - totalCount, - cursor, - items {{ - id, - name, - description, - commits {{ - totalCount - }} - }} - }} - }} - }}", - Variables = new { id } - }; - return (await ExecuteGraphQLRequest(request, cancellationToken).ConfigureAwait(false)).stream; - } - - /// - /// Gets all favorite streams for the current user - /// - /// Max number of streams to return - /// - /// - [Obsolete("Favourite streams are no longer a supported feature", true)] - public Task> FavoriteStreamsGet(int limit = 10, CancellationToken cancellationToken = default) => - throw new NotImplementedException(); - - /// - /// Gets all streams for the current user - /// - /// Max number of streams to return - /// - /// - /// - [Obsolete($"Use client.{nameof(ActiveUser)}.{nameof(ActiveUserResource.GetProjects)}", true)] - public Task> StreamsGet(int limit = 10, CancellationToken cancellationToken = default) => - throw new NotImplementedException(); - - /// - /// Creates a stream. - /// - /// - /// - /// The stream's id. - /// - [Obsolete($"Use client.{nameof(Project)}.{nameof(ProjectResource.Create)}")] - public async Task StreamCreate(StreamCreateInput streamInput, CancellationToken cancellationToken = default) - { - var request = new GraphQLRequest - { - Query = @"mutation streamCreate($myStream: StreamCreateInput!) { streamCreate(stream: $myStream) }", - Variables = new { myStream = streamInput } - }; - var res = await ExecuteGraphQLRequest>(request, cancellationToken).ConfigureAwait(false); - return (string)res["streamCreate"]; - } - - /// - /// Updates a stream. - /// - /// Note: the id field needs to be a valid stream id. - /// - /// The stream's id. - /// - [Obsolete($"Use client.{nameof(Project)}.{nameof(ProjectResource.Update)}")] - public async Task StreamUpdate(StreamUpdateInput streamInput, CancellationToken cancellationToken = default) - { - var request = new GraphQLRequest - { - Query = @"mutation streamUpdate($myStream: StreamUpdateInput!) { streamUpdate(stream:$myStream) }", - Variables = new { myStream = streamInput } - }; - - var res = await ExecuteGraphQLRequest>(request, cancellationToken).ConfigureAwait(false); - - return (bool)res["streamUpdate"]; - } - - /// - /// Deletes a stream. - /// - /// Id of the stream to be deleted - /// - /// - /// - [Obsolete($"Use client.{nameof(Project)}.{nameof(ProjectResource.Delete)}")] - public async Task StreamDelete(string id, CancellationToken cancellationToken = default) - { - var request = new GraphQLRequest - { - Query = @"mutation streamDelete($id: String!) { streamDelete(id:$id) }", - Variables = new { id } - }; - var res = await ExecuteGraphQLRequest>(request, cancellationToken).ConfigureAwait(false); - return (bool)res["streamDelete"]; - } - - /// - /// Revokes permissions of a user on a given stream. - /// - /// - /// - /// - public async Task StreamRevokePermission( - StreamRevokePermissionInput permissionInput, - CancellationToken cancellationToken = default - ) - { - var request = new GraphQLRequest - { - Query = - @"mutation streamRevokePermission($permissionParams: StreamRevokePermissionInput!) { - streamRevokePermission(permissionParams: $permissionParams) - }", - Variables = new { permissionParams = permissionInput } - }; - - var res = await ExecuteGraphQLRequest>(request, cancellationToken).ConfigureAwait(false); - return (bool)res["streamRevokePermission"]; - } - - /// - /// Updates permissions for a user on a given stream. - /// - /// includes the streamId, the userId of the user to update, and the user's new role - /// - /// - /// - /// - [Obsolete($"Use client.{nameof(Project)}.{nameof(ProjectResource.UpdateRole)}")] - public async Task StreamUpdatePermission( - StreamPermissionInput updatePermissionInput, - CancellationToken cancellationToken = default - ) - { - var request = new GraphQLRequest - { - Query = - @" - mutation streamUpdatePermission($permissionParams: StreamUpdatePermissionInput!) { - streamUpdatePermission(permissionParams:$permissionParams) - }", - Variables = new { permissionParams = updatePermissionInput } - }; - - var res = await ExecuteGraphQLRequest>(request, cancellationToken).ConfigureAwait(false); - return (bool)res["streamUpdatePermission"]; - } - - /// - /// Gets the pending collaborators of a stream by id. - /// Requires the user to be an owner of the stream. - /// - /// - /// - /// - /// - [Obsolete($"Use client.{nameof(Project)}.{nameof(ProjectResource.GetWithTeam)}", true)] - public Task StreamGetPendingCollaborators(string streamId, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - /// - /// Sends an email invite to join a stream and assigns them a collaborator role. - /// - /// - /// - /// - /// - [Obsolete($"Use client.{nameof(ProjectInvite)}.{nameof(ProjectInviteResource.Create)}")] - public async Task StreamInviteCreate( - StreamInviteCreateInput inviteCreateInput, - CancellationToken cancellationToken = default - ) - { - if ((inviteCreateInput.email == null) & (inviteCreateInput.userId == null)) - { - throw new ArgumentException("You must provide either an email or a user id to create a stream invite"); - } - - var request = new GraphQLRequest - { - Query = - @" - mutation streamInviteCreate($input: StreamInviteCreateInput!) { - streamInviteCreate(input: $input) - }", - Variables = new { input = inviteCreateInput } - }; - - var res = await ExecuteGraphQLRequest>(request, cancellationToken).ConfigureAwait(false); - return (bool)res["streamInviteCreate"]; - } - - /// - /// Cancels an invite to join a stream. - /// - /// Id of the stream - /// Id of the invite to cancel - /// - /// - /// - [Obsolete($"Use client.{nameof(ProjectInvite)}.{nameof(ProjectInviteResource.Cancel)}")] - public async Task StreamInviteCancel( - string streamId, - string inviteId, - CancellationToken cancellationToken = default - ) - { - var request = new GraphQLRequest - { - Query = - @" - mutation streamInviteCancel( $streamId: String!, $inviteId: String! ) { - streamInviteCancel(streamId: $streamId, inviteId: $inviteId) - }", - Variables = new { streamId, inviteId } - }; - - var res = await ExecuteGraphQLRequest>(request, cancellationToken).ConfigureAwait(false); - return (bool)res["streamInviteCancel"]; - } - - /// - /// Accept or decline a stream invite. - /// - /// - /// - /// - /// - /// - /// - /// - [Obsolete($"Use client.{nameof(ProjectInvite)}.{nameof(ProjectInviteResource.Use)}")] - public async Task StreamInviteUse( - string streamId, - string token, - bool accept = true, - CancellationToken cancellationToken = default - ) - { - var request = new GraphQLRequest - { - Query = - @" - mutation streamInviteUse( $accept: Boolean!, $streamId: String!, $token: String! ) { - streamInviteUse(accept: $accept, streamId: $streamId, token: $token) - }", - Variables = new - { - streamId, - token, - accept - } - }; - - var res = await ExecuteGraphQLRequest>(request, cancellationToken).ConfigureAwait(false); - return (bool)res["streamInviteUse"]; - } - - /// - /// - /// - /// - /// - /// - [Obsolete($"Use client.{nameof(ActiveUser)}.{nameof(ActiveUserResource.ProjectInvites)}")] - public async Task> GetAllPendingInvites(CancellationToken cancellationToken = default) - { - var request = new GraphQLRequest - { - Query = - @" - query StreamInvites { - streamInvites{ - id - token - inviteId - streamId - streamName - title - role - invitedBy { - id - name - company - avatar - } - } - }" - }; - - var res = await ExecuteGraphQLRequest(request, cancellationToken).ConfigureAwait(false); - return res.streamInvites; - } -} diff --git a/src/Speckle.Sdk/Api/GraphQL/Legacy/Client.GraphqlCleintOperations/Client.UserOperations.cs b/src/Speckle.Sdk/Api/GraphQL/Legacy/Client.GraphqlCleintOperations/Client.UserOperations.cs deleted file mode 100644 index 42a41f6f..00000000 --- a/src/Speckle.Sdk/Api/GraphQL/Legacy/Client.GraphqlCleintOperations/Client.UserOperations.cs +++ /dev/null @@ -1,50 +0,0 @@ -using Speckle.Sdk.Api.GraphQL.Models; -using Speckle.Sdk.Api.GraphQL.Resources; - -namespace Speckle.Sdk.Api; - -public partial class Client -{ - /// - /// Gets the currently active user profile. - /// - /// - /// - /// - [Obsolete($"Use client.{nameof(ActiveUser)}.{nameof(ActiveUserResource.Get)}")] - public async Task ActiveUserGet(CancellationToken cancellationToken = default) - { - return await ActiveUser.Get(cancellationToken).ConfigureAwait(false); - } - - /// - /// Get another user's profile by its user id. - /// - /// Id of the user you are looking for - /// - /// - /// - [Obsolete($"Use client.{nameof(OtherUser)}.{nameof(OtherUserResource.Get)}")] - public async Task OtherUserGet(string id, CancellationToken cancellationToken = default) - { - return await OtherUser.Get(id, cancellationToken).ConfigureAwait(false); - } - - /// - /// Searches for a user on the server. - /// - /// String to search for. Must be at least 3 characters - /// Max number of users to return - /// - /// - [Obsolete($"Use client.{nameof(OtherUser)}.{nameof(OtherUserResource.UserSearch)}")] - public async Task> UserSearch( - string query, - int limit = 10, - CancellationToken cancellationToken = default - ) - { - var res = await OtherUser.UserSearch(query, limit, cancellationToken: cancellationToken).ConfigureAwait(false); - return res.items; - } -} diff --git a/src/Speckle.Sdk/Api/GraphQL/Legacy/Client.Subscriptions/Client.Subscriptions.Branch.cs b/src/Speckle.Sdk/Api/GraphQL/Legacy/Client.Subscriptions/Client.Subscriptions.Branch.cs deleted file mode 100644 index 95db13e8..00000000 --- a/src/Speckle.Sdk/Api/GraphQL/Legacy/Client.Subscriptions/Client.Subscriptions.Branch.cs +++ /dev/null @@ -1,16 +0,0 @@ -#nullable disable -using Speckle.Sdk.Api.GraphQL.Resources; - -namespace Speckle.Sdk.Api; - -public partial class Client -{ - [Obsolete($"Use {nameof(Subscription)}.{nameof(SubscriptionResource.CreateProjectModelsUpdatedSubscription)}", true)] - public void SubscribeBranchCreated(string streamId) => throw new NotImplementedException(); - - [Obsolete($"Use {nameof(Subscription)}.{nameof(SubscriptionResource.CreateProjectModelsUpdatedSubscription)}", true)] - public void SubscribeBranchUpdated(string streamId, string branchId = null) => throw new NotImplementedException(); - - [Obsolete($"Use {nameof(Subscription)}.{nameof(SubscriptionResource.CreateProjectModelsUpdatedSubscription)}", true)] - public void SubscribeBranchDeleted(string streamId) => throw new NotImplementedException(); -} diff --git a/src/Speckle.Sdk/Api/GraphQL/Legacy/Client.Subscriptions/Client.Subscriptions.Commit.cs b/src/Speckle.Sdk/Api/GraphQL/Legacy/Client.Subscriptions/Client.Subscriptions.Commit.cs deleted file mode 100644 index fa8d05ce..00000000 --- a/src/Speckle.Sdk/Api/GraphQL/Legacy/Client.Subscriptions/Client.Subscriptions.Commit.cs +++ /dev/null @@ -1,25 +0,0 @@ -#nullable disable -using Speckle.Sdk.Api.GraphQL.Resources; - -namespace Speckle.Sdk.Api; - -public partial class Client -{ - [Obsolete( - $"Use {nameof(Subscription)}.{nameof(SubscriptionResource.CreateProjectVersionsUpdatedSubscription)}", - true - )] - public void SubscribeCommitCreated(string streamId) => throw new NotImplementedException(); - - [Obsolete( - $"Use {nameof(Subscription)}.{nameof(SubscriptionResource.CreateProjectVersionsUpdatedSubscription)}", - true - )] - public void SubscribeCommitUpdated(string streamId, string commitId = null) => throw new NotImplementedException(); - - [Obsolete( - $"Use {nameof(Subscription)}.{nameof(SubscriptionResource.CreateProjectVersionsUpdatedSubscription)}", - true - )] - public void SubscribeCommitDeleted(string streamId) => throw new NotImplementedException(); -} diff --git a/src/Speckle.Sdk/Api/GraphQL/Legacy/Client.Subscriptions/Client.Subscriptions.Stream.cs b/src/Speckle.Sdk/Api/GraphQL/Legacy/Client.Subscriptions/Client.Subscriptions.Stream.cs deleted file mode 100644 index d01eebe4..00000000 --- a/src/Speckle.Sdk/Api/GraphQL/Legacy/Client.Subscriptions/Client.Subscriptions.Stream.cs +++ /dev/null @@ -1,22 +0,0 @@ -#nullable disable -using Speckle.Sdk.Api.GraphQL.Resources; - -namespace Speckle.Sdk.Api; - -public partial class Client -{ - [Obsolete($"Use {nameof(Subscription)}.{nameof(SubscriptionResource.CreateUserProjectsUpdatedSubscription)}", true)] - public void SubscribeUserStreamAdded() => throw new NotImplementedException(); - - [Obsolete($"Use {nameof(Subscription)}.{nameof(SubscriptionResource.CreateProjectUpdatedSubscription)}", true)] - public void SubscribeStreamUpdated(string id) => throw new NotImplementedException(); - - [Obsolete($"Use {nameof(Subscription)}.{nameof(SubscriptionResource.CreateUserProjectsUpdatedSubscription)}", true)] - public void SubscribeUserStreamRemoved() => throw new NotImplementedException(); - - [Obsolete( - $"Use {nameof(Subscription)}.{nameof(SubscriptionResource.CreateProjectCommentsUpdatedSubscription)}", - true - )] - public void SubscribeCommentActivity(string streamId) => throw new NotImplementedException(); -} diff --git a/src/Speckle.Sdk/Api/GraphQL/Legacy/LegacyGraphQLModels.cs b/src/Speckle.Sdk/Api/GraphQL/Legacy/LegacyGraphQLModels.cs deleted file mode 100644 index f237341b..00000000 --- a/src/Speckle.Sdk/Api/GraphQL/Legacy/LegacyGraphQLModels.cs +++ /dev/null @@ -1,367 +0,0 @@ -#nullable disable -using Speckle.Sdk.Api.GraphQL.Enums; -using Speckle.Sdk.Api.GraphQL.Models; - -namespace Speckle.Sdk.Api; - -#region inputs - -internal static class DeprecationMessages -{ - public const string FE1_DEPRECATION_MESSAGE = - $"Stream/Branch/Commit API is now deprecated, Use the new Project/Model/Version API functions in {nameof(Client)}"; -} - -[Obsolete(DeprecationMessages.FE1_DEPRECATION_MESSAGE)] -public class StreamCreateInput -{ - public string name { get; set; } - public string description { get; set; } - public bool isPublic { get; set; } = true; -} - -[Obsolete(DeprecationMessages.FE1_DEPRECATION_MESSAGE)] -public class StreamUpdateInput -{ - public string id { get; set; } - public string name { get; set; } - public string description { get; set; } - public bool isPublic { get; set; } = true; -} - -[Obsolete(DeprecationMessages.FE1_DEPRECATION_MESSAGE)] -public class StreamPermissionInput -{ - public string streamId { get; set; } - public string userId { get; set; } - public string role { get; set; } -} - -[Obsolete(DeprecationMessages.FE1_DEPRECATION_MESSAGE)] -public class StreamRevokePermissionInput -{ - public string streamId { get; set; } - public string userId { get; set; } -} - -[Obsolete(DeprecationMessages.FE1_DEPRECATION_MESSAGE)] -public class StreamInviteCreateInput -{ - public string streamId { get; set; } - public string userId { get; set; } - public string email { get; set; } - public string message { get; set; } - public string role { get; set; } -} - -[Obsolete(DeprecationMessages.FE1_DEPRECATION_MESSAGE)] -public class BranchCreateInput -{ - public string streamId { get; set; } - public string name { get; set; } - public string description { get; set; } -} - -[Obsolete(DeprecationMessages.FE1_DEPRECATION_MESSAGE)] -public class BranchUpdateInput -{ - public string streamId { get; set; } - public string id { get; set; } - public string name { get; set; } - public string description { get; set; } -} - -[Obsolete(DeprecationMessages.FE1_DEPRECATION_MESSAGE)] -public class BranchDeleteInput -{ - public string streamId { get; set; } - public string id { get; set; } -} - -[Obsolete(DeprecationMessages.FE1_DEPRECATION_MESSAGE)] -public class CommitCreateInput -{ - public string streamId { get; set; } - public string branchName { get; set; } - public string objectId { get; set; } - public string message { get; set; } - public string sourceApplication { get; set; } = ".net"; - public int totalChildrenCount { get; set; } - public List parents { get; set; } - - [Obsolete("Please use the parents property. This property will be removed in later versions")] - public List previousCommitIds { get; set; } -} - -[Obsolete(DeprecationMessages.FE1_DEPRECATION_MESSAGE)] -public class CommitUpdateInput -{ - public string streamId { get; set; } - public string id { get; set; } - public string message { get; set; } -} - -[Obsolete(DeprecationMessages.FE1_DEPRECATION_MESSAGE)] -public class CommitDeleteInput -{ - public string streamId { get; set; } - public string id { get; set; } -} - -[Obsolete(DeprecationMessages.FE1_DEPRECATION_MESSAGE)] -public class CommitReceivedInput -{ - public string streamId { get; set; } - public string commitId { get; set; } - public string sourceApplication { get; set; } - public string message { get; set; } -} - -#endregion - -[Obsolete(DeprecationMessages.FE1_DEPRECATION_MESSAGE)] -public class Stream -{ - public string id { get; set; } - public string name { get; set; } - public string description { get; set; } - - public bool isPublic { get; set; } - public string role { get; set; } - public DateTime createdAt { get; set; } - public DateTime updatedAt { get; set; } - public string favoritedDate { get; set; } - - public int commentCount { get; set; } - public int favoritesCount { get; set; } - - public List collaborators { get; set; } - public List pendingCollaborators { get; set; } = new(); - public Branches branches { get; set; } - - /// - /// Set only in the case that you've requested this through . - /// - public Branch branch { get; set; } - - /// - /// Set only in the case that you've requested this through . - /// - public Commit commit { get; set; } - - /// - /// Set only in the case that you've requested this through - /// - public Commits commits { get; set; } - - public ResourceCollection activity { get; set; } - - public SpeckleObject @object { get; set; } - - public override string ToString() - { - return $"Stream ({name} | {id})"; - } -} - -[Obsolete(DeprecationMessages.FE1_DEPRECATION_MESSAGE)] -public class Collaborator -{ - public string id { get; set; } - public string name { get; set; } - public string role { get; set; } - public string avatar { get; set; } - - public override string ToString() - { - return $"Collaborator ({name} | {role} | {id})"; - } -} - -[Obsolete(DeprecationMessages.FE1_DEPRECATION_MESSAGE)] -public class StreamInvitesResponse -{ - public List streamInvites { get; set; } -} - -[Obsolete(DeprecationMessages.FE1_DEPRECATION_MESSAGE)] -public class Branches -{ - public int totalCount { get; set; } - public string cursor { get; set; } - public List items { get; set; } -} - -[Obsolete(DeprecationMessages.FE1_DEPRECATION_MESSAGE)] -public class Commits -{ - public int totalCount { get; set; } - public string cursor { get; set; } - public List items { get; set; } -} - -[Obsolete(DeprecationMessages.FE1_DEPRECATION_MESSAGE)] -public class Commit -{ - public string id { get; set; } - public string message { get; set; } - public string branchName { get; set; } - public string authorName { get; set; } - public string authorId { get; set; } - public string authorAvatar { get; set; } - public DateTime createdAt { get; set; } - public string sourceApplication { get; set; } - - public string referencedObject { get; set; } - public int totalChildrenCount { get; set; } - public List parents { get; set; } - - public override string ToString() - { - return $"Commit ({message} | {id})"; - } -} - -[Obsolete(DeprecationMessages.FE1_DEPRECATION_MESSAGE)] -public class SpeckleObject -{ - public string id { get; set; } - public string speckleType { get; set; } - public string applicationId { get; set; } - public int totalChildrenCount { get; set; } - public DateTime createdAt { get; set; } -} - -[Obsolete(DeprecationMessages.FE1_DEPRECATION_MESSAGE)] -public class Branch -{ - public string id { get; set; } - public string name { get; set; } - public string description { get; set; } - public Commits commits { get; set; } - - public override string ToString() - { - return $"Branch ({name} | {id})"; - } -} - -[Obsolete(DeprecationMessages.FE1_DEPRECATION_MESSAGE)] -public class Streams -{ - public int totalCount { get; set; } - public string cursor { get; set; } - public List items { get; set; } -} - -[Obsolete(DeprecationMessages.FE1_DEPRECATION_MESSAGE)] -public class Resource -{ - public string resourceId { get; set; } - public ResourceType resourceType { get; set; } -} - -[Obsolete(DeprecationMessages.FE1_DEPRECATION_MESSAGE)] -public class Location -{ - public double x { get; set; } - public double y { get; set; } - public double z { get; set; } -} - -[Obsolete(DeprecationMessages.FE1_DEPRECATION_MESSAGE)] -public class UserSearchData -{ - public UserSearch userSearch { get; set; } -} - -[Obsolete(DeprecationMessages.FE1_DEPRECATION_MESSAGE)] -public class UserSearch -{ - public string cursor { get; set; } - public List items { get; set; } -} - -[Obsolete(DeprecationMessages.FE1_DEPRECATION_MESSAGE)] -public class StreamData -{ - public Stream stream { get; set; } -} - -[Obsolete(DeprecationMessages.FE1_DEPRECATION_MESSAGE)] -public class StreamsData -{ - public Streams streams { get; set; } -} - -#region comments -[Obsolete(DeprecationMessages.FE1_DEPRECATION_MESSAGE)] -public class Comments -{ - public int totalCount { get; set; } - public DateTime? cursor { get; set; } - public List items { get; set; } -} - -[Obsolete(DeprecationMessages.FE1_DEPRECATION_MESSAGE)] -public sealed class CommentData -{ - public Comments comments { get; init; } - public List camPos { get; init; } - public object filters { get; init; } - public Location location { get; init; } - public object selection { get; init; } - public object sectionBox { get; init; } -} - -[Obsolete(DeprecationMessages.FE1_DEPRECATION_MESSAGE)] -public class CommentItem -{ - public string id { get; set; } - public string authorId { get; set; } - public bool archived { get; set; } - public string screenshot { get; set; } - public string rawText { get; set; } - public CommentData data { get; set; } - public DateTime createdAt { get; set; } - public DateTime updatedAt { get; set; } - public DateTime? viewedAt { get; set; } - public object reactions { get; set; } - public Comments replies { get; set; } - public List resources { get; set; } -} - -[Obsolete(DeprecationMessages.FE1_DEPRECATION_MESSAGE)] -public class ContentContent -{ - public string Type { get; set; } - - //public Mark[] Marks { get; set; } - public string Text { get; set; } -} - -[Obsolete(DeprecationMessages.FE1_DEPRECATION_MESSAGE)] -public class CommentsData -{ - public Comments comments { get; set; } -} - -[Obsolete(DeprecationMessages.FE1_DEPRECATION_MESSAGE)] -public class CommentItemData -{ - public CommentItem comment { get; set; } -} - -[Obsolete(DeprecationMessages.FE1_DEPRECATION_MESSAGE)] -public class CommentActivityMessage -{ - public string type { get; set; } - public CommentItem comment { get; set; } -} - -[Obsolete(DeprecationMessages.FE1_DEPRECATION_MESSAGE)] -public class CommentActivityResponse -{ - public CommentActivityMessage commentActivity { get; set; } -} -#endregion diff --git a/src/Speckle.Sdk/Api/GraphQL/Legacy/SubscriptionModels.cs b/src/Speckle.Sdk/Api/GraphQL/Legacy/SubscriptionModels.cs deleted file mode 100644 index 454eba57..00000000 --- a/src/Speckle.Sdk/Api/GraphQL/Legacy/SubscriptionModels.cs +++ /dev/null @@ -1,100 +0,0 @@ -#nullable disable -namespace Speckle.Sdk.Api; - -#region streams -[Obsolete(DeprecationMessages.FE1_DEPRECATION_MESSAGE)] -public class StreamInfo -{ - public string id { get; set; } - public string name { get; set; } - public string description { get; set; } - public string sharedBy { get; set; } -} - -[Obsolete(DeprecationMessages.FE1_DEPRECATION_MESSAGE)] -public class UserStreamAddedResult -{ - public StreamInfo userStreamAdded { get; set; } -} - -[Obsolete(DeprecationMessages.FE1_DEPRECATION_MESSAGE)] -public class StreamUpdatedResult -{ - public StreamInfo streamUpdated { get; set; } -} - -[Obsolete(DeprecationMessages.FE1_DEPRECATION_MESSAGE)] -public class UserStreamRemovedResult -{ - public StreamInfo userStreamRemoved { get; set; } -} -#endregion - -#region branches - -[Obsolete(DeprecationMessages.FE1_DEPRECATION_MESSAGE)] -public class BranchInfo -{ - public string id { get; set; } - public string name { get; set; } - public string description { get; set; } - public string streamId { get; set; } - public string authorId { get; set; } -} - -[Obsolete(DeprecationMessages.FE1_DEPRECATION_MESSAGE)] -public class BranchCreatedResult -{ - public BranchInfo branchCreated { get; set; } -} - -[Obsolete(DeprecationMessages.FE1_DEPRECATION_MESSAGE)] -public class BranchUpdatedResult -{ - public BranchInfo branchUpdated { get; set; } -} - -[Obsolete(DeprecationMessages.FE1_DEPRECATION_MESSAGE)] -public class BranchDeletedResult -{ - public BranchInfo branchDeleted { get; set; } -} -#endregion - -#region commits - -[Obsolete(DeprecationMessages.FE1_DEPRECATION_MESSAGE)] -public class CommitInfo -{ - public string id { get; set; } - public string streamId { get; set; } - public string branchName { get; set; } - public string objectId { get; set; } - public string authorId { get; set; } - public string message { get; set; } - public string sourceApplication { get; set; } - public int? totalChildrenCount { get; set; } - public IList parents { get; set; } - - [Obsolete("Please use the parents property. This property will be removed in later versions")] - public IList previousCommitIds { get; set; } -} - -[Obsolete(DeprecationMessages.FE1_DEPRECATION_MESSAGE)] -public class CommitCreatedResult -{ - public CommitInfo commitCreated { get; set; } -} - -[Obsolete(DeprecationMessages.FE1_DEPRECATION_MESSAGE)] -public class CommitUpdatedResult -{ - public CommitInfo commitUpdated { get; set; } -} - -[Obsolete(DeprecationMessages.FE1_DEPRECATION_MESSAGE)] -public class CommitDeletedResult -{ - public CommitInfo commitDeleted { get; set; } -} -#endregion diff --git a/src/Speckle.Sdk/Api/GraphQL/Models/PendingStreamCollaborator.cs b/src/Speckle.Sdk/Api/GraphQL/Models/PendingStreamCollaborator.cs index 57de53f2..b9110664 100644 --- a/src/Speckle.Sdk/Api/GraphQL/Models/PendingStreamCollaborator.cs +++ b/src/Speckle.Sdk/Api/GraphQL/Models/PendingStreamCollaborator.cs @@ -15,10 +15,4 @@ public sealed class PendingStreamCollaborator public LimitedUser invitedBy { get; init; } public LimitedUser user { get; init; } public string token { get; init; } - - [Obsolete(DeprecationMessages.FE1_DEPRECATION_MESSAGE)] - public string streamId { get; init; } - - [Obsolete(DeprecationMessages.FE1_DEPRECATION_MESSAGE)] - public string streamName { get; init; } } diff --git a/src/Speckle.Sdk/Api/GraphQL/Models/ServerInfo.cs b/src/Speckle.Sdk/Api/GraphQL/Models/ServerInfo.cs index 27e93cd6..89533649 100644 --- a/src/Speckle.Sdk/Api/GraphQL/Models/ServerInfo.cs +++ b/src/Speckle.Sdk/Api/GraphQL/Models/ServerInfo.cs @@ -1,9 +1,5 @@ -using System.Runtime.InteropServices; +namespace Speckle.Sdk.Api.GraphQL.Models; -namespace Speckle.Sdk.Api.GraphQL.Models; - -[ClassInterface(ClassInterfaceType.AutoDual)] -[ComVisible(true)] public sealed class ServerInfo { public string name { get; init; } diff --git a/src/Speckle.Sdk/Api/GraphQL/Models/User.cs b/src/Speckle.Sdk/Api/GraphQL/Models/User.cs index 59eab643..0e3990f0 100644 --- a/src/Speckle.Sdk/Api/GraphQL/Models/User.cs +++ b/src/Speckle.Sdk/Api/GraphQL/Models/User.cs @@ -4,14 +4,12 @@ namespace Speckle.Sdk.Api.GraphQL.Models; public abstract class UserBase { - public ResourceCollection activity { get; init; } public string avatar { get; init; } public string bio { get; init; } public string company { get; set; } public string id { get; init; } public string name { get; init; } public string role { get; init; } - public ResourceCollection timeline { get; init; } public bool? verified { get; init; } } diff --git a/src/Speckle.Sdk/Api/Helpers.cs b/src/Speckle.Sdk/Api/Helpers.cs deleted file mode 100644 index 98fb6c47..00000000 --- a/src/Speckle.Sdk/Api/Helpers.cs +++ /dev/null @@ -1,75 +0,0 @@ -using System.Diagnostics.Contracts; -using Speckle.Sdk.Logging; - -namespace Speckle.Sdk.Api; - -public static class Helpers -{ - public const string RELEASES_URL = "https://releases.speckle.dev"; - - /// - /// value to fallback to if the given is - public static string TimeAgo(DateTime? timestamp, string fallback = "Never") - { - return timestamp.HasValue ? TimeAgo(timestamp.Value) : fallback; - } - - /// Formats the given difference between the current system time and the provided - /// into a human readable string - /// - /// - /// A Human readable string - public static string TimeAgo(DateTime timestamp) - { - TimeSpan timeAgo; - - timeAgo = DateTime.UtcNow.Subtract(timestamp); - - if (timeAgo.TotalSeconds < 60) - { - return "just now"; - } - - if (timeAgo.TotalMinutes < 60) - { - return $"{timeAgo.Minutes} minute{PluralS(timeAgo.Minutes)} ago"; - } - - if (timeAgo.TotalHours < 24) - { - return $"{timeAgo.Hours} hour{PluralS(timeAgo.Hours)} ago"; - } - - if (timeAgo.TotalDays < 7) - { - return $"{timeAgo.Days} day{PluralS(timeAgo.Days)} ago"; - } - - if (timeAgo.TotalDays < 30) - { - return $"{timeAgo.Days / 7} week{PluralS(timeAgo.Days / 7)} ago"; - } - - if (timeAgo.TotalDays < 365) - { - return $"{timeAgo.Days / 30} month{PluralS(timeAgo.Days / 30)} ago"; - } - - if (timestamp <= new DateTime(1800, 1, 1)) - { - SpeckleLog.Logger.Warning( - "Tried to calculate {functionName} of a DateTime value that was way in the past: {dateTimeValue}", - nameof(TimeAgo), - timestamp - ); - // We assume this was an error, Likely a non-nullable DateTime was initialized/deserialized to the default - // Instead of potentially lying to the user, lets tell them we don't know what happened. - return "Unknown"; - } - - return $"{timeAgo.Days / 365} year{PluralS(timeAgo.Days / 365)} ago"; - } - - [Pure] - public static string PluralS(int num) => num != 1 ? "s" : ""; -} diff --git a/src/Speckle.Sdk/Api/Operations/Operations.Receive.cs b/src/Speckle.Sdk/Api/Operations/Operations.Receive.cs index bc12f5d0..9c3e7536 100644 --- a/src/Speckle.Sdk/Api/Operations/Operations.Receive.cs +++ b/src/Speckle.Sdk/Api/Operations/Operations.Receive.cs @@ -1,6 +1,6 @@ using System.Collections.Concurrent; using System.Diagnostics; -using Speckle.Sdk.Logging; +using Microsoft.Extensions.Logging; using Speckle.Sdk.Models; using Speckle.Sdk.Serialisation; using Speckle.Sdk.Serialisation.Utilities; @@ -8,7 +8,7 @@ namespace Speckle.Sdk.Api; -public static partial class Operations +public partial class Operations { /// /// Receives an object (and all its sub-children) from the two provided s. @@ -31,7 +31,7 @@ public static partial class Operations /// Deserialization of the requested object(s) failed /// requested cancel /// The requested Speckle Object - public static async Task Receive( + public async Task Receive( string objectId, ITransport? remoteTransport = null, ITransport? localTransport = null, @@ -66,14 +66,14 @@ public static async Task Receive( }; // Setup Logging - using var receiveActivity = SpeckleActivityFactory.Start(); + using var receiveActivity = activityFactory.Start(); receiveActivity?.SetTag("remoteTransportContext", remoteTransport?.TransportContext); receiveActivity?.SetTag("localTransportContext", localTransport.TransportContext); receiveActivity?.SetTag("objectId", objectId); var timer = Stopwatch.StartNew(); // Receive Json - SpeckleLog.Logger.Information( + logger.LogDebug( "Starting receive {objectId} from transports {localTransport} / {remoteTransport}", objectId, localTransport.TransportName, @@ -88,15 +88,12 @@ public static async Task Receive( // Fall back to remote if (remoteTransport is null) { - var ex = new TransportException( + throw new TransportException( $"Could not find specified object using the local transport {localTransport.TransportName}, and you didn't provide a fallback remote from which to pull it." ); - - SpeckleLog.Logger.Error(ex, "Cannot receive object from the given transports {exceptionMessage}", ex.Message); - throw ex; } - SpeckleLog.Logger.Debug( + logger.LogDebug( "Cannot find object {objectId} in the local transport, hitting remote {transportName}", objectId, remoteTransport.TransportName @@ -106,12 +103,12 @@ public static async Task Receive( .ConfigureAwait(false); } - using var activity = SpeckleActivityFactory.Start("Deserialize"); + using var activity = activityFactory.Start("Deserialize"); // Proceed to deserialize the object, now safely knowing that all its children are present in the local (fast) transport. - Base res = await serializer.DeserializeJsonAsync(objString).ConfigureAwait(false); + Base res = await serializer.DeserializeAsync(objString).ConfigureAwait(false); timer.Stop(); - SpeckleLog.Logger.Information( + logger.LogDebug( "Finished receiving {objectId} from {source} in {elapsed} seconds", objectId, remoteTransport?.TransportName, diff --git a/src/Speckle.Sdk/Api/Operations/Operations.Send.cs b/src/Speckle.Sdk/Api/Operations/Operations.Send.cs index 680a3092..7670484e 100644 --- a/src/Speckle.Sdk/Api/Operations/Operations.Send.cs +++ b/src/Speckle.Sdk/Api/Operations/Operations.Send.cs @@ -1,14 +1,14 @@ using System.Collections.Concurrent; using System.Diagnostics; +using Microsoft.Extensions.Logging; using Speckle.Newtonsoft.Json.Linq; -using Speckle.Sdk.Logging; using Speckle.Sdk.Models; using Speckle.Sdk.Serialisation; using Speckle.Sdk.Transports; namespace Speckle.Sdk.Api; -public static partial class Operations +public partial class Operations { /// /// Sends a Speckle Object to the provided and (optionally) the default local cache @@ -21,7 +21,7 @@ public static partial class Operations /// using ServerTransport destination = new(account, streamId); /// var (objectId, references) = await Send(mySpeckleObject, destination, true); /// - public static async Task<(string rootObjId, IReadOnlyDictionary convertedReferences)> Send( + public async Task<(string rootObjId, IReadOnlyDictionary convertedReferences)> Send( Base value, ITransport transport, bool useDefaultCache, @@ -58,7 +58,7 @@ public static partial class Operations /// Serialization or Send operation was unsuccessful /// One or more failed to send /// The requested cancellation - public static async Task<(string rootObjId, IReadOnlyDictionary convertedReferences)> Send( + public async Task<(string rootObjId, IReadOnlyDictionary convertedReferences)> Send( Base value, IReadOnlyCollection transports, Action>? onProgressAction = null, @@ -78,11 +78,11 @@ public static partial class Operations } // make sure all logs in the operation have the proper context - using var activity = SpeckleActivityFactory.Start(); + using var activity = activityFactory.Start(); activity?.SetTag("correlationId", Guid.NewGuid().ToString()); { var sendTimer = Stopwatch.StartNew(); - SpeckleLog.Logger.Information("Starting send operation"); + logger.LogDebug("Starting send operation"); var internalProgressAction = GetInternalProgressAction(onProgressAction); @@ -106,7 +106,7 @@ public static partial class Operations "the elapsed summary doesn't need to add up to the total elapsed... Threading magic..." ); activity?.SetTag("serializerElapsed", serializerV2.Elapsed); - SpeckleLog.Logger.Information( + logger.LogDebug( "Finished sending objects after {elapsed}, result {objectId}", sendTimer.Elapsed.TotalSeconds, rootObjectId @@ -116,11 +116,7 @@ public static partial class Operations } catch (Exception ex) when (!ex.IsFatal()) { - SpeckleLog.Logger.Information( - ex, - "Send operation failed after {elapsed} seconds", - sendTimer.Elapsed.TotalSeconds - ); + logger.LogInformation(ex, "Send operation failed after {elapsed} seconds", sendTimer.Elapsed.TotalSeconds); if (ex is OperationCanceledException or SpeckleException) { throw; diff --git a/src/Speckle.Sdk/Api/Operations/Operations.Serialize.cs b/src/Speckle.Sdk/Api/Operations/Operations.Serialize.cs index 2fd14da6..1c2e3cd3 100644 --- a/src/Speckle.Sdk/Api/Operations/Operations.Serialize.cs +++ b/src/Speckle.Sdk/Api/Operations/Operations.Serialize.cs @@ -5,7 +5,7 @@ namespace Speckle.Sdk.Api; -public static partial class Operations +public partial class Operations { /// /// Serializes a given object. @@ -18,7 +18,7 @@ public static partial class Operations /// The object to serialise /// /// A json string representation of the object. - public static string Serialize(Base value, CancellationToken cancellationToken = default) + public string Serialize(Base value, CancellationToken cancellationToken = default) { var serializer = new SpeckleObjectSerializer { CancellationToken = cancellationToken }; return serializer.Serialize(value); @@ -31,14 +31,14 @@ public static string Serialize(Base value, CancellationToken cancellationToken = /// /// The json string representation of a speckle object that you want to deserialize /// - /// + /// /// was null /// was not valid JSON /// cannot be deserialised to type /// contains closure references (see Remarks) - public static async Task DeserializeAsync(string value, CancellationToken cancellationToken = default) + public async Task DeserializeAsync(string value, CancellationToken cancellationToken = default) { var deserializer = new SpeckleObjectDeserializer { CancellationToken = cancellationToken }; - return await deserializer.DeserializeJsonAsync(value).ConfigureAwait(false); + return await deserializer.DeserializeAsync(value).ConfigureAwait(false); } } diff --git a/src/Speckle.Sdk/Api/Operations/Operations.cs b/src/Speckle.Sdk/Api/Operations/Operations.cs index 2a961774..a1c4d960 100644 --- a/src/Speckle.Sdk/Api/Operations/Operations.cs +++ b/src/Speckle.Sdk/Api/Operations/Operations.cs @@ -1,4 +1,7 @@ using System.Collections.Concurrent; +using Microsoft.Extensions.Logging; +using Speckle.InterfaceGenerator; +using Speckle.Sdk.Logging; using Speckle.Sdk.Transports; namespace Speckle.Sdk.Api; @@ -8,7 +11,8 @@ namespace Speckle.Sdk.Api; /// Serialize/Deserialize /// Push/Pull (methods to serialize and send data to one or more servers) /// -public static partial class Operations +[GenerateAutoInterface] +public partial class Operations(ILogger logger, ISdkActivityFactory activityFactory) : IOperations { /// /// Factory for progress actions used internally inside send and receive methods. diff --git a/src/Speckle.Sdk/Credentials/Account.cs b/src/Speckle.Sdk/Credentials/Account.cs index 8381f45f..98cd30e7 100644 --- a/src/Speckle.Sdk/Credentials/Account.cs +++ b/src/Speckle.Sdk/Credentials/Account.cs @@ -72,12 +72,6 @@ public string GetHashedServer() return Crypt.Md5(CleanURL(url), "X2"); } - public async Task Validate() - { - Uri server = new(serverInfo.url); - return await AccountManager.GetUserInfo(token, server).ConfigureAwait(false); - } - public override string ToString() { return $"Account ({userInfo.email} | {serverInfo.url})"; diff --git a/src/Speckle.Sdk/Credentials/AccountManager.cs b/src/Speckle.Sdk/Credentials/AccountManager.cs index 61e657ae..affa6dfc 100644 --- a/src/Speckle.Sdk/Credentials/AccountManager.cs +++ b/src/Speckle.Sdk/Credentials/AccountManager.cs @@ -6,6 +6,8 @@ using System.Text.RegularExpressions; using GraphQL; using GraphQL.Client.Http; +using Microsoft.Extensions.Logging; +using Speckle.InterfaceGenerator; using Speckle.Newtonsoft.Json; using Speckle.Sdk.Api; using Speckle.Sdk.Api.GraphQL; @@ -23,7 +25,9 @@ namespace Speckle.Sdk.Credentials; /// /// Manage accounts locally for desktop applications. /// -public static class AccountManager +[GenerateAutoInterface] +public class AccountManager(ISpeckleApplication application, ILogger logger, ISpeckleHttp speckleHttp) + : IAccountManager { public const string DEFAULT_SERVER_URL = "https://app.speckle.systems"; @@ -36,9 +40,9 @@ public static class AccountManager /// /// Server URL /// - public static async Task GetServerInfo(Uri server, CancellationToken cancellationToken = default) + public async Task GetServerInfo(Uri server, CancellationToken cancellationToken = default) { - using var httpClient = Http.GetHttpProxyClient(); + using var httpClient = speckleHttp.CreateHttpClient(); using var gqlClient = new GraphQLHttpClient( new GraphQLHttpClientOptions @@ -96,14 +100,9 @@ public static async Task GetServerInfo(Uri server, CancellationToken /// /// Server URL /// - public static async Task GetUserInfo( - string token, - Uri server, - CancellationToken cancellationToken = default - ) + public async Task GetUserInfo(string token, Uri server, CancellationToken cancellationToken = default) { - using var httpClient = Http.GetHttpProxyClient(); - Http.AddAuthHeader(httpClient, token); + using var httpClient = speckleHttp.CreateHttpClient(authorizationToken: token); using var gqlClient = new GraphQLHttpClient( new GraphQLHttpClientOptions { EndPoint = new Uri(server, "/graphql") }, @@ -141,7 +140,7 @@ public static async Task GetUserInfo( /// /// Server URL /// - internal static async Task GetUserServerInfo( + internal async Task GetUserServerInfo( string token, Uri server, CancellationToken ct = default @@ -149,8 +148,7 @@ internal static async Task GetUserServerInfo( { try { - using var httpClient = Http.GetHttpProxyClient(); - Http.AddAuthHeader(httpClient, token); + using var httpClient = speckleHttp.CreateHttpClient(authorizationToken: token); using var client = new GraphQLHttpClient( new GraphQLHttpClientOptions { EndPoint = new Uri(server, "/graphql") }, @@ -206,7 +204,7 @@ internal static async Task GetUserServerInfo( /// /// The Default Server URL for authentication, can be overridden by placing a file with the alternatrive url in the Speckle folder or with an ENV_VAR /// - public static Uri GetDefaultServerUrl() + public Uri GetDefaultServerUrl() { var customServerUrl = ""; @@ -238,7 +236,7 @@ public static Uri GetDefaultServerUrl() /// The Id of the account to fetch /// /// Account with was not found - public static Account GetAccount(string id) + public Account GetAccount(string id) { return GetAccounts().FirstOrDefault(acc => acc.id == id) ?? throw new SpeckleAccountManagerException($"Account {id} not found"); @@ -248,7 +246,7 @@ public static Account GetAccount(string id) /// Upgrades an account from the account.serverInfo.movedFrom account to the account.serverInfo.movedTo account /// /// Id of the account to upgrade - public static async Task UpgradeAccount(string id) + public async Task UpgradeAccount(string id) { Account account = GetAccount(id); @@ -272,7 +270,7 @@ public static async Task UpgradeAccount(string id) await s_accountStorage.WriteComplete().ConfigureAwait(false); } - public static IEnumerable GetAccounts(string serverUrl) + public IEnumerable GetAccounts(string serverUrl) { return GetAccounts(new Uri(serverUrl)); } @@ -283,7 +281,7 @@ public static IEnumerable GetAccounts(string serverUrl) /// Accounts are deemed to be the same when the Account.Id matches. /// /// Uri for server. - public static IEnumerable GetAccounts(Uri serverUrl) + public IEnumerable GetAccounts(Uri serverUrl) { var accounts = GetAccounts().ToList(); List filtered = new(); @@ -313,7 +311,7 @@ public static IEnumerable GetAccounts(Uri serverUrl) /// Gets this environment's default account if any. If there is no default, the first found will be returned and set as default. /// /// The default account or null. - public static Account? GetDefaultAccount() + public Account? GetDefaultAccount() { var defaultAccount = GetAccounts().FirstOrDefault(acc => acc.isDefault); if (defaultAccount != null) @@ -324,7 +322,7 @@ public static IEnumerable GetAccounts(Uri serverUrl) var firstAccount = GetAccounts().FirstOrDefault(); if (firstAccount == null) { - SpeckleLog.Logger.Information("No Speckle accounts found. Visit the Speckle web app to create one"); + logger.LogInformation("No Speckle accounts found. Visit the Speckle web app to create one"); } return firstAccount; @@ -335,7 +333,7 @@ public static IEnumerable GetAccounts(Uri serverUrl) /// /// This function does have potential side effects. Any invalid accounts found while enumerating will be removed /// Un-enumerated enumerable of accounts - public static IEnumerable GetAccounts() + public IEnumerable GetAccounts() { static bool IsInvalid(Account ac) => ac.userInfo == null || ac.serverInfo == null; @@ -366,7 +364,7 @@ public static IEnumerable GetAccounts() /// These are accounts not handled by Manager and are stored in json format in a local directory /// /// - private static IList GetLocalAccounts() + private IList GetLocalAccounts() { var accountsDir = SpecklePathProvider.AccountsFolderPath; if (!Directory.Exists(accountsDir)) @@ -398,7 +396,7 @@ account is not null } catch (Exception ex) when (!ex.IsFatal()) { - SpeckleLog.Logger.Warning(ex, "Failed to load json account at {filePath}", file); + logger.LogWarning(ex, "Failed to load json account at {filePath}", file); } } @@ -409,7 +407,7 @@ account is not null /// Refetches user and server info for each account /// /// - public static async Task UpdateAccounts(CancellationToken ct = default) + public async Task UpdateAccounts(CancellationToken ct = default) { // need to ToList() the GetAccounts call or the UpdateObject call at the end of this method // will not work because sqlite does not support concurrent db calls @@ -458,7 +456,7 @@ public static async Task UpdateAccounts(CancellationToken ct = default) /// Removes an account /// /// ID of the account to remove - public static void RemoveAccount(string id) + public void RemoveAccount(string id) { //TODO: reset default account s_accountStorage.DeleteObject(id); @@ -475,7 +473,7 @@ public static void RemoveAccount(string id) /// Changes the default account /// /// - public static void ChangeDefaultAccount(string id) + public void ChangeDefaultAccount(string id) { foreach (var account in GetAccounts()) { @@ -500,7 +498,7 @@ public static void ChangeDefaultAccount(string id) /// /// /// - public static Uri? GetLocalIdentifierForAccount(Account account) + public Uri? GetLocalIdentifierForAccount(Account account) { var identifier = account.GetLocalIdentifier(); @@ -510,12 +508,18 @@ public static void ChangeDefaultAccount(string id) return searchResult == null ? null : identifier; } + public async Task Validate(Account account) + { + Uri server = new(account.serverInfo.url); + return await GetUserInfo(account.token, server).ConfigureAwait(false); + } + /// /// Gets the account that corresponds to the given local identifier. /// /// The local identifier of the account. /// The account that matches the local identifier, or null if no match is found. - public static Account? GetAccountForLocalIdentifier(Uri localIdentifier) + public Account? GetAccountForLocalIdentifier(Uri localIdentifier) { var searchResult = GetAccounts() .FirstOrDefault(acc => @@ -527,34 +531,31 @@ public static void ChangeDefaultAccount(string id) return searchResult; } - private static Uri EnsureCorrectServerUrl(Uri? server) + private Uri EnsureCorrectServerUrl(Uri? server) { var localUrl = server; if (localUrl == null) { localUrl = GetDefaultServerUrl(); - SpeckleLog.Logger.Debug( - "The provided server url was null or empty. Changed to the default url {serverUrl}", - localUrl - ); + logger.LogDebug("The provided server url was null or empty. Changed to the default url {serverUrl}", localUrl); } return localUrl; } - private static void EnsureGetAccessCodeFlowIsSupported() + private void EnsureGetAccessCodeFlowIsSupported() { if (!HttpListener.IsSupported) { - SpeckleLog.Logger.Error("HttpListener not supported"); + logger.LogError("HttpListener not supported"); throw new PlatformNotSupportedException("Your operating system is not supported"); } } - private static async Task GetAccessCode(Uri server, string challenge, TimeSpan timeout) + private async Task GetAccessCode(Uri server, string challenge, TimeSpan timeout) { EnsureGetAccessCodeFlowIsSupported(); - SpeckleLog.Logger.Debug("Starting auth process for {server}/authn/verify/sca/{challenge}", server, challenge); + logger.LogDebug("Starting auth process for {server}/authn/verify/sca/{challenge}", server, challenge); var accessCode = ""; @@ -566,14 +567,14 @@ private static async Task GetAccessCode(Uri server, string challenge, Ti var localUrl = "http://localhost:29363/"; listener.Prefixes.Add(localUrl); listener.Start(); - SpeckleLog.Logger.Debug("Listening for auth redirects on {localUrl}", localUrl); + logger.LogDebug("Listening for auth redirects on {localUrl}", localUrl); // Note: The GetContext method blocks while waiting for a request. HttpListenerContext context = listener.GetContext(); HttpListenerRequest request = context.Request; HttpListenerResponse response = context.Response; accessCode = request.QueryString["access_code"]; - SpeckleLog.Logger.Debug("Got access code {accessCode}", accessCode); + logger.LogDebug("Got access code {accessCode}", accessCode); string message = accessCode != null @@ -587,7 +588,7 @@ private static async Task GetAccessCode(Uri server, string challenge, Ti Stream output = response.OutputStream; output.Write(buffer, 0, buffer.Length); output.Close(); - SpeckleLog.Logger.Debug("Processed finished processing the access code"); + logger.LogDebug("Processed finished processing the access code"); listener.Stop(); listener.Close(); }); @@ -597,7 +598,7 @@ private static async Task GetAccessCode(Uri server, string challenge, Ti // this is means the task timed out if (completedTask != task) { - SpeckleLog.Logger.Warning( + logger.LogWarning( "Local auth flow failed to complete within the timeout window. Access code is {accessCode}", accessCode ); @@ -606,7 +607,7 @@ private static async Task GetAccessCode(Uri server, string challenge, Ti if (task.IsFaulted && task.Exception is not null) { - SpeckleLog.Logger.Error( + logger.LogError( task.Exception, "Getting access code flow failed with {exceptionMessage}", task.Exception.Message @@ -615,14 +616,14 @@ private static async Task GetAccessCode(Uri server, string challenge, Ti } // task completed within timeout - SpeckleLog.Logger.Information( + logger.LogInformation( "Local auth flow completed successfully within the timeout window. Access code is {accessCode}", accessCode ); return accessCode; } - private static async Task CreateAccount(string accessCode, string challenge, Uri server) + private async Task CreateAccount(string accessCode, string challenge, Uri server) { try { @@ -637,7 +638,7 @@ private static async Task CreateAccount(string accessCode, string chall serverInfo = userResponse.serverInfo, userInfo = userResponse.activeUser }; - SpeckleLog.Logger.Information("Successfully created account for {serverUrl}", server); + logger.LogInformation("Successfully created account for {serverUrl}", server); return account; } @@ -647,7 +648,7 @@ private static async Task CreateAccount(string accessCode, string chall } } - private static void TryLockAccountAddFlow(TimeSpan timespan) + private static void TryLockAccountAddFlow(ISpeckleApplication application, TimeSpan timespan) { // use a static variable to quickly // prevent launching this flow multiple times @@ -678,7 +679,7 @@ private static void TryLockAccountAddFlow(TimeSpan timespan) } } - var lockId = Setup.ApplicationVersion + "@" + DateTime.Now.Add(timespan).ToString("o"); + var lockId = application.ApplicationVersion + "@" + DateTime.Now.Add(timespan).ToString("o"); // using the lock release time as an id and value // for ease of deletion and retrieval @@ -701,9 +702,9 @@ private static void UnlockAccountAddFlow() /// /// Server to use to add the account, if not provied the default Server will be used /// - public static async Task AddAccount(Uri? server = null) + public async Task AddAccount(Uri? server = null) { - SpeckleLog.Logger.Debug("Starting to add account for {serverUrl}", server); + logger.LogDebug("Starting to add account for {serverUrl}", server); server = EnsureCorrectServerUrl(server); @@ -711,7 +712,7 @@ public static async Task AddAccount(Uri? server = null) var timeout = TimeSpan.FromMinutes(1); // this is not part of the try finally block // we do not want to clean up the existing locks - TryLockAccountAddFlow(timeout); + TryLockAccountAddFlow(application, timeout); var challenge = GenerateChallenge(); try @@ -726,17 +727,17 @@ public static async Task AddAccount(Uri? server = null) //if the account already exists it will not be added again s_accountStorage.SaveObject(account.id, JsonConvert.SerializeObject(account)); - SpeckleLog.Logger.Debug("Finished adding account {accountId} for {serverUrl}", account.id, server); + logger.LogDebug("Finished adding account {accountId} for {serverUrl}", account.id, server); } catch (SpeckleAccountManagerException ex) { - SpeckleLog.Logger.Fatal(ex, "Failed to add account: {exceptionMessage}", ex.Message); + logger.LogCritical(ex, "Failed to add account: {exceptionMessage}", ex.Message); // rethrowing any known errors throw; } catch (Exception ex) when (!ex.IsFatal()) { - SpeckleLog.Logger.Fatal(ex, "Failed to add account: {exceptionMessage}", ex.Message); + logger.LogCritical(ex, "Failed to add account: {exceptionMessage}", ex.Message); throw new SpeckleAccountManagerException($"Failed to add account: {ex.Message}", ex); } finally @@ -745,11 +746,11 @@ public static async Task AddAccount(Uri? server = null) } } - private static async Task GetToken(string accessCode, string challenge, Uri server) + private async Task GetToken(string accessCode, string challenge, Uri server) { try { - using var client = Http.GetHttpProxyClient(); + using var client = speckleHttp.CreateHttpClient(); var body = new { @@ -773,11 +774,11 @@ private static async Task GetToken(string accessCode, str } } - private static async Task GetRefreshedToken(string refreshToken, Uri server) + private async Task GetRefreshedToken(string refreshToken, Uri server) { try { - using var client = Http.GetHttpProxyClient(); + using var client = speckleHttp.CreateHttpClient(); var body = new { @@ -807,11 +808,11 @@ private static async Task GetRefreshedToken(string refres /// if response contains FE2 header and the value was /// response contained FE2 header, but the value was , empty, or not parseable to a /// Request to failed to send or response was not successful - private static async Task IsFrontend2Server(Uri server) + private async Task IsFrontend2Server(Uri server) { - using var httpClient = Http.GetHttpProxyClient(); + using var httpClient = speckleHttp.CreateHttpClient(); - var response = await Http.HttpPing(server).ConfigureAwait(false); + var response = await speckleHttp.HttpPing(server).ConfigureAwait(false); var headers = response.Headers; const string HEADER = "x-speckle-frontend-2"; diff --git a/src/Speckle.Sdk/Credentials/Responses.cs b/src/Speckle.Sdk/Credentials/Responses.cs index 17ca4895..45d65f69 100644 --- a/src/Speckle.Sdk/Credentials/Responses.cs +++ b/src/Speckle.Sdk/Credentials/Responses.cs @@ -1,4 +1,3 @@ -using System.Runtime.InteropServices; using Speckle.Sdk.Api.GraphQL.Models; namespace Speckle.Sdk.Credentials; @@ -15,8 +14,6 @@ internal sealed class TokenExchangeResponse public string refreshToken { get; init; } } -[ClassInterface(ClassInterfaceType.AutoDual)] -[ComVisible(true)] public sealed class UserInfo { public string id { get; init; } diff --git a/src/Speckle.Sdk/Credentials/StreamWrapper.cs b/src/Speckle.Sdk/Credentials/StreamWrapper.cs deleted file mode 100644 index e02b3dd3..00000000 --- a/src/Speckle.Sdk/Credentials/StreamWrapper.cs +++ /dev/null @@ -1,506 +0,0 @@ -using System.Diagnostics.CodeAnalysis; -using System.Text.RegularExpressions; -using System.Web; -using Speckle.Sdk.Api; -using Speckle.Sdk.Common; -using Speckle.Sdk.Helpers; - -namespace Speckle.Sdk.Credentials; - -[SuppressMessage("Design", "CA1054:URI-like parameters should not be strings", Justification = "Class needs re-write")] -[SuppressMessage("Usage", "CA2234:Pass system uri objects instead of strings", Justification = "Class needs re-write")] -public class StreamWrapper -{ - private Account? _account; - - public StreamWrapper() { } - - /// - /// Creates a StreamWrapper from a stream url or a stream id - /// - /// Stream Url eg: http://speckle.server/streams/8fecc9aa6d/commits/76a23d7179 or stream ID eg: 8fecc9aa6d - /// - public StreamWrapper(string streamUrlOrId) - { - OriginalInput = streamUrlOrId; - - if (!Uri.TryCreate(streamUrlOrId, UriKind.Absolute, out _)) - { - StreamWrapperFromId(streamUrlOrId); - } - else - { - StreamWrapperFromUrl(streamUrlOrId); - } - } - - /// - /// Creates a StreamWrapper by streamId, userId and serverUrl - /// - /// - /// - /// - public StreamWrapper(string streamId, string? userId, string serverUrl) - { - UserId = userId; - ServerUrl = serverUrl; - StreamId = streamId; - - OriginalInput = $"{ServerUrl}/streams/{StreamId}{(UserId != null ? "?u=" + UserId : "")}"; - } - - //this needs to be public so it's serialized and stored in Dynamo - public string? OriginalInput { get; set; } - - public string? UserId { get; set; } - public string ServerUrl { get; set; } - public string StreamId { get; set; } - public string? CommitId { get; set; } - - /// May be an ID instead for FE2 urls - public string? BranchName { get; set; } - public string? ObjectId { get; set; } - - /// - /// Determines if the current stream wrapper contains a valid stream. - /// - public bool IsValid => Type != StreamWrapperType.Undefined; - - public StreamWrapperType Type - { - // Quick solution to determine whether a wrapper points to a branch, commit or stream. - get - { - if (!string.IsNullOrEmpty(ObjectId)) - { - return StreamWrapperType.Object; - } - - if (!string.IsNullOrEmpty(CommitId)) - { - return StreamWrapperType.Commit; - } - - if (!string.IsNullOrEmpty(BranchName)) - { - return StreamWrapperType.Branch; - } - - // If we reach here and there is no stream id, it means that the stream is invalid for some reason. - return !string.IsNullOrEmpty(StreamId) ? StreamWrapperType.Stream : StreamWrapperType.Undefined; - } - } - - private void StreamWrapperFromId(string streamId) - { - Account? account = AccountManager.GetDefaultAccount(); - - if (account == null) - { - throw new SpeckleException("You do not have any account. Please create one or add it to the Speckle Manager."); - } - - ServerUrl = account.serverInfo.url; - UserId = account.userInfo.id; - StreamId = streamId; - } - - /// - /// The ReGex pattern to determine if a URL's AbsolutePath is a Frontend2 URL or not. - /// This is used in conjunction with to extract the correct values into the instance. - /// - private static readonly Regex s_fe2UrlRegex = - new( - @"/projects/(?[\w\d]+)(?:/models/(?[\w\d]+(?:@[\w\d]+)?)(?:,(?[\w\d]+(?:@[\w\d]+)?))*)?" - ); - - /// - /// Parses a FrontEnd2 URL Regex match and assigns it's data to this StreamWrapper instance. - /// - /// A regex match coming from - /// Will throw when the URL is not properly formatted. - /// Will throw when the URL is correct, but is not currently supported by the StreamWrapper class. - private void ParseFe2RegexMatch(Match match) - { - var projectId = match.Groups["projectId"]; - var model = match.Groups["model"]; - var additionalModels = match.Groups["additionalModels"]; - - if (!projectId.Success) - { - throw new SpeckleException("The provided url is not a valid Speckle url"); - } - - if (!model.Success) - { - throw new SpeckleException("The provided url is not pointing to any model in the project."); - } - - if (additionalModels.Success || model.Value == "all") - { - throw new NotSupportedException("Multi-model urls are not supported yet"); - } -#if NETSTANDARD2_0 - if (model.Value.StartsWith("$")) -#else - if (model.Value.StartsWith('$')) -#endif - { - throw new NotSupportedException("Federation model urls are not supported"); - } - - var modelRes = ParseFe2ModelValue(model.Value); - - // INFO: The Branch endpoint is being updated to fallback to checking a branch ID if no name is found. - // Assigning the BranchID as the BranchName is a workaround to support FE2 links in the old StreamWrapper. - // A better solution must be redesigned taking into account all the new Frontend2 URL features. - StreamId = projectId.Value; - BranchName = modelRes.branchId; - CommitId = modelRes.commitId; - ObjectId = modelRes.objectId; - } - - /// - /// Parses the segment of the FE2 URL that represents a modelID, modelID@versionID or objectID. - /// It is meant to parse a single value. If url is multi-model it should be used once per model. - /// - /// The a single value of the model url segment - /// A tuple containing the branch, commit and object information for that value. Each value can be null - /// Determines if a modelValue is an ObjectId by checking it's length is exactly 32 chars long. - private static (string? branchId, string? commitId, string? objectId) ParseFe2ModelValue(string modelValue) - { - if (modelValue.Length == 32) - { - return (null, null, modelValue); // Model value is an ObjectID - } - - if (!modelValue.Contains('@')) - { - return (modelValue, null, null); // Model has no version attached - } - - var res = modelValue.Split('@'); - return (res[0], res[1], null); // Model has version attached - } - - private void StreamWrapperFromUrl(string streamUrl) - { - Uri uri = new(streamUrl); - ServerUrl = uri.GetLeftPart(UriPartial.Authority); - - var fe2Match = s_fe2UrlRegex.Match(uri.AbsolutePath); - if (fe2Match.Success) - { - //NEW FRONTEND URL! - ParseFe2RegexMatch(fe2Match); - return; - } - - // Note: this is a hack. It's because new Uri() is parsed escaped in .net framework; wheareas in .netstandard it's not. - // Tests pass in Speckle.Sdk without this hack. - if (uri.Segments.Length >= 4 && uri.Segments[3]?.ToLowerInvariant() == "branches/") - { - StreamId = uri.Segments[2].Replace("/", ""); - if (uri.Segments.Length > 5) - { - var branchSegs = uri.Segments.ToList().GetRange(4, uri.Segments.Length - 4); - BranchName = Uri.UnescapeDataString(string.Concat(branchSegs)); - } - else - { - BranchName = Uri.UnescapeDataString(uri.Segments[4]); - } - } - else - { - switch (uri.Segments.Length) - { - case 3: // ie http://speckle.server/streams/8fecc9aa6d - if (!uri.Segments[1].Equals("streams/", StringComparison.InvariantCultureIgnoreCase)) - { - throw new SpeckleException($"Cannot parse {uri} into a stream wrapper class."); - } - else - { - StreamId = uri.Segments[2].Replace("/", ""); - } - - break; - case 4: // ie https://speckle.server/streams/0c6ad366c4/globals/ - if (uri.Segments[3].StartsWith("globals", StringComparison.InvariantCultureIgnoreCase)) - { - StreamId = uri.Segments[2].Replace("/", ""); - BranchName = Uri.UnescapeDataString(uri.Segments[3].Replace("/", "")); - } - else - { - throw new SpeckleException($"Cannot parse {uri} into a stream wrapper class"); - } - - break; - case 5: // ie http://speckle.server/streams/8fecc9aa6d/commits/76a23d7179 - switch (uri.Segments[3].ToLowerInvariant()) - { - // NOTE: this is a good practice reminder on how it should work - case "commits/": - StreamId = uri.Segments[2].Replace("/", ""); - CommitId = uri.Segments[4].Replace("/", ""); - break; - case "globals/": - StreamId = uri.Segments[2].Replace("/", ""); - BranchName = Uri.UnescapeDataString(uri.Segments[3].Replace("/", "")); - CommitId = uri.Segments[4].Replace("/", ""); - break; - case "branches/": - StreamId = uri.Segments[2].Replace("/", ""); - BranchName = Uri.UnescapeDataString(uri.Segments[4].Replace("/", "")); - break; - case "objects/": - StreamId = uri.Segments[2].Replace("/", ""); - ObjectId = uri.Segments[4].Replace("/", ""); - break; - default: - throw new SpeckleException($"Cannot parse {uri} into a stream wrapper class."); - } - - break; - - default: - throw new SpeckleException($"Cannot parse {uri} into a stream wrapper class."); - } - } - - var queryDictionary = HttpUtility.ParseQueryString(uri.Query); - UserId = queryDictionary["u"]; - } - - /// - /// Gets a valid account for this stream wrapper. - /// Note: this method ensures that the stream exists and/or that the user has an account which has access to that stream. If used in a sync manner, make sure it's not blocking. - /// - /// Throws exception if account fetching failed. This could be due to non-existent account or stream. - /// The valid account object for this stream. - public async Task GetAccount() - { - if (_account != null) - { - return _account; - } - - // Step 1: check if direct account id (?u=) - if (OriginalInput != null && OriginalInput.Contains("?u=")) - { - var userId = OriginalInput.Split(new[] { "?u=" }, StringSplitOptions.None)[1]; - var acc = AccountManager.GetAccounts().FirstOrDefault(acc => acc.userInfo.id == userId); - if (acc != null) - { - await ValidateWithAccount(acc).ConfigureAwait(false); - _account = acc; - return acc; - } - } - - // Step 2: check the default - var defAcc = AccountManager.GetDefaultAccount(); - List err = new(); - try - { - defAcc.NotNull(); - await ValidateWithAccount(defAcc).ConfigureAwait(false); - _account = defAcc; - return defAcc; - } - catch (Exception ex) when (!ex.IsFatal()) - { - err.Add(new SpeckleException($"Account {defAcc?.userInfo?.email} failed to auth stream wrapper", ex)); - } - - // Step 3: all the rest - var accs = AccountManager.GetAccounts(ServerUrl).ToList(); - if (accs.Count == 0) - { - throw new SpeckleException($"You don't have any accounts for {ServerUrl}."); - } - - foreach (var acc in accs) - { - try - { - await ValidateWithAccount(acc).ConfigureAwait(false); - _account = acc; - return acc; - } - catch (Exception ex) when (!ex.IsFatal()) - { - err.Add(new SpeckleException($"Account {acc} failed to auth stream wrapper", ex)); - } - } - - AggregateException inner = new(null, err); - throw new SpeckleException("Failed to validate stream wrapper", inner); - } - - public void SetAccount(Account acc) - { - _account = acc; - UserId = _account.userInfo.id; - } - - public bool Equals(StreamWrapper? wrapper) - { - if (wrapper == null) - { - return false; - } - - if (Type != wrapper.Type) - { - return false; - } - - return Type == wrapper.Type - && ServerUrl == wrapper.ServerUrl - && UserId == wrapper.UserId - && StreamId == wrapper.StreamId - && Type == StreamWrapperType.Branch - && BranchName == wrapper.BranchName - || Type == StreamWrapperType.Object && ObjectId == wrapper.ObjectId - || Type == StreamWrapperType.Commit && CommitId == wrapper.CommitId; - } - - /// - /// Verifies that the state of the stream wrapper represents a valid Speckle resource e.g. points to a valid stream/branch etc. - /// - /// The account to use to verify the current state of the stream wrapper - /// The of the provided is invalid or does not match the 's - /// You are not connected to the internet - /// Verification of the current state of the stream wrapper with provided was unsuccessful. The could be invalid, or lack permissions for the , or the or are invalid - public async Task ValidateWithAccount(Account acc) - { - Uri url; - try - { - url = new(ServerUrl); - } - catch (UriFormatException ex) - { - throw new ArgumentException("Server Url is improperly formatted", nameof(acc), ex); - } - - if (ServerUrl != acc.serverInfo.url && url != acc.serverInfo.migration?.movedFrom) - { - throw new ArgumentException($"Account is not from server {ServerUrl}", nameof(acc)); - } - - try - { - await Http.HttpPing(url).ConfigureAwait(false); - } - catch (HttpRequestException ex) - { - throw new HttpRequestException("You are not connected to the internet.", ex); - } - - using var client = new Client(acc); - // First check if the stream exists - try - { - await client.StreamGet(StreamId).ConfigureAwait(false); - } - catch (Exception ex) when (!ex.IsFatal()) - { - throw new SpeckleException( - $"You don't have access to stream {StreamId} on server {ServerUrl}, or the stream does not exist.", - ex - ); - } - - // Check if the branch exists - if (Type == StreamWrapperType.Branch) - { - var branch = await client.BranchGet(StreamId, BranchName.NotNull(), 1).ConfigureAwait(false); - if (branch == null) - { - throw new SpeckleException( - $"The branch with name '{BranchName}' doesn't exist in stream {StreamId} on server {ServerUrl}" - ); - } - } - } - - public Uri ToServerUri() - { - if (_account != null) - { - return _account.serverInfo.frontend2 ? ToProjectUri() : ToStreamUri(); - } - - if (OriginalInput != null) - { - Uri uri = new(OriginalInput); - var fe2Match = s_fe2UrlRegex.Match(uri.AbsolutePath); - return fe2Match.Success ? ToProjectUri() : ToStreamUri(); - } - - // Default to old FE1 - return ToStreamUri(); - } - - private Uri ToProjectUri() - { - var uri = new Uri(ServerUrl); - - // TODO: THis has to be the branch ID or it won't work. - var branchID = BranchName; - var leftPart = $"projects/{StreamId}/models/"; - switch (Type) - { - case StreamWrapperType.Commit: - leftPart += $"{branchID}@{CommitId}"; - break; - case StreamWrapperType.Branch: - leftPart += $"{branchID}"; - break; - case StreamWrapperType.Object: - leftPart += $"{ObjectId}"; - break; - } - var acc = $"{(UserId != null ? "?u=" + UserId : "")}"; - - var finalUri = new Uri(uri, leftPart + acc); - return finalUri; - } - - private Uri ToStreamUri() - { - var uri = new Uri(ServerUrl); - var leftPart = $"streams/{StreamId}"; - switch (Type) - { - case StreamWrapperType.Commit: - leftPart += $"/commits/{CommitId}"; - break; - case StreamWrapperType.Branch: - leftPart += $"/branches/{BranchName}"; - break; - case StreamWrapperType.Object: - leftPart += $"/objects/{ObjectId}"; - break; - } - var acc = $"{(UserId != null ? "?u=" + UserId : "")}"; - - var finalUri = new Uri(uri, leftPart + acc); - return finalUri; - } - - public override string ToString() => ToServerUri().ToString(); -} - -public enum StreamWrapperType -{ - Undefined, - Stream, - Commit, - Branch, - Object -} diff --git a/src/Speckle.Sdk/Helpers/Http.cs b/src/Speckle.Sdk/Helpers/Http.cs index fecbac47..8f17e0ab 100644 --- a/src/Speckle.Sdk/Helpers/Http.cs +++ b/src/Speckle.Sdk/Helpers/Http.cs @@ -1,166 +1,56 @@ using System.Net; -using System.Net.NetworkInformation; -using System.Net.Sockets; +using Microsoft.Extensions.Logging; using Polly; -using Polly.Contrib.WaitAndRetry; -using Polly.Extensions.Http; -using Polly.Timeout; +using Speckle.InterfaceGenerator; using Speckle.Sdk.Common; -using Speckle.Sdk.Credentials; -using Speckle.Sdk.Logging; namespace Speckle.Sdk.Helpers; -public static class Http +[GenerateAutoInterface] +public class SpeckleHttp(ILogger logger, ISpeckleHttpClientHandlerFactory speckleHttpClientHandlerFactory) + : ISpeckleHttp { - public const int DEFAULT_TIMEOUT_SECONDS = 60; - - public static IEnumerable DefaultDelay() - { - return Backoff.DecorrelatedJitterBackoffV2(TimeSpan.FromMilliseconds(200), 5); - } - - public static IAsyncPolicy HttpAsyncPolicy( - IEnumerable? delay = null, - int timeoutSeconds = DEFAULT_TIMEOUT_SECONDS - ) - { - var retryPolicy = HttpPolicyExtensions - .HandleTransientHttpError() - .Or() - .WaitAndRetryAsync( - delay ?? DefaultDelay(), - (ex, timeSpan, retryAttempt, context) => - { - context.Remove("retryCount"); - context.Add("retryCount", retryAttempt); - } - ); - - var timeoutPolicy = Policy.TimeoutAsync(timeoutSeconds); - - return Policy.WrapAsync(retryPolicy, timeoutPolicy); - } - - /// - /// Checks if the user has a valid internet connection by first pinging cloudfare (fast) - /// and then trying get from the default Speckle server (slower) - /// - /// True if the user is connected to the internet, false otherwise. - public static async Task UserHasInternet() - { - Uri? defaultServer = null; - try - { - //Perform a quick ping test e.g. to cloudflaire dns, as is quicker than pinging server - if (await Ping("1.1.1.1").ConfigureAwait(false)) - { - return true; - } - - defaultServer = AccountManager.GetDefaultServerUrl(); - await HttpPing(defaultServer).ConfigureAwait(false); - return true; - } - catch (HttpRequestException ex) - { - using var activity = SpeckleActivityFactory.Start(); - activity?.SetTag("defaultServer", defaultServer); - SpeckleLog.Logger.Warning(ex, "Failed to ping internet"); - - return false; - } - } - - /// - /// Pings a specific url to verify it's accessible. Retries 3 times. - /// - /// The hostname or address to ping. - /// True if the the status code is 200, false otherwise. - public static async Task Ping(string hostnameOrAddress) - { - SpeckleLog.Logger.Information("Pinging {hostnameOrAddress}", hostnameOrAddress); - var policy = Policy - .Handle() - .Or() - .WaitAndRetryAsync( - DefaultDelay(), - (ex, timeSpan, retryAttempt, context) => { - //Log.Information( - // ex, - // "The http request failed with {exceptionType} exception retrying after {cooldown} milliseconds. This is retry attempt {retryAttempt}", - // ex.GetType().Name, - // timeSpan.TotalSeconds * 1000, - // retryAttempt - //); - } - ); - var policyResult = await policy - .ExecuteAndCaptureAsync(async () => - { - Ping myPing = new(); - var hostname = - Uri.CheckHostName(hostnameOrAddress) != UriHostNameType.Unknown - ? hostnameOrAddress - : new Uri(hostnameOrAddress).DnsSafeHost; - byte[] buffer = new byte[32]; - int timeout = 1000; - PingOptions pingOptions = new(); - PingReply reply = await myPing.SendPingAsync(hostname, timeout, buffer, pingOptions).ConfigureAwait(false); - if (reply.Status != IPStatus.Success) - { - throw new SpeckleException($"The ping operation failed with status {reply.Status}"); - } - - return true; - }) - .ConfigureAwait(false); - if (policyResult.Outcome == OutcomeType.Successful) - { - return true; - } - - SpeckleLog.Logger.Warning( - policyResult.FinalException, - "Failed to ping {hostnameOrAddress} cause: {exceptionMessage}", - policyResult.FinalException.Message - ); - return false; - } - /// /// Sends a GET request to the provided /// /// The URI that should be pinged /// Request to failed - public static async Task HttpPing(Uri uri) + public async Task HttpPing(Uri uri) { try { - using var httpClient = GetHttpProxyClient(); + using var httpClient = CreateHttpClient(); HttpResponseMessage response = await httpClient.GetAsync(uri).ConfigureAwait(false); response.EnsureSuccessStatusCode(); - SpeckleLog.Logger.Information("Successfully pinged {uri}", uri); + logger.LogInformation("Successfully pinged {uri}", uri); return response; } catch (HttpRequestException ex) { - SpeckleLog.Logger.Warning(ex, "Ping to {uri} was unsuccessful: {message}", uri, ex.Message); + logger.LogWarning(ex, "Ping to {uri} was unsuccessful: {message}", uri, ex.Message); throw new HttpRequestException($"Ping to {uri} was unsuccessful", ex); } } - public static HttpClient GetHttpProxyClient(SpeckleHttpClientHandler? speckleHttpClientHandler = null) + public const int DEFAULT_TIMEOUT_SECONDS = 60; + + public HttpClient CreateHttpClient( + HttpMessageHandler? innerHandler = null, + IAsyncPolicy? resiliencePolicy = null, + int timeoutSeconds = DEFAULT_TIMEOUT_SECONDS, + string? authorizationToken = null + ) { IWebProxy proxy = WebRequest.GetSystemWebProxy(); proxy.Credentials = CredentialCache.DefaultCredentials; - speckleHttpClientHandler ??= new SpeckleHttpClientHandler(new HttpClientHandler(), HttpAsyncPolicy()); + var speckleHandler = speckleHttpClientHandlerFactory.Create(innerHandler, resiliencePolicy, timeoutSeconds); - var client = new HttpClient(speckleHttpClientHandler) + var client = new HttpClient(speckleHandler) { Timeout = Timeout.InfiniteTimeSpan //timeout is configured on the SpeckleHttpClientHandler through policy }; + AddAuthHeader(client, authorizationToken); return client; } @@ -178,7 +68,7 @@ public static bool CanAddAuth(string? authToken, out string? bearerHeader) return false; } - public static void AddAuthHeader(HttpClient client, string? authToken) + private static void AddAuthHeader(HttpClient client, string? authToken) { if (CanAddAuth(authToken, out string? value)) { diff --git a/src/Speckle.Sdk/Helpers/SpeckleHttpClientHandler.cs b/src/Speckle.Sdk/Helpers/SpeckleHttpClientHandler.cs index 37a37a0f..998ad743 100644 --- a/src/Speckle.Sdk/Helpers/SpeckleHttpClientHandler.cs +++ b/src/Speckle.Sdk/Helpers/SpeckleHttpClientHandler.cs @@ -7,10 +7,16 @@ namespace Speckle.Sdk.Helpers; public sealed class SpeckleHttpClientHandler : DelegatingHandler { private readonly IAsyncPolicy _resiliencePolicy; + private readonly ISdkActivityFactory _activityFactory; - public SpeckleHttpClientHandler(HttpMessageHandler innerHandler, IAsyncPolicy resiliencePolicy) + public SpeckleHttpClientHandler( + HttpMessageHandler innerHandler, + ISdkActivityFactory activityFactory, + IAsyncPolicy resiliencePolicy + ) : base(innerHandler) { + _activityFactory = activityFactory; _resiliencePolicy = resiliencePolicy; } @@ -24,7 +30,7 @@ CancellationToken cancellationToken // this is a preliminary client server correlation implementation // refactor this, when we have a better observability stack var context = new Context(); - using var activity = SpeckleActivityFactory.Start("Http Request"); + using var activity = _activityFactory.Start("Http Request"); { activity?.SetTag("http.method", request.Method); activity?.SetTag("http.url", request.RequestUri); @@ -46,7 +52,7 @@ CancellationToken cancellationToken context.TryGetValue("retryCount", out var retryCount); activity?.SetTag("retryCount", retryCount); activity?.SetStatus( - policyResult.Result.IsSuccessStatusCode ? SpeckleActivityStatusCode.Ok : SpeckleActivityStatusCode.Error + policyResult.Result.IsSuccessStatusCode ? SdkActivityStatusCode.Ok : SdkActivityStatusCode.Error ); if (policyResult.FinalException != null) { diff --git a/src/Speckle.Sdk/Helpers/SpeckleHttpClientHandlerFactory.cs b/src/Speckle.Sdk/Helpers/SpeckleHttpClientHandlerFactory.cs new file mode 100644 index 00000000..f12bc354 --- /dev/null +++ b/src/Speckle.Sdk/Helpers/SpeckleHttpClientHandlerFactory.cs @@ -0,0 +1,51 @@ +using Polly; +using Polly.Contrib.WaitAndRetry; +using Polly.Extensions.Http; +using Polly.Timeout; +using Speckle.InterfaceGenerator; +using Speckle.Sdk.Logging; + +namespace Speckle.Sdk.Helpers; + +[GenerateAutoInterface] +public sealed class SpeckleHttpClientHandlerFactory(ISdkActivityFactory activityFactory) + : ISpeckleHttpClientHandlerFactory +{ + public IEnumerable DefaultDelay() + { + return Backoff.DecorrelatedJitterBackoffV2(TimeSpan.FromMilliseconds(200), 5); + } + + public IAsyncPolicy HttpAsyncPolicy( + IEnumerable? delay = null, + int timeoutSeconds = SpeckleHttp.DEFAULT_TIMEOUT_SECONDS + ) + { + var retryPolicy = HttpPolicyExtensions + .HandleTransientHttpError() + .Or() + .WaitAndRetryAsync( + delay ?? DefaultDelay(), + (ex, timeSpan, retryAttempt, context) => + { + context.Remove("retryCount"); + context.Add("retryCount", retryAttempt); + } + ); + + var timeoutPolicy = Policy.TimeoutAsync(timeoutSeconds); + + return Policy.WrapAsync(retryPolicy, timeoutPolicy); + } + + public SpeckleHttpClientHandler Create( + HttpMessageHandler? innerHandler = null, + IAsyncPolicy? resiliencePolicy = null, + int timeoutSeconds = SpeckleHttp.DEFAULT_TIMEOUT_SECONDS + ) => + new( + innerHandler ?? new HttpClientHandler(), + activityFactory, + resiliencePolicy ?? HttpAsyncPolicy(timeoutSeconds: timeoutSeconds) + ); +} diff --git a/src/Speckle.Sdk/Logging/Analytics.cs b/src/Speckle.Sdk/Logging/Analytics.cs deleted file mode 100644 index a8ead990..00000000 --- a/src/Speckle.Sdk/Logging/Analytics.cs +++ /dev/null @@ -1,344 +0,0 @@ -#nullable disable -using System.Diagnostics; -using System.Net.Http.Headers; -using System.Net.NetworkInformation; -using System.Reflection; -using System.Runtime.InteropServices; -using System.Text; -using System.Web; -using Speckle.Newtonsoft.Json; -using Speckle.Sdk.Credentials; -using Speckle.Sdk.Helpers; - -namespace Speckle.Sdk.Logging; - -/// -/// Anonymous telemetry to help us understand how to make a better Speckle. -/// This really helps us to deliver a better open source project and product! -/// -public static class Analytics -{ - /// - /// Default Mixpanel events - /// - public enum Events - { - /// - /// Event triggered when data is sent to a Speckle Server - /// - Send, - - /// - /// Event triggered when data is received from a Speckle Server - /// - Receive, - - /// - /// Event triggered when a node is executed in a visual programming environment, it should contain the name of the action and the host application - /// - NodeRun, - - /// - /// Event triggered when an action is executed in Desktop UI, it should contain the name of the action and the host application - /// - DUIAction, - - /// - /// Event triggered when a node is first created in a visual programming environment, it should contain the name of the action and the host application - /// - NodeCreate, - - /// - /// Event triggered when the import/export alert is launched or closed - /// - ImportExportAlert, - - /// - /// Event triggered when the connector is registered - /// - Registered, - - /// - /// Event triggered by the Mapping Tool - /// - MappingsAction, - - /// - /// Event triggered when user selects object to convert to Speckle on Send - /// - ConvertToSpeckle, - - /// - /// Event triggered when user selects object to convert to Native on Receive - /// - ConvertToNative - } - - private const string MIXPANEL_TOKEN = "acd87c5a50b56df91a795e999812a3a4"; - private static readonly Uri s_mixpanelServer = new("https://analytics.speckle.systems"); - - /// - /// Cached email - /// - private static string LastEmail { get; set; } - - /// - /// Cached server URL - /// - private static string LastServer { get; set; } - - /// - /// when the DEBUG pre-processor directive is , otherwise - /// - /// This must be kept as a computed property, not a compile time const - internal static bool IsReleaseMode => -#if DEBUG - false; -#else - true; -#endif - - /// - /// Tracks an event without specifying the email and server. - /// It's not always possible to know which account the user has selected, especially in visual programming. - /// Therefore we are caching the email and server values so that they can be used also when nodes such as "Serialize" are used. - /// If no account info is cached, we use the default account data. - /// - /// Name of the even - /// Additional parameters to pass in to event - /// True if it's an action performed by a logged user - public static void TrackEvent( - Events eventName, - Dictionary customProperties = null, - bool isAction = true - ) - { - string email; - string server; - - if (LastEmail != null && LastServer != null && LastServer != "no-account-server") - { - email = LastEmail; - server = LastServer; - } - else - { - var acc = AccountManager.GetDefaultAccount(); - if (acc == null) - { - var macAddr = NetworkInterface - .GetAllNetworkInterfaces() - .Where(nic => - nic.OperationalStatus == OperationalStatus.Up && nic.NetworkInterfaceType != NetworkInterfaceType.Loopback - ) - .Select(nic => nic.GetPhysicalAddress().ToString()) - .FirstOrDefault(); - - email = macAddr; - server = "no-account-server"; - isAction = false; - } - else - { - email = acc.GetHashedEmail(); - server = acc.GetHashedServer(); - } - } - - TrackEvent(email, server, eventName, customProperties, isAction); - } - - /// - /// Tracks an event from a specified account, anonymizes personal information - /// - /// Account to use, it will be anonymized - /// Name of the event - /// Additional parameters to pass to the event - /// True if it's an action performed by a logged user - public static void TrackEvent( - Account account, - Events eventName, - Dictionary customProperties = null, - bool isAction = true - ) - { - if (account == null) - { - TrackEvent(eventName, customProperties, isAction); - } - else - { - TrackEvent(account.GetHashedEmail(), account.GetHashedServer(), eventName, customProperties, isAction); - } - } - - /// - /// Tracks an event from a specified email and server, anonymizes personal information - /// - /// Email of the user anonymized - /// Server URL anonymized - /// Name of the event - /// Additional parameters to pass to the event - /// True if it's an action performed by a logged user - private static void TrackEvent( - string hashedEmail, - string hashedServer, - Events eventName, - Dictionary customProperties = null, - bool isAction = true - ) - { - LastEmail = hashedEmail; - LastServer = hashedServer; - - if (!IsReleaseMode) - { - //only track in prod - return; - } - - Task.Run(async () => - { - using var activity = SpeckleActivityFactory.Start(); - activity?.SetTag("isAction", isAction); - activity?.SetTag("eventName", eventName.ToString()); - try - { - var executingAssembly = Assembly.GetExecutingAssembly(); - var properties = new Dictionary - { - { "distinct_id", hashedEmail }, - { "server_id", hashedServer }, - { "token", MIXPANEL_TOKEN }, - { "hostApp", Setup.Application }, - { "hostAppVersion", Setup.Version }, - { - "core_version", - FileVersionInfo.GetVersionInfo(executingAssembly.Location).ProductVersion - ?? executingAssembly.GetName().Version.ToString() - }, - { "$os", GetOs() } - }; - - if (isAction) - { - properties.Add("type", "action"); - } - - if (customProperties != null) - { - foreach (KeyValuePair customProp in customProperties) - { - properties[customProp.Key] = customProp.Value; - } - } - - string json = JsonConvert.SerializeObject(new { @event = eventName.ToString(), properties }); - - var query = new StreamContent(new MemoryStream(Encoding.UTF8.GetBytes("data=" + HttpUtility.UrlEncode(json)))); - - using HttpClient client = new(); - client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("text/plain")); - query.Headers.ContentType = new MediaTypeHeaderValue("application/json"); - var res = await client.PostAsync(new Uri(s_mixpanelServer, "/track?ip=1"), query).ConfigureAwait(false); - res.EnsureSuccessStatusCode(); - } - catch (Exception ex) when (!ex.IsFatal()) - { - SpeckleLog.Logger.Warning(ex, "Analytics event failed {exceptionMessage}", ex.Message); - } - }); - } - - internal static void AddConnectorToProfile(string hashedEmail, string connector) - { - Task.Run(async () => - { - try - { - var data = new Dictionary - { - { "$token", MIXPANEL_TOKEN }, - { "$distinct_id", hashedEmail }, - { - "$union", - new Dictionary - { - { - "Connectors", - new List { connector } - } - } - } - }; - string json = JsonConvert.SerializeObject(data); - - var query = new StreamContent(new MemoryStream(Encoding.UTF8.GetBytes("data=" + HttpUtility.UrlEncode(json)))); - using HttpClient client = Http.GetHttpProxyClient(); - client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("text/plain")); - query.Headers.ContentType = new MediaTypeHeaderValue("application/json"); - var res = await client - .PostAsync(new Uri(s_mixpanelServer, "/engage#profile-union"), query) - .ConfigureAwait(false); - res.EnsureSuccessStatusCode(); - } - catch (Exception ex) when (!ex.IsFatal()) - { - //.ForContext("connector", connector) - SpeckleLog.Logger.Warning(ex, "Failed add connector to profile"); - } - }); - } - - internal static void IdentifyProfile(string hashedEmail) - { - Task.Run(async () => - { - try - { - var data = new Dictionary - { - { "$token", MIXPANEL_TOKEN }, - { "$distinct_id", hashedEmail }, - { - "$set", - new Dictionary { { "Identified", true } } - } - }; - string json = JsonConvert.SerializeObject(data); - - var query = new StreamContent(new MemoryStream(Encoding.UTF8.GetBytes("data=" + HttpUtility.UrlEncode(json)))); - using HttpClient client = Http.GetHttpProxyClient(); - client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("text/plain")); - query.Headers.ContentType = new MediaTypeHeaderValue("application/json"); - var res = await client.PostAsync(new Uri(s_mixpanelServer, "/engage#profile-set"), query).ConfigureAwait(false); - res.EnsureSuccessStatusCode(); - } - catch (Exception ex) when (!ex.IsFatal()) - { - //.ForContext("connector", connector) - SpeckleLog.Logger.Warning(ex, "Failed identify profile"); - } - }); - } - - private static string GetOs() - { - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - return "Windows"; - } - - if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) - { - return "Mac OS X"; - } - - if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) - { - return "Linux"; - } - - return "Unknown"; - } -} diff --git a/src/Speckle.Sdk.Logging/ISpeckleActivity.cs b/src/Speckle.Sdk/Logging/ISdkActivity.cs similarity index 78% rename from src/Speckle.Sdk.Logging/ISpeckleActivity.cs rename to src/Speckle.Sdk/Logging/ISdkActivity.cs index 3ce6004a..c7cccaa3 100644 --- a/src/Speckle.Sdk.Logging/ISpeckleActivity.cs +++ b/src/Speckle.Sdk/Logging/ISdkActivity.cs @@ -1,14 +1,14 @@ namespace Speckle.Sdk.Logging; -public interface ISpeckleActivity : IDisposable +public interface ISdkActivity : IDisposable { void SetTag(string key, object? value); void RecordException(Exception e); string TraceId { get; } - void SetStatus(SpeckleActivityStatusCode code); + void SetStatus(SdkActivityStatusCode code); } -public enum SpeckleActivityStatusCode +public enum SdkActivityStatusCode { /// Unset status code is the default value indicating the status code is not initialized. Unset, diff --git a/src/Speckle.Sdk/Logging/ISdkActivityFactory.cs b/src/Speckle.Sdk/Logging/ISdkActivityFactory.cs new file mode 100644 index 00000000..62d336f8 --- /dev/null +++ b/src/Speckle.Sdk/Logging/ISdkActivityFactory.cs @@ -0,0 +1,13 @@ +namespace Speckle.Sdk.Logging; + +public interface ISdkActivityFactory : IDisposable +{ + Speckle.Sdk.Logging.ISdkActivity? Start(string? name = default, string source = ""); +} + +public sealed class NullActivityFactory : ISdkActivityFactory +{ + public void Dispose() { } + + public ISdkActivity? Start(string? name = default, string source = "") => null; +} diff --git a/src/Speckle.Sdk.Logging/Path.cs b/src/Speckle.Sdk/Logging/SpecklePathProvider.cs similarity index 53% rename from src/Speckle.Sdk.Logging/Path.cs rename to src/Speckle.Sdk/Logging/SpecklePathProvider.cs index 66bb85b4..8e214a58 100644 --- a/src/Speckle.Sdk.Logging/Path.cs +++ b/src/Speckle.Sdk/Logging/SpecklePathProvider.cs @@ -5,19 +5,13 @@ namespace Speckle.Sdk.Logging; /// /// Helper class dedicated for Speckle specific Path operations. /// -public static class SpecklePathProvider +internal static class SpecklePathProvider { - private static string s_applicationName = "Speckle"; + private const string APPLICATION_NAME = "Speckle"; - private static string s_blobFolderName = "Blobs"; + private const string BLOB_FOLDER_NAME = "Blobs"; - private static string s_kitsFolderName = "Kits"; - - private static string s_accountsFolderName = "Accounts"; - - private static string s_objectsFolderName = "Objects"; - - private const string LOG_FOLDER_NAME = "Logs"; + private const string ACCOUNTS_FOLDER_NAME = "Accounts"; private static string UserDataPathEnvVar => "SPECKLE_USERDATA_PATH"; private static string? Path => Environment.GetEnvironmentVariable(UserDataPathEnvVar); @@ -30,83 +24,19 @@ public static class SpecklePathProvider ? Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) : UserApplicationDataPath(); - /// - /// Get the path where the Speckle applications should be installed - /// - public static string InstallSpeckleFolderPath => EnsureFolderExists(InstallApplicationDataPath, s_applicationName); - /// /// Get the folder where the user's Speckle data should be stored. /// - public static string UserSpeckleFolderPath => EnsureFolderExists(UserApplicationDataPath(), s_applicationName); - - /// - /// Get the folder where the Speckle kits should be stored. - /// - public static string KitsFolderPath => EnsureFolderExists(InstallSpeckleFolderPath, s_kitsFolderName); - - /// - /// - /// - public static string ObjectsFolderPath => EnsureFolderExists(KitsFolderPath, s_objectsFolderName); + public static string UserSpeckleFolderPath => EnsureFolderExists(UserApplicationDataPath(), APPLICATION_NAME); /// /// Get the folder where the Speckle accounts data should be stored. /// - public static string AccountsFolderPath => EnsureFolderExists(UserSpeckleFolderPath, s_accountsFolderName); - - /// - /// Override the global Speckle application name. - /// - /// - public static void OverrideApplicationName(string applicationName) - { - s_applicationName = applicationName; - } - - /// - /// Override the global Speckle application data path. - /// - public static void OverrideApplicationDataPath(string? path) - { - Environment.SetEnvironmentVariable(UserDataPathEnvVar, path); - } - - /// - /// Override the global Blob storage folder name. - /// - public static void OverrideBlobStorageFolder(string blobFolderName) - { - s_blobFolderName = blobFolderName; - } - - /// - /// Override the global Kits folder name. - /// - public static void OverrideKitsFolderName(string kitsFolderName) - { - s_kitsFolderName = kitsFolderName; - } - - /// - /// Override the global Accounts folder name. - /// - public static void OverrideAccountsFolderName(string accountsFolderName) - { - s_accountsFolderName = accountsFolderName; - } - - /// - /// - /// - public static void OverrideObjectsFolderName(string objectsFolderName) - { - s_objectsFolderName = objectsFolderName; - } + public static string AccountsFolderPath => EnsureFolderExists(UserSpeckleFolderPath, ACCOUNTS_FOLDER_NAME); /// /// Get the platform specific user configuration folder path.
- /// Unless overriden (see ) will be the path e.g.: + /// will be the path e.g.: /// In cases such as linux servers where the above path is not permissive, we will fall back to ///
/// @@ -144,7 +74,8 @@ public static string UserApplicationDataPath() catch (SystemException ex) when (ex is PlatformNotSupportedException or ArgumentException) { //Adding this log just so we confidently know which Exception type to catch here. - SpeckleLog.Logger.Warning(ex, "Falling back to user profile path"); + // TODO: Must re-add log call when (and if) this get's made as a service + //SpeckleLog.Logger.Warning(ex, "Falling back to user profile path"); // on server linux, there might not be a user setup, things can run under root // in that case, the appdata variable is most probably not set up @@ -156,10 +87,8 @@ public static string UserApplicationDataPath() /// /// Get the folder where the user's Speckle blobs should be stored. /// - public static string BlobStoragePath(string? path = null) - { - return EnsureFolderExists(path ?? UserSpeckleFolderPath, s_blobFolderName); - } + public static string BlobStoragePath(string? path = null) => + EnsureFolderExists(path ?? UserSpeckleFolderPath, BLOB_FOLDER_NAME); private static string EnsureFolderExists(params string[] folderName) { @@ -167,7 +96,4 @@ private static string EnsureFolderExists(params string[] folderName) Directory.CreateDirectory(path); return path; } - - internal static string LogFolderPath(string applicationAndVersion) => - EnsureFolderExists(UserSpeckleFolderPath, LOG_FOLDER_NAME, applicationAndVersion); } diff --git a/src/Speckle.Sdk/Models/Base.cs b/src/Speckle.Sdk/Models/Base.cs index 34777f8f..b6856b7d 100644 --- a/src/Speckle.Sdk/Models/Base.cs +++ b/src/Speckle.Sdk/Models/Base.cs @@ -8,7 +8,6 @@ using Speckle.Sdk.Common; using Speckle.Sdk.Helpers; using Speckle.Sdk.Host; -using Speckle.Sdk.Logging; using Speckle.Sdk.Serialisation; using Speckle.Sdk.Transports; @@ -235,24 +234,7 @@ var kvp in GetMembers( { continue; } - - try - { - myDuplicate[kvp.Key] = kvp.Value; - } - catch (Exception ex) when (!ex.IsFatal()) - { - // avoids any last ditch unsettable or strange props. - SpeckleLog.Logger.Warning( - "Shallow copy of {type} failed to copy {propertyName} of type {propertyType} with value {valueType} - CanWrite / CanRead", - type, - kvp.Key, - propertyInfo?.PropertyType, - kvp.Value?.GetType(), - propertyInfo?.CanWrite, - propertyInfo?.CanRead - ); - } + myDuplicate[kvp.Key] = kvp.Value; } return myDuplicate; diff --git a/src/Speckle.Sdk/Models/CommitObjectBuilder.cs b/src/Speckle.Sdk/Models/CommitObjectBuilder.cs deleted file mode 100644 index df6f64af..00000000 --- a/src/Speckle.Sdk/Models/CommitObjectBuilder.cs +++ /dev/null @@ -1,170 +0,0 @@ -using System.Collections; -using Speckle.Sdk.Logging; -using Speckle.Sdk.Models.Collections; -using Speckle.Sdk.Models.Extensions; - -namespace Speckle.Sdk.Models; - -/// -/// Abstract Builder class for a root commit object. -/// -/// The native object data type needed as input for building -/// -/// It is designed to be inherited by a host app specific implementation, -/// to give connectors flexibility in constructing their objects. -/// Inheritors should also create some function to add -/// -public abstract class CommitObjectBuilder -{ - /// Special appId symbol for the root object - protected const string ROOT = "__Root"; - private const string ELEMENTS = nameof(Collection.elements); - - /// app id -> base - protected IDictionary Converted { get; } - - /// Base -> NestingInstructions ordered by priority - private readonly Dictionary> _nestingInstructions = new(); - - protected CommitObjectBuilder() - { - Converted = new Dictionary(); - } - - /// - /// Given the parameters, builds connector specific - /// to be applied when is called. - /// - /// - /// - public abstract void IncludeObject(Base conversionResult, TNativeObjectData nativeElement); - - /// - /// Iterates through the converted objects applying - /// - /// - /// Can be overriden to adjust exactly which objects get automatically applied, - /// or to inject additional items into the dict that should not be automatically applied. - /// - /// - public virtual void BuildCommitObject(Base rootCommitObject) - { - ApplyRelationships(Converted.Values, rootCommitObject); - } - - protected void SetRelationship(Base conversionResult, NestingInstructions nestingInstructions) - { - SetRelationship(conversionResult, new List { nestingInstructions }); - } - - /// - /// Sets information on how a given object should be nested in the commit tree. - /// encodes the order in which we should try and nest the given - /// when is called - /// - /// The object to be nested - /// Information about how the object ideally should be nested, in order of priority - protected void SetRelationship(Base conversionResult, IList nestingInstructionsList) - { - string? appId = conversionResult.applicationId; - if (appId != null) - { - Converted[appId] = conversionResult; - } - _nestingInstructions[conversionResult] = nestingInstructionsList; - } - - /// - /// For each object in - /// - /// - /// - /// - protected void ApplyRelationships(IEnumerable toAdd, Base rootCommitObject) - { - foreach (Base c in toAdd) - { - try - { - ApplyRelationship(c, rootCommitObject); - } - catch (Exception ex) when (!ex.IsFatal()) - { - // This should never happen, we should be ensuring that at least one of the parents is valid. - SpeckleLog.Logger.Fatal(ex, "Failed to add object {speckleType} to commit object", c?.GetType()); - } - } - } - - /// - /// Will attempt to find and nest the object - /// under the first valid parent according to the dictionary. - /// - /// - /// A parent is considered valid if - /// 1. Is non null - /// 2. Is in the dictionary - /// 3. Has (or can dynamically accept) a typed property with the propName specified by the item - /// 4. Said can accept the object's type - /// - /// - /// - /// Thrown when no valid parent was found for given - protected void ApplyRelationship(Base current, Base rootCommitObject) - { - var instructions = _nestingInstructions[current]; - foreach (var instruction in instructions) - { - if (instruction.ParentApplicationId is null) - { - continue; - } - - Base? parent; - if (instruction.ParentApplicationId == ROOT) - { - parent = rootCommitObject; - } - else - { - Converted.TryGetValue(instruction.ParentApplicationId, out parent); - } - - if (parent is null) - { - continue; - } - - try - { - instruction.Nest(parent, current); - return; - } - catch (Exception ex) when (!ex.IsFatal()) - { - // A parent was found, but it was invalid (Likely because of a type mismatch on a `elements` property) - SpeckleLog.Logger.Warning(ex, "Failed to add object {speckleType} to a converted parent", current.GetType()); - } - } - - throw new InvalidOperationException( - $"Could not find a valid parent for object of type {current.GetType()}. Checked {instructions.Count} potential parent, and non were converted!" - ); - } - - protected static void NestUnderElementsProperty(Base parent, Base child) - { - NestUnderProperty(parent, child, ELEMENTS); - } - - protected static void NestUnderProperty(Base parent, Base child, string property) - { - if (parent.GetDetachedProp(property) is not IList elements) - { - elements = new List(); - parent.SetDetachedProp(property, elements); - } - - elements.Add(child); - } -} diff --git a/src/Speckle.Sdk/Models/DynamicBase.cs b/src/Speckle.Sdk/Models/DynamicBase.cs index 40da7664..ddb81167 100644 --- a/src/Speckle.Sdk/Models/DynamicBase.cs +++ b/src/Speckle.Sdk/Models/DynamicBase.cs @@ -3,7 +3,6 @@ using Speckle.Newtonsoft.Json; using Speckle.Sdk.Common; using Speckle.Sdk.Host; -using Speckle.Sdk.Logging; namespace Speckle.Sdk.Models; @@ -74,6 +73,7 @@ public object? this[string key] _properties[key] = value; return; } + try { prop.SetValue(this, value); @@ -254,15 +254,7 @@ public static IEnumerable GetInstanceMembers(Type t) .ForEach(e => { var attr = e.GetCustomAttribute().NotNull(); - try - { - dic[attr.Name] = e.Invoke(this, null); - } - catch (Exception ex) when (!ex.IsFatal()) - { - SpeckleLog.Logger.Warning(ex, "Failed to get computed member: {name}", attr.Name); - dic[attr.Name] = null; - } + dic[attr.Name] = e.Invoke(this, null); }); } diff --git a/src/Speckle.Sdk/ScrutorFunctions.cs b/src/Speckle.Sdk/ScrutorFunctions.cs new file mode 100644 index 00000000..93457b30 --- /dev/null +++ b/src/Speckle.Sdk/ScrutorFunctions.cs @@ -0,0 +1,113 @@ +using System.Runtime.CompilerServices; + +namespace Speckle.Sdk; + +/// +/// This is from the Scrutor project (https://github.com/khellang/Scrutor) but we don't want to pull in the dependencies +/// +public static class ScrutorFunctions +{ + public static bool IsNonAbstractClass(this Type type) + { + if (type.IsSpecialName) + { + return false; + } + + if (type.IsClass && !type.IsAbstract) + { + if (type.HasAttribute()) + { + return false; + } + + return type.IsPublic || type.IsNestedPublic; + } + + return false; + } + + public static bool HasAttribute(this Type type) + where T : Attribute + { + return type.HasAttribute(typeof(T)); + } + + public static bool HasAttribute(this Type type, Type attributeType) + { + return type.IsDefined(attributeType, inherit: true); + } + + public static IEnumerable FindMatchingInterface(this Type type) + { + var matchingInterfaceName = $"I{type.Name}"; + + var matchedInterfaces = GetImplementedInterfacesToMap(type) + .Where(x => string.Equals(x.Name, matchingInterfaceName, StringComparison.Ordinal)) + .ToArray(); + + if (matchedInterfaces.Length == 0) + { + yield break; + } + + Type? matchingType = matchedInterfaces.FirstOrDefault(); + + if (matchingType is null) + { + yield break; + } + + yield return matchingType; + } + + private static IEnumerable GetImplementedInterfacesToMap(Type type) + { + if (!type.IsGenericType) + { + return type.GetInterfaces(); + } + + if (!type.IsGenericTypeDefinition) + { + return type.GetInterfaces(); + } + + return FilterMatchingGenericInterfaces(type); + } + + private static IEnumerable FilterMatchingGenericInterfaces(Type type) + { + var genericArguments = type.GetGenericArguments(); + + foreach (var current in type.GetInterfaces()) + { + if ( + current.IsGenericType + && current.ContainsGenericParameters + && GenericParametersMatch(genericArguments, current.GetGenericArguments()) + ) + { + yield return current.GetGenericTypeDefinition(); + } + } + } + + private static bool GenericParametersMatch(IReadOnlyList parameters, IReadOnlyList interfaceArguments) + { + if (parameters.Count != interfaceArguments.Count) + { + return false; + } + + for (var i = 0; i < parameters.Count; i++) + { + if (parameters[i] != interfaceArguments[i]) + { + return false; + } + } + + return true; + } +} diff --git a/src/Speckle.Sdk/Serialisation/SpeckleObjectDeserializer.cs b/src/Speckle.Sdk/Serialisation/SpeckleObjectDeserializer.cs index f9febbee..84b99404 100644 --- a/src/Speckle.Sdk/Serialisation/SpeckleObjectDeserializer.cs +++ b/src/Speckle.Sdk/Serialisation/SpeckleObjectDeserializer.cs @@ -45,7 +45,7 @@ public sealed class SpeckleObjectDeserializer /// was null /// cannot be deserialised to type // /// did not contain the required json objects (closures) - public async Task DeserializeJsonAsync(string rootObjectJson) + public async Task DeserializeAsync(string rootObjectJson) { if (_isBusy) { diff --git a/src/Speckle.Sdk/Serialisation/SpeckleObjectSerializer.cs b/src/Speckle.Sdk/Serialisation/SpeckleObjectSerializer.cs index d544c572..c3f04549 100644 --- a/src/Speckle.Sdk/Serialisation/SpeckleObjectSerializer.cs +++ b/src/Speckle.Sdk/Serialisation/SpeckleObjectSerializer.cs @@ -8,7 +8,6 @@ using Speckle.Newtonsoft.Json; using Speckle.Sdk.Common; using Speckle.Sdk.Helpers; -using Speckle.Sdk.Logging; using Speckle.Sdk.Models; using Speckle.Sdk.Transports; using Constants = Speckle.Sdk.Helpers.Constants; @@ -225,32 +224,10 @@ private void SerializeProperty( writer.WriteEndArray(); break; //BACKWARDS COMPATIBILITY: matrix4x4 changed from System.Numerics float to System.DoubleNumerics double in release 2.16 - case System.Numerics.Matrix4x4 ms: - SpeckleLog.Logger.Warning( - "This kept for backwards compatibility, no one should be using {this}", - "BaseObjectSerializerV2 serialize System.Numerics.Matrix4x4" - ); - writer.WriteStartArray(); - writer.WriteValue((double)ms.M11); - writer.WriteValue((double)ms.M12); - writer.WriteValue((double)ms.M13); - writer.WriteValue((double)ms.M14); - writer.WriteValue((double)ms.M21); - writer.WriteValue((double)ms.M22); - writer.WriteValue((double)ms.M23); - writer.WriteValue((double)ms.M24); - writer.WriteValue((double)ms.M31); - writer.WriteValue((double)ms.M32); - writer.WriteValue((double)ms.M33); - writer.WriteValue((double)ms.M34); - writer.WriteValue((double)ms.M41); - writer.WriteValue((double)ms.M42); - writer.WriteValue((double)ms.M43); - writer.WriteValue((double)ms.M44); - writer.WriteEndArray(); - break; + case System.Numerics.Matrix4x4: + throw new ArgumentException("Please use Speckle.DoubleNumerics.Matrix4x4 instead", nameof(obj)); default: - throw new ArgumentException($"Unsupported value in serialization: {obj.GetType()}"); + throw new ArgumentException($"Unsupported value in serialization: {obj.GetType()}", nameof(obj)); } } diff --git a/src/Speckle.Sdk/Serialisation/Utilities/ValueConverter.cs b/src/Speckle.Sdk/Serialisation/Utilities/ValueConverter.cs index 4c522d5c..aca99be6 100644 --- a/src/Speckle.Sdk/Serialisation/Utilities/ValueConverter.cs +++ b/src/Speckle.Sdk/Serialisation/Utilities/ValueConverter.cs @@ -5,7 +5,6 @@ using System.Globalization; using Speckle.DoubleNumerics; using Speckle.Sdk.Common; -using Speckle.Sdk.Logging; namespace Speckle.Sdk.Serialisation.Utilities; @@ -267,33 +266,9 @@ public static bool ConvertValue(Type type, object? value, out object? convertedV } #region BACKWARDS COMPATIBILITY: matrix4x4 changed from System.Numerics float to System.DoubleNumerics double in release 2.16 - if (type == typeof(System.Numerics.Matrix4x4) && value is IReadOnlyList lMatrix) + if (type == typeof(System.Numerics.Matrix4x4) && value is IReadOnlyList) { - SpeckleLog.Logger.Warning( - "This kept for backwards compatibility, no one should be using {this}", - "ValueConverter deserialize to System.Numerics.Matrix4x4" - ); - convertedValue = new System.Numerics.Matrix4x4( - I(0), - I(1), - I(2), - I(3), - I(4), - I(5), - I(6), - I(7), - I(8), - I(9), - I(10), - I(11), - I(12), - I(13), - I(14), - I(15) - ); - return true; - - float I(int index) => Convert.ToSingle(lMatrix[index]); + throw new ArgumentException("Only Speckle.DoubleNumerics.Matrix4x4 is supported.", nameof(type)); } #endregion diff --git a/src/Speckle.Sdk/ServiceRegistration.cs b/src/Speckle.Sdk/ServiceRegistration.cs new file mode 100644 index 00000000..5a134d22 --- /dev/null +++ b/src/Speckle.Sdk/ServiceRegistration.cs @@ -0,0 +1,59 @@ +using System.Reflection; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; +using Speckle.InterfaceGenerator; +using Speckle.Sdk.Host; +using Speckle.Sdk.Logging; + +namespace Speckle.Sdk; + +[GenerateAutoInterface] +public class SpeckleApplication : ISpeckleApplication +{ + public string Application { get; init; } + public string Version { get; init; } + public string Slug { get; init; } + + public string ApplicationVersion => $"{Application} {Version}"; +} + +public static class ServiceRegistration +{ + public static IServiceCollection AddSpeckleSdk( + this IServiceCollection serviceCollection, + HostApplication application, + HostAppVersion version + ) + { + serviceCollection.AddLogging(); + string name = application.Name; + + serviceCollection.AddSingleton( + new SpeckleApplication + { + Application = name, + Version = HostApplications.GetVersion(version), + Slug = application.Slug + } + ); + serviceCollection.AddSingleton(); + serviceCollection.AddMatchingInterfacesAsTransient(Assembly.GetExecutingAssembly()); + return serviceCollection; + } + + public static IServiceCollection AddMatchingInterfacesAsTransient( + this IServiceCollection serviceCollection, + Assembly assembly + ) + { + foreach (var type in assembly.ExportedTypes.Where(t => t.IsNonAbstractClass())) + { + foreach (var matchingInterface in type.FindMatchingInterface()) + { + serviceCollection.TryAddTransient(matchingInterface, type); + } + } + + return serviceCollection; + } +} diff --git a/src/Speckle.Sdk/Setup.cs b/src/Speckle.Sdk/Setup.cs deleted file mode 100644 index 8623f30f..00000000 --- a/src/Speckle.Sdk/Setup.cs +++ /dev/null @@ -1,93 +0,0 @@ -using System.Diagnostics; -using Speckle.Sdk.Credentials; -using Speckle.Sdk.Helpers; -using Speckle.Sdk.Host; -using Speckle.Sdk.Logging; - -namespace Speckle.Sdk; - -/// -/// Anonymous telemetry to help us understand how to make a better Speckle. -/// This really helps us to deliver a better open source project and product! -/// -public static class Setup -{ - public static Mutex Mutex { get; set; } - - private static bool s_initialized; - - static Setup() - { - //Set fallback values - try - { - Application = Process.GetCurrentProcess().ProcessName; - } - catch (InvalidOperationException) - { - Application = "other (.NET)"; - } - } - - /// - /// Set from the connectors, defines which current host application we're running on. - /// - internal static string Application { get; private set; } - internal static string Version { get; private set; } - internal static string ApplicationVersion => $"{Application} {Version}"; - - /// - /// Set from the connectors, defines which current host application we're running on - includes the version. - /// - internal static string Slug { get; private set; } = HostApplications.Other.Slug; - - public static IDisposable? Initialize(SpeckleConfiguration configuration) - { - if (s_initialized) - { - SpeckleLog.Logger.Information("Setup was already initialized with {currentHostApp}", configuration.Application); - throw new InvalidOperationException(); - } - - s_initialized = true; - Application = configuration.Application.Name; - Version = HostApplications.GetVersion(configuration.Version); - Slug = configuration.Application.Slug; - - //start mutex so that Manager can detect if this process is running - Mutex = new Mutex(false, "SpeckleConnector-" + configuration.Application); - - foreach (var account in AccountManager.GetAccounts()) - { - Analytics.AddConnectorToProfile(account.GetHashedEmail(), Application); - Analytics.IdentifyProfile(account.GetHashedEmail()); - } - return LogBuilder.Initialize( - GetUserIdFromDefaultAccount(), - ApplicationVersion, - Slug, - configuration.Logging, - configuration.Tracing - ); - } - - private static string GetUserIdFromDefaultAccount() - { - var machineName = Environment.MachineName; - var userName = Environment.UserName; - var id = Crypt.Md5($"{machineName}:{userName}", "X2"); - try - { - var defaultAccount = AccountManager.GetDefaultAccount(); - if (defaultAccount != null) - { - id = defaultAccount.GetHashedEmail(); - } - } - catch (Exception ex) when (!ex.IsFatal()) - { - // To log it after Logger initialized as deferred action. - } - return id; - } -} diff --git a/src/Speckle.Sdk/Speckle.Sdk.csproj b/src/Speckle.Sdk/Speckle.Sdk.csproj index 8ef46c04..0d65715a 100644 --- a/src/Speckle.Sdk/Speckle.Sdk.csproj +++ b/src/Speckle.Sdk/Speckle.Sdk.csproj @@ -37,8 +37,13 @@ - - + + + + + + + diff --git a/src/Speckle.Sdk/SpeckleConfiguration.cs b/src/Speckle.Sdk/SpeckleConfiguration.cs deleted file mode 100644 index 2b711a05..00000000 --- a/src/Speckle.Sdk/SpeckleConfiguration.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Speckle.Sdk.Host; -using Speckle.Sdk.Logging; - -namespace Speckle.Sdk; - -public record SpeckleConfiguration( - HostApplication Application, - HostAppVersion Version, - SpeckleLogging? Logging = null, - SpeckleTracing? Tracing = null -); diff --git a/src/Speckle.Sdk/Transports/MemoryTransport.cs b/src/Speckle.Sdk/Transports/MemoryTransport.cs index d9bede8a..f3825c7a 100644 --- a/src/Speckle.Sdk/Transports/MemoryTransport.cs +++ b/src/Speckle.Sdk/Transports/MemoryTransport.cs @@ -27,7 +27,6 @@ public MemoryTransport( _blobStorageEnabled = blobStorageEnabled; _basePath = basePath ?? SpecklePathProvider.UserApplicationDataPath(); _applicationName = applicationName ?? "Speckle"; - SpeckleLog.Logger.Debug("Creating a new Memory Transport"); var dir = Path.Combine(_basePath, _applicationName); try { diff --git a/src/Speckle.Sdk/Transports/ServerTransport.cs b/src/Speckle.Sdk/Transports/ServerTransport.cs index 517e8bad..47045f1f 100644 --- a/src/Speckle.Sdk/Transports/ServerTransport.cs +++ b/src/Speckle.Sdk/Transports/ServerTransport.cs @@ -1,6 +1,7 @@ using System.Diagnostics; using Speckle.Sdk.Common; using Speckle.Sdk.Credentials; +using Speckle.Sdk.Helpers; using Speckle.Sdk.Logging; using Speckle.Sdk.Models; using Speckle.Sdk.Serialisation.Utilities; @@ -10,6 +11,8 @@ namespace Speckle.Sdk.Transports; public sealed class ServerTransport : IServerTransport { + private readonly ISpeckleHttp _http; + private readonly ISdkActivityFactory _activityFactory; private readonly object _elapsedLock = new(); private Exception? _exception; @@ -28,20 +31,30 @@ public sealed class ServerTransport : IServerTransport /// /// Defaults to /// was not formatted as valid stream id - public ServerTransport(Account account, string streamId, int timeoutSeconds = 60, string? blobStorageFolder = null) + public ServerTransport( + ISpeckleHttp http, + ISdkActivityFactory activityFactory, + Account account, + string streamId, + int timeoutSeconds = 60, + string? blobStorageFolder = null + ) { if (string.IsNullOrWhiteSpace(streamId)) { throw new ArgumentException($"{streamId} is not a valid id", streamId); } + _http = http; + _activityFactory = activityFactory; + Account = account; BaseUri = new(account.serverInfo.url); StreamId = streamId; AuthorizationToken = account.token; TimeoutSeconds = timeoutSeconds; BlobStorageFolder = blobStorageFolder ?? SpecklePathProvider.BlobStoragePath(); - Initialize(account.serverInfo.url); + Api = new ParallelServerApi(http, activityFactory, BaseUri, AuthorizationToken, BlobStorageFolder, TimeoutSeconds); Directory.CreateDirectory(BlobStorageFolder); } @@ -74,7 +87,7 @@ public void SaveBlob(Blob obj) public object Clone() { - return new ServerTransport(Account, StreamId, TimeoutSeconds, BlobStorageFolder) + return new ServerTransport(_http, _activityFactory, Account, StreamId, TimeoutSeconds, BlobStorageFolder) { OnProgressAction = OnProgressAction, CancellationToken = CancellationToken, @@ -120,7 +133,8 @@ public async Task CopyObjectAndChildren( CancellationToken.ThrowIfCancellationRequested(); - using ParallelServerApi api = new(BaseUri, AuthorizationToken, BlobStorageFolder, TimeoutSeconds); + using ParallelServerApi api = + new(_http, _activityFactory, BaseUri, AuthorizationToken, BlobStorageFolder, TimeoutSeconds); var stopwatch = Stopwatch.StartNew(); api.CancellationToken = CancellationToken; @@ -264,13 +278,6 @@ public void EndWrite() _sendingThread = null; } - private void Initialize(string baseUri) - { - SpeckleLog.Logger.Information("Initializing a new Remote Transport for {baseUri}", baseUri); - - Api = new ParallelServerApi(BaseUri, AuthorizationToken, BlobStorageFolder, TimeoutSeconds); - } - public override string ToString() { return $"Server Transport @{Account.serverInfo.url}"; diff --git a/src/Speckle.Sdk/Transports/ServerTransportFactory.cs b/src/Speckle.Sdk/Transports/ServerTransportFactory.cs index d67da531..0710cfe6 100644 --- a/src/Speckle.Sdk/Transports/ServerTransportFactory.cs +++ b/src/Speckle.Sdk/Transports/ServerTransportFactory.cs @@ -1,17 +1,19 @@ using System.Diagnostics.CodeAnalysis; using Speckle.InterfaceGenerator; using Speckle.Sdk.Credentials; +using Speckle.Sdk.Helpers; +using Speckle.Sdk.Logging; namespace Speckle.Sdk.Transports; [GenerateAutoInterface] [ExcludeFromCodeCoverage] //factories don't need coverage -public class ServerTransportFactory : IServerTransportFactory +public class ServerTransportFactory(ISpeckleHttp http, ISdkActivityFactory activityFactory) : IServerTransportFactory { - public IServerTransport Create( + public ServerTransport Create( Account account, string streamId, int timeoutSeconds = 60, string? blobStorageFolder = null - ) => new ServerTransport(account, streamId, timeoutSeconds, blobStorageFolder); + ) => new ServerTransport(http, activityFactory, account, streamId, timeoutSeconds, blobStorageFolder); } diff --git a/src/Speckle.Sdk/Transports/ServerUtils/ParallelServerAPI.cs b/src/Speckle.Sdk/Transports/ServerUtils/ParallelServerAPI.cs index ff3159ef..a976758c 100644 --- a/src/Speckle.Sdk/Transports/ServerUtils/ParallelServerAPI.cs +++ b/src/Speckle.Sdk/Transports/ServerUtils/ParallelServerAPI.cs @@ -1,6 +1,8 @@ using System.Collections.Concurrent; using System.Diagnostics; using Speckle.Sdk.Common; +using Speckle.Sdk.Helpers; +using Speckle.Sdk.Logging; using Speckle.Sdk.Serialisation.Utilities; namespace Speckle.Sdk.Transports.ServerUtils; @@ -21,11 +23,15 @@ internal class ParallelServerApi : ParallelOperationExecutor { private readonly string _authToken; + private readonly ISpeckleHttp _http; + private readonly ISdkActivityFactory _activityFactory; private readonly Uri _baseUri; private readonly int _timeoutSeconds; public ParallelServerApi( + ISpeckleHttp http, + ISdkActivityFactory activityFactory, Uri baseUri, string authorizationToken, string blobStorageFolder, @@ -34,6 +40,8 @@ public ParallelServerApi( int numBufferedOperations = 8 ) { + _http = http; + _activityFactory = activityFactory; _baseUri = baseUri; _authToken = authorizationToken; _timeoutSeconds = timeoutSeconds; @@ -204,7 +212,7 @@ public void EnsureStarted() protected override void ThreadMain() { - using ServerApi serialApi = new(_baseUri, _authToken, BlobStorageFolder, _timeoutSeconds); + using ServerApi serialApi = new(_http, _activityFactory, _baseUri, _authToken, BlobStorageFolder, _timeoutSeconds); serialApi.CancellationToken = CancellationToken; serialApi.CompressPayloads = CompressPayloads; diff --git a/src/Speckle.Sdk/Transports/ServerUtils/ServerAPI.cs b/src/Speckle.Sdk/Transports/ServerUtils/ServerAPI.cs index 696a9bf8..60a59fad 100644 --- a/src/Speckle.Sdk/Transports/ServerUtils/ServerAPI.cs +++ b/src/Speckle.Sdk/Transports/ServerUtils/ServerAPI.cs @@ -12,6 +12,7 @@ namespace Speckle.Sdk.Transports.ServerUtils; public sealed class ServerApi : IDisposable, IServerApi { + private readonly ISdkActivityFactory _activityFactory; private const int BATCH_SIZE_GET_OBJECTS = 10000; private const int BATCH_SIZE_HAS_OBJECTS = 100000; @@ -26,21 +27,26 @@ public sealed class ServerApi : IDisposable, IServerApi private readonly HttpClient _client; - public ServerApi(Uri baseUri, string? authorizationToken, string blobStorageFolder, int timeoutSeconds = 120) + public ServerApi( + ISpeckleHttp speckleHttp, + ISdkActivityFactory activityFactory, + Uri baseUri, + string? authorizationToken, + string blobStorageFolder, + int timeoutSeconds = 120 + ) { + _activityFactory = activityFactory; CancellationToken = CancellationToken.None; BlobStorageFolder = blobStorageFolder; - _client = Http.GetHttpProxyClient( - new SpeckleHttpClientHandler( - new HttpClientHandler { AutomaticDecompression = DecompressionMethods.GZip }, - Http.HttpAsyncPolicy(timeoutSeconds: timeoutSeconds) - ) + _client = speckleHttp.CreateHttpClient( + new HttpClientHandler { AutomaticDecompression = DecompressionMethods.GZip }, + timeoutSeconds: timeoutSeconds, + authorizationToken: authorizationToken ); _client.BaseAddress = baseUri; - - Http.AddAuthHeader(_client, authorizationToken); } public CancellationToken CancellationToken { get; set; } @@ -55,7 +61,7 @@ public void Dispose() public async Task DownloadSingleObject(string streamId, string objectId, Action? progress) { - using var _ = SpeckleActivityFactory.Start(); + using var _ = _activityFactory.Start(); CancellationToken.ThrowIfCancellationRequested(); // Get root object @@ -85,7 +91,7 @@ CbObjectDownloaded onObjectCallback { return; } - using var _ = SpeckleActivityFactory.Start(); + using var _ = _activityFactory.Start(); if (objectIds.Count < BATCH_SIZE_GET_OBJECTS) { diff --git a/src/Speckle.Sdk/packages.lock.json b/src/Speckle.Sdk/packages.lock.json index 2820ef90..8bd70699 100644 --- a/src/Speckle.Sdk/packages.lock.json +++ b/src/Speckle.Sdk/packages.lock.json @@ -35,6 +35,24 @@ "SQLitePCLRaw.bundle_e_sqlite3": "2.1.4" } }, + "Microsoft.Extensions.DependencyInjection.Abstractions": { + "type": "Direct", + "requested": "[3.1.0, )", + "resolved": "3.1.0", + "contentHash": "44rDtOf1JXXAFpNT2EXMExaDm/4OJ2RXOL9i9lE4bK427nzC7Exphv+beB6IgluyE2GIoo8zezTStMXI7MQ8WA==" + }, + "Microsoft.Extensions.Logging": { + "type": "Direct", + "requested": "[3.1.0, )", + "resolved": "3.1.0", + "contentHash": "P+8sKQ8L4ooL79sxxqwFPxGGC3aBrUDLB/dZqhs4J0XjTyrkeeyJQ4D4nzJB6OnAhy78HIIgQ/RbD6upOXLynw==", + "dependencies": { + "Microsoft.Extensions.Configuration.Binder": "3.1.0", + "Microsoft.Extensions.DependencyInjection": "3.1.0", + "Microsoft.Extensions.Logging.Abstractions": "3.1.0", + "Microsoft.Extensions.Options": "3.1.0" + } + }, "Microsoft.SourceLink.GitHub": { "type": "Direct", "requested": "[8.0.0, )", @@ -156,6 +174,63 @@ "SQLitePCLRaw.core": "2.1.4" } }, + "Microsoft.Extensions.Configuration": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "Lu41BWNmwhKr6LgyQvcYBOge0pPvmiaK8R5UHXX4//wBhonJyWcT2OK1mqYfEM5G7pTf31fPrpIHOT6sN7EGOA==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "3.1.0" + } + }, + "Microsoft.Extensions.Configuration.Abstractions": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "ESz6bVoDQX7sgWdKHF6G9Pq672T8k+19AFb/txDXwdz7MoqaNQj2/in3agm/3qae9V+WvQZH86LLTNVo0it8vQ==", + "dependencies": { + "Microsoft.Extensions.Primitives": "3.1.0" + } + }, + "Microsoft.Extensions.Configuration.Binder": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "o9eELDBfNkR7sUtYysFZ1Q7BQ1mYt27DMkups/3vu7xgPyOpMD+iAfrBZFzUXT2iw0fmFb8s1gfNBZS+IgjKdQ==", + "dependencies": { + "Microsoft.Extensions.Configuration": "3.1.0" + } + }, + "Microsoft.Extensions.DependencyInjection": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "KVkv3aF2MQpmGFRh4xRx2CNbc2sjDFk+lH4ySrjWSOS+XoY1Xc+sJphw3N0iYOpoeCCq8976ceVYDH8sdx2qIQ==", + "dependencies": { + "Microsoft.Bcl.AsyncInterfaces": "1.1.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.0" + } + }, + "Microsoft.Extensions.Logging.Abstractions": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "jjo4YXRx6MIpv6DiRxJjSpl+sPP0+5VW0clMEdLyIAz44PPwrDTFrd5PZckIxIXl1kKZ2KK6IL2nkt0+ug2MQg==" + }, + "Microsoft.Extensions.Options": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "9b6JHY7TAXrSfZ6EEGf+j8XnqKIiMPErfmaNXhJYSCb+BUW2H4RtzkNJvwLJzwgzqBP0wtTjyA6Uw4BPPdmkMw==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.0", + "Microsoft.Extensions.Primitives": "3.1.0", + "System.ComponentModel.Annotations": "4.7.0" + } + }, + "Microsoft.Extensions.Primitives": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "LEKAnX7lhUhSoIc2XraCTK3M4IU/LdVUzCe464Sa4+7F4ZJuXHHRzZli2mDbiT4xzAZhgqXbvfnb5+CNDcQFfg==", + "dependencies": { + "System.Memory": "4.5.2", + "System.Runtime.CompilerServices.Unsafe": "4.7.0" + } + }, "Microsoft.NETCore.Platforms": { "type": "Transitive", "resolved": "1.1.0", @@ -206,6 +281,11 @@ "resolved": "4.5.1", "contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg==" }, + "System.ComponentModel.Annotations": { + "type": "Transitive", + "resolved": "4.7.0", + "contentHash": "0YFqjhp/mYkDGpU0Ye1GjE53HMp9UVfGN7seGpAMttAC0C40v5gw598jCgpbBLMmCo0E5YRLBv5Z2doypO49ZQ==" + }, "System.Memory": { "type": "Transitive", "resolved": "4.5.4", @@ -307,6 +387,24 @@ "SQLitePCLRaw.bundle_e_sqlite3": "2.1.4" } }, + "Microsoft.Extensions.DependencyInjection.Abstractions": { + "type": "Direct", + "requested": "[3.1.0, )", + "resolved": "3.1.0", + "contentHash": "44rDtOf1JXXAFpNT2EXMExaDm/4OJ2RXOL9i9lE4bK427nzC7Exphv+beB6IgluyE2GIoo8zezTStMXI7MQ8WA==" + }, + "Microsoft.Extensions.Logging": { + "type": "Direct", + "requested": "[3.1.0, )", + "resolved": "3.1.0", + "contentHash": "P+8sKQ8L4ooL79sxxqwFPxGGC3aBrUDLB/dZqhs4J0XjTyrkeeyJQ4D4nzJB6OnAhy78HIIgQ/RbD6upOXLynw==", + "dependencies": { + "Microsoft.Extensions.Configuration.Binder": "3.1.0", + "Microsoft.Extensions.DependencyInjection": "3.1.0", + "Microsoft.Extensions.Logging.Abstractions": "3.1.0", + "Microsoft.Extensions.Options": "3.1.0" + } + }, "Microsoft.SourceLink.GitHub": { "type": "Direct", "requested": "[8.0.0, )", @@ -402,6 +500,57 @@ "SQLitePCLRaw.core": "2.1.4" } }, + "Microsoft.Extensions.Configuration": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "Lu41BWNmwhKr6LgyQvcYBOge0pPvmiaK8R5UHXX4//wBhonJyWcT2OK1mqYfEM5G7pTf31fPrpIHOT6sN7EGOA==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "3.1.0" + } + }, + "Microsoft.Extensions.Configuration.Abstractions": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "ESz6bVoDQX7sgWdKHF6G9Pq672T8k+19AFb/txDXwdz7MoqaNQj2/in3agm/3qae9V+WvQZH86LLTNVo0it8vQ==", + "dependencies": { + "Microsoft.Extensions.Primitives": "3.1.0" + } + }, + "Microsoft.Extensions.Configuration.Binder": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "o9eELDBfNkR7sUtYysFZ1Q7BQ1mYt27DMkups/3vu7xgPyOpMD+iAfrBZFzUXT2iw0fmFb8s1gfNBZS+IgjKdQ==", + "dependencies": { + "Microsoft.Extensions.Configuration": "3.1.0" + } + }, + "Microsoft.Extensions.DependencyInjection": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "KVkv3aF2MQpmGFRh4xRx2CNbc2sjDFk+lH4ySrjWSOS+XoY1Xc+sJphw3N0iYOpoeCCq8976ceVYDH8sdx2qIQ==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.0" + } + }, + "Microsoft.Extensions.Logging.Abstractions": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "jjo4YXRx6MIpv6DiRxJjSpl+sPP0+5VW0clMEdLyIAz44PPwrDTFrd5PZckIxIXl1kKZ2KK6IL2nkt0+ug2MQg==" + }, + "Microsoft.Extensions.Options": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "9b6JHY7TAXrSfZ6EEGf+j8XnqKIiMPErfmaNXhJYSCb+BUW2H4RtzkNJvwLJzwgzqBP0wtTjyA6Uw4BPPdmkMw==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.0", + "Microsoft.Extensions.Primitives": "3.1.0" + } + }, + "Microsoft.Extensions.Primitives": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "LEKAnX7lhUhSoIc2XraCTK3M4IU/LdVUzCe464Sa4+7F4ZJuXHHRzZli2mDbiT4xzAZhgqXbvfnb5+CNDcQFfg==" + }, "Microsoft.SourceLink.Common": { "type": "Transitive", "resolved": "8.0.0", diff --git a/tests/Speckle.LongSendProblem/Program.cs b/tests/Speckle.LongSendProblem/Program.cs deleted file mode 100644 index 95290d11..00000000 --- a/tests/Speckle.LongSendProblem/Program.cs +++ /dev/null @@ -1,70 +0,0 @@ -using Speckle.Objects.Geometry; -using Speckle.Sdk; -using Speckle.Sdk.Api; -using Speckle.Sdk.Credentials; -using Speckle.Sdk.Host; -using Speckle.Sdk.Logging; -using Speckle.Sdk.Models; -using Speckle.Sdk.Transports; - -//Replace this with a brand new model URL -Uri modelUrl = new("https://testing1.speckle.dev/projects/cdedc63e6d/models/2d68380f1d"); - -//Keep this as-is, copy the Data.db into %appdata%/longsendtest/Data.db -const string OBJECT_ID = "5cbf84a0061172102ef8a66ae914f232"; - -SetupSpeckle(); -var testData = await GetSampleData(OBJECT_ID).ConfigureAwait(false); -await SendToSpeckle(testData, modelUrl).ConfigureAwait(false); - -return; - -static async Task SendToSpeckle(Base testData, Uri modelUrl) -{ - SpeckleLog.Logger.Information("Starting Long Send Test Send"); - var destinationTransport = await GetDestination(modelUrl).ConfigureAwait(false); - - var (res, _) = await Operations.Send(testData, new[] { destinationTransport }).ConfigureAwait(false); - SpeckleLog.Logger.Information("Starting Send was successful: {objectId}", res); -} - -static async Task GetDestination(Uri modelUrl) -{ - StreamWrapper sw = new(modelUrl.ToString()); - var acc = await sw.GetAccount().ConfigureAwait(false); - return new ServerTransport(acc, sw.StreamId); -} - -static async Task GetSampleData(string objectId) -{ - SpeckleLog.Logger.Information("Gathering Sample Data Set"); - using SQLiteTransport source = new(SpecklePathProvider.UserApplicationDataPath(), "longsendtest"); - MemoryTransport memoryTransport = new(); - return await Operations.Receive(objectId, source, memoryTransport).ConfigureAwait(false); -} - -static void SetupSpeckle() -{ - TypeLoader.Initialize(typeof(Base).Assembly, typeof(Point).Assembly); - var config = new SpeckleConfiguration( - new("Long Send Problem Test Script", "LongSend"), - default, - new( - MinimumLevel: SpeckleLogLevel.Debug, - Console: true, - File: new(Path: "SpeckleCoreLog.txt"), - Otel: new( - Endpoint: "https://seq.speckle.systems/ingest/otlp/v1/logs", - Headers: new() { { "X-Seq-ApiKey", "agZqxG4jQELxQQXh0iZQ" } } - ) - ), - new( - Console: false, - Otel: new( - Endpoint: "https://seq.speckle.systems/ingest/otlp/v1/traces", - Headers: new() { { "X-Seq-ApiKey", "agZqxG4jQELxQQXh0iZQ" } } - ) - ) - ); - Setup.Initialize(config); -} diff --git a/tests/Speckle.LongSendProblem/Speckle.LongSendProblem.csproj b/tests/Speckle.LongSendProblem/Speckle.LongSendProblem.csproj deleted file mode 100644 index 3b260bac..00000000 --- a/tests/Speckle.LongSendProblem/Speckle.LongSendProblem.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - Exe - net8.0 - enable - enable - - - - - - - diff --git a/tests/Speckle.LongSendProblem/packages.lock.json b/tests/Speckle.LongSendProblem/packages.lock.json deleted file mode 100644 index 457984c7..00000000 --- a/tests/Speckle.LongSendProblem/packages.lock.json +++ /dev/null @@ -1,204 +0,0 @@ -{ - "version": 2, - "dependencies": { - "net8.0": { - "GitVersion.MsBuild": { - "type": "Direct", - "requested": "[5.12.0, )", - "resolved": "5.12.0", - "contentHash": "dJuigXycpJNOiLT9or7mkHSkGFHgGW3/p6cNNYEKZBa7Hhp1FdX/cvqYWWYhRLpfoZOedeA7aRbYiOB3vW/dvA==" - }, - "Microsoft.SourceLink.GitHub": { - "type": "Direct", - "requested": "[8.0.0, )", - "resolved": "8.0.0", - "contentHash": "G5q7OqtwIyGTkeIOAc3u2ZuV/kicQaec5EaRnc0pIeSnh9LUjj+PYQrJYBURvDt7twGl2PKA7nSN0kz1Zw5bnQ==", - "dependencies": { - "Microsoft.Build.Tasks.Git": "8.0.0", - "Microsoft.SourceLink.Common": "8.0.0" - } - }, - "PolySharp": { - "type": "Direct", - "requested": "[1.14.1, )", - "resolved": "1.14.1", - "contentHash": "mOOmFYwad3MIOL14VCjj02LljyF1GNw1wP0YVlxtcPvqdxjGGMNdNJJxHptlry3MOd8b40Flm8RPOM8JOlN2sQ==" - }, - "Speckle.InterfaceGenerator": { - "type": "Direct", - "requested": "[0.9.6, )", - "resolved": "0.9.6", - "contentHash": "HKH7tYrYYlCK1ct483hgxERAdVdMtl7gUKW9ijWXxA1UsYR4Z+TrRHYmzZ9qmpu1NnTycSrp005NYM78GDKV1w==" - }, - "GraphQL.Client.Abstractions": { - "type": "Transitive", - "resolved": "6.0.0", - "contentHash": "h7uzWFORHZ+CCjwr/ThAyXMr0DPpzEANDa4Uo54wqCQ+j7qUKwqYTgOrb1W40sqbvNaZm9v/X7It31SUw0maHA==", - "dependencies": { - "GraphQL.Primitives": "6.0.0" - } - }, - "GraphQL.Client.Abstractions.Websocket": { - "type": "Transitive", - "resolved": "6.0.0", - "contentHash": "Nr9bPf8gIOvLuXpqEpqr9z9jslYFJOvd0feHth3/kPqeR3uMbjF5pjiwh4jxyMcxHdr8Pb6QiXkV3hsSyt0v7A==", - "dependencies": { - "GraphQL.Client.Abstractions": "6.0.0" - } - }, - "GraphQL.Primitives": { - "type": "Transitive", - "resolved": "6.0.0", - "contentHash": "yg72rrYDapfsIUrul7aF6wwNnTJBOFvuA9VdDTQpPa8AlAriHbufeXYLBcodKjfUdkCnaiggX1U/nEP08Zb5GA==" - }, - "Microsoft.Build.Tasks.Git": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "bZKfSIKJRXLTuSzLudMFte/8CempWjVamNUR5eHJizsy+iuOuO/k2gnh7W0dHJmYY0tBf+gUErfluCv5mySAOQ==" - }, - "Microsoft.Data.Sqlite.Core": { - "type": "Transitive", - "resolved": "7.0.7", - "contentHash": "21FRzcJhaTrlv7kTrqr/ltFcSQM2TyuTTPhUcjO8H73od7Bb3QraNW90c7lUucNI/245XPkKZG4fp7/7OsKCSg==", - "dependencies": { - "SQLitePCLRaw.core": "2.1.4" - } - }, - "Microsoft.SourceLink.Common": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw==" - }, - "SQLitePCLRaw.bundle_e_sqlite3": { - "type": "Transitive", - "resolved": "2.1.4", - "contentHash": "EWI1olKDjFEBMJu0+3wuxwziIAdWDVMYLhuZ3Qs84rrz+DHwD00RzWPZCa+bLnHCf3oJwuFZIRsHT5p236QXww==", - "dependencies": { - "SQLitePCLRaw.lib.e_sqlite3": "2.1.4", - "SQLitePCLRaw.provider.e_sqlite3": "2.1.4" - } - }, - "SQLitePCLRaw.core": { - "type": "Transitive", - "resolved": "2.1.4", - "contentHash": "inBjvSHo9UDKneGNzfUfDjK08JzlcIhn1+SP5Y3m6cgXpCxXKCJDy6Mka7LpgSV+UZmKSnC8rTwB0SQ0xKu5pA==", - "dependencies": { - "System.Memory": "4.5.3" - } - }, - "SQLitePCLRaw.lib.e_sqlite3": { - "type": "Transitive", - "resolved": "2.1.4", - "contentHash": "2C9Q9eX7CPLveJA0rIhf9RXAvu+7nWZu1A2MdG6SD/NOu26TakGgL1nsbc0JAspGijFOo3HoN79xrx8a368fBg==" - }, - "SQLitePCLRaw.provider.e_sqlite3": { - "type": "Transitive", - "resolved": "2.1.4", - "contentHash": "CSlb5dUp1FMIkez9Iv5EXzpeq7rHryVNqwJMWnpq87j9zWZexaEMdisDktMsnnrzKM6ahNrsTkjqNodTBPBxtQ==", - "dependencies": { - "SQLitePCLRaw.core": "2.1.4" - } - }, - "System.Memory": { - "type": "Transitive", - "resolved": "4.5.3", - "contentHash": "3oDzvc/zzetpTKWMShs1AADwZjQ/36HnsufHRPcOjyRAAMLDlu2iD33MBI2opxnezcVUtXyqDXXjoFMOU9c7SA==" - }, - "System.Reactive": { - "type": "Transitive", - "resolved": "5.0.0", - "contentHash": "erBZjkQHWL9jpasCE/0qKAryzVBJFxGHVBAvgRN1bzM0q2s1S4oYREEEL0Vb+1kA/6BKb5FjUZMp5VXmy+gzkQ==" - }, - "speckle.objects": { - "type": "Project", - "dependencies": { - "Speckle.Sdk": "[1.0.0, )" - } - }, - "speckle.sdk": { - "type": "Project", - "dependencies": { - "GraphQL.Client": "[6.0.0, )", - "Microsoft.CSharp": "[4.7.0, )", - "Microsoft.Data.Sqlite": "[7.0.7, )", - "Polly": "[7.2.3, )", - "Polly.Contrib.WaitAndRetry": "[1.1.1, )", - "Polly.Extensions.Http": "[3.0.0, )", - "Speckle.DoubleNumerics": "[4.0.1, )", - "Speckle.Newtonsoft.Json": "[13.0.2, )", - "Speckle.Sdk.Logging": "[1.0.0, )", - "System.Text.Json": "[5.0.2, )" - } - }, - "speckle.sdk.logging": { - "type": "Project" - }, - "GraphQL.Client": { - "type": "CentralTransitive", - "requested": "[6.0.0, )", - "resolved": "6.0.0", - "contentHash": "8yPNBbuVBpTptivyAlak4GZvbwbUcjeQTL4vN1HKHRuOykZ4r7l5fcLS6vpyPyLn0x8FsL31xbOIKyxbmR9rbA==", - "dependencies": { - "GraphQL.Client.Abstractions": "6.0.0", - "GraphQL.Client.Abstractions.Websocket": "6.0.0", - "System.Reactive": "5.0.0" - } - }, - "Microsoft.CSharp": { - "type": "CentralTransitive", - "requested": "[4.7.0, )", - "resolved": "4.7.0", - "contentHash": "pTj+D3uJWyN3My70i2Hqo+OXixq3Os2D1nJ2x92FFo6sk8fYS1m1WLNTs0Dc1uPaViH0YvEEwvzddQ7y4rhXmA==" - }, - "Microsoft.Data.Sqlite": { - "type": "CentralTransitive", - "requested": "[7.0.7, )", - "resolved": "7.0.7", - "contentHash": "tiNmV1oPy+Z2R7Wd0bPB/FxCr8B+/5q11OpDMG751GA/YuOL7MZrBFfzv5oFRlFe08K6sjrnbrauzzGIeNrzLQ==", - "dependencies": { - "Microsoft.Data.Sqlite.Core": "7.0.7", - "SQLitePCLRaw.bundle_e_sqlite3": "2.1.4" - } - }, - "Polly": { - "type": "CentralTransitive", - "requested": "[7.2.3, )", - "resolved": "7.2.3", - "contentHash": "DeCY0OFbNdNxsjntr1gTXHJ5pKUwYzp04Er2LLeN3g6pWhffsGuKVfMBLe1lw7x76HrPkLxKEFxBlpRxS2nDEQ==" - }, - "Polly.Contrib.WaitAndRetry": { - "type": "CentralTransitive", - "requested": "[1.1.1, )", - "resolved": "1.1.1", - "contentHash": "1MUQLiSo4KDkQe6nzQRhIU05lm9jlexX5BVsbuw0SL82ynZ+GzAHQxJVDPVBboxV37Po3SG077aX8DuSy8TkaA==" - }, - "Polly.Extensions.Http": { - "type": "CentralTransitive", - "requested": "[3.0.0, )", - "resolved": "3.0.0", - "contentHash": "drrG+hB3pYFY7w1c3BD+lSGYvH2oIclH8GRSehgfyP5kjnFnHKQuuBhuHLv+PWyFuaTDyk/vfRpnxOzd11+J8g==", - "dependencies": { - "Polly": "7.1.0" - } - }, - "Speckle.DoubleNumerics": { - "type": "CentralTransitive", - "requested": "[4.0.1, )", - "resolved": "4.0.1", - "contentHash": "MzEQ1Im0zTja+tEsdRIk/WlPiKqb22NmTOJcR1ZKm/mz46pezyyID3/wRz6vJUELMpSLnG7LhsxBL+nxbr7V0w==" - }, - "Speckle.Newtonsoft.Json": { - "type": "CentralTransitive", - "requested": "[13.0.2, )", - "resolved": "13.0.2", - "contentHash": "g1BejUZwax5PRfL6xHgLEK23sqHWOgOj9hE7RvfRRlN00AGt8GnPYt8HedSK7UB3HiRW8zCA9Pn0iiYxCK24BA==" - }, - "System.Text.Json": { - "type": "CentralTransitive", - "requested": "[5.0.2, )", - "resolved": "5.0.2", - "contentHash": "I47dVIGiV6SfAyppphxqupertT/5oZkYLDCX6vC3HpOI4ZLjyoKAreUoem2ie6G0RbRuFrlqz/PcTQjfb2DOfQ==" - } - } - } -} \ No newline at end of file diff --git a/tests/Speckle.Objects.Tests.Unit/packages.lock.json b/tests/Speckle.Objects.Tests.Unit/packages.lock.json index 2681856b..326e78cf 100644 --- a/tests/Speckle.Objects.Tests.Unit/packages.lock.json +++ b/tests/Speckle.Objects.Tests.Unit/packages.lock.json @@ -121,6 +121,57 @@ "SQLitePCLRaw.core": "2.1.4" } }, + "Microsoft.Extensions.Configuration": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "Lu41BWNmwhKr6LgyQvcYBOge0pPvmiaK8R5UHXX4//wBhonJyWcT2OK1mqYfEM5G7pTf31fPrpIHOT6sN7EGOA==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "3.1.0" + } + }, + "Microsoft.Extensions.Configuration.Abstractions": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "ESz6bVoDQX7sgWdKHF6G9Pq672T8k+19AFb/txDXwdz7MoqaNQj2/in3agm/3qae9V+WvQZH86LLTNVo0it8vQ==", + "dependencies": { + "Microsoft.Extensions.Primitives": "3.1.0" + } + }, + "Microsoft.Extensions.Configuration.Binder": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "o9eELDBfNkR7sUtYysFZ1Q7BQ1mYt27DMkups/3vu7xgPyOpMD+iAfrBZFzUXT2iw0fmFb8s1gfNBZS+IgjKdQ==", + "dependencies": { + "Microsoft.Extensions.Configuration": "3.1.0" + } + }, + "Microsoft.Extensions.DependencyInjection": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "KVkv3aF2MQpmGFRh4xRx2CNbc2sjDFk+lH4ySrjWSOS+XoY1Xc+sJphw3N0iYOpoeCCq8976ceVYDH8sdx2qIQ==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.0" + } + }, + "Microsoft.Extensions.Logging.Abstractions": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "jjo4YXRx6MIpv6DiRxJjSpl+sPP0+5VW0clMEdLyIAz44PPwrDTFrd5PZckIxIXl1kKZ2KK6IL2nkt0+ug2MQg==" + }, + "Microsoft.Extensions.Options": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "9b6JHY7TAXrSfZ6EEGf+j8XnqKIiMPErfmaNXhJYSCb+BUW2H4RtzkNJvwLJzwgzqBP0wtTjyA6Uw4BPPdmkMw==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.0", + "Microsoft.Extensions.Primitives": "3.1.0" + } + }, + "Microsoft.Extensions.Primitives": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "LEKAnX7lhUhSoIc2XraCTK3M4IU/LdVUzCe464Sa4+7F4ZJuXHHRzZli2mDbiT4xzAZhgqXbvfnb5+CNDcQFfg==" + }, "Microsoft.SourceLink.Common": { "type": "Transitive", "resolved": "8.0.0", @@ -218,18 +269,16 @@ "GraphQL.Client": "[6.0.0, )", "Microsoft.CSharp": "[4.7.0, )", "Microsoft.Data.Sqlite": "[7.0.7, )", + "Microsoft.Extensions.DependencyInjection.Abstractions": "[3.1.0, )", + "Microsoft.Extensions.Logging": "[3.1.0, )", "Polly": "[7.2.3, )", "Polly.Contrib.WaitAndRetry": "[1.1.1, )", "Polly.Extensions.Http": "[3.0.0, )", "Speckle.DoubleNumerics": "[4.0.1, )", "Speckle.Newtonsoft.Json": "[13.0.2, )", - "Speckle.Sdk.Logging": "[1.0.0, )", "System.Text.Json": "[5.0.2, )" } }, - "speckle.sdk.logging": { - "type": "Project" - }, "GraphQL.Client": { "type": "CentralTransitive", "requested": "[6.0.0, )", @@ -257,6 +306,24 @@ "SQLitePCLRaw.bundle_e_sqlite3": "2.1.4" } }, + "Microsoft.Extensions.DependencyInjection.Abstractions": { + "type": "CentralTransitive", + "requested": "[3.1.0, )", + "resolved": "3.1.0", + "contentHash": "44rDtOf1JXXAFpNT2EXMExaDm/4OJ2RXOL9i9lE4bK427nzC7Exphv+beB6IgluyE2GIoo8zezTStMXI7MQ8WA==" + }, + "Microsoft.Extensions.Logging": { + "type": "CentralTransitive", + "requested": "[3.1.0, )", + "resolved": "3.1.0", + "contentHash": "P+8sKQ8L4ooL79sxxqwFPxGGC3aBrUDLB/dZqhs4J0XjTyrkeeyJQ4D4nzJB6OnAhy78HIIgQ/RbD6upOXLynw==", + "dependencies": { + "Microsoft.Extensions.Configuration.Binder": "3.1.0", + "Microsoft.Extensions.DependencyInjection": "3.1.0", + "Microsoft.Extensions.Logging.Abstractions": "3.1.0", + "Microsoft.Extensions.Options": "3.1.0" + } + }, "Polly": { "type": "CentralTransitive", "requested": "[7.2.3, )", diff --git a/tests/Speckle.Sdk.Serialization.Tests/SerializationTests.cs b/tests/Speckle.Sdk.Serialization.Tests/SerializationTests.cs index 594baede..e22e3832 100644 --- a/tests/Speckle.Sdk.Serialization.Tests/SerializationTests.cs +++ b/tests/Speckle.Sdk.Serialization.Tests/SerializationTests.cs @@ -1,4 +1,5 @@ using System.Reflection; +using Microsoft.Extensions.Logging.Abstractions; using NUnit.Framework; using Shouldly; using Speckle.Newtonsoft.Json.Linq; @@ -63,7 +64,7 @@ public async Task Basic_Namespace_Validation(string fileName) var starts = oldSpeckleType.StartsWith("Speckle.Core.") || oldSpeckleType.StartsWith("Objects."); starts.ShouldBeTrue($"{oldSpeckleType} isn't expected"); - var baseType = await deserializer.DeserializeJsonAsync(objJson); + var baseType = await deserializer.DeserializeAsync(objJson); baseType.id.ShouldBe(id); starts = baseType.speckle_type.StartsWith("Speckle.Core.") || baseType.speckle_type.StartsWith("Objects."); diff --git a/tests/Speckle.Sdk.Serialization.Tests/packages.lock.json b/tests/Speckle.Sdk.Serialization.Tests/packages.lock.json index 2681856b..326e78cf 100644 --- a/tests/Speckle.Sdk.Serialization.Tests/packages.lock.json +++ b/tests/Speckle.Sdk.Serialization.Tests/packages.lock.json @@ -121,6 +121,57 @@ "SQLitePCLRaw.core": "2.1.4" } }, + "Microsoft.Extensions.Configuration": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "Lu41BWNmwhKr6LgyQvcYBOge0pPvmiaK8R5UHXX4//wBhonJyWcT2OK1mqYfEM5G7pTf31fPrpIHOT6sN7EGOA==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "3.1.0" + } + }, + "Microsoft.Extensions.Configuration.Abstractions": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "ESz6bVoDQX7sgWdKHF6G9Pq672T8k+19AFb/txDXwdz7MoqaNQj2/in3agm/3qae9V+WvQZH86LLTNVo0it8vQ==", + "dependencies": { + "Microsoft.Extensions.Primitives": "3.1.0" + } + }, + "Microsoft.Extensions.Configuration.Binder": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "o9eELDBfNkR7sUtYysFZ1Q7BQ1mYt27DMkups/3vu7xgPyOpMD+iAfrBZFzUXT2iw0fmFb8s1gfNBZS+IgjKdQ==", + "dependencies": { + "Microsoft.Extensions.Configuration": "3.1.0" + } + }, + "Microsoft.Extensions.DependencyInjection": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "KVkv3aF2MQpmGFRh4xRx2CNbc2sjDFk+lH4ySrjWSOS+XoY1Xc+sJphw3N0iYOpoeCCq8976ceVYDH8sdx2qIQ==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.0" + } + }, + "Microsoft.Extensions.Logging.Abstractions": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "jjo4YXRx6MIpv6DiRxJjSpl+sPP0+5VW0clMEdLyIAz44PPwrDTFrd5PZckIxIXl1kKZ2KK6IL2nkt0+ug2MQg==" + }, + "Microsoft.Extensions.Options": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "9b6JHY7TAXrSfZ6EEGf+j8XnqKIiMPErfmaNXhJYSCb+BUW2H4RtzkNJvwLJzwgzqBP0wtTjyA6Uw4BPPdmkMw==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.0", + "Microsoft.Extensions.Primitives": "3.1.0" + } + }, + "Microsoft.Extensions.Primitives": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "LEKAnX7lhUhSoIc2XraCTK3M4IU/LdVUzCe464Sa4+7F4ZJuXHHRzZli2mDbiT4xzAZhgqXbvfnb5+CNDcQFfg==" + }, "Microsoft.SourceLink.Common": { "type": "Transitive", "resolved": "8.0.0", @@ -218,18 +269,16 @@ "GraphQL.Client": "[6.0.0, )", "Microsoft.CSharp": "[4.7.0, )", "Microsoft.Data.Sqlite": "[7.0.7, )", + "Microsoft.Extensions.DependencyInjection.Abstractions": "[3.1.0, )", + "Microsoft.Extensions.Logging": "[3.1.0, )", "Polly": "[7.2.3, )", "Polly.Contrib.WaitAndRetry": "[1.1.1, )", "Polly.Extensions.Http": "[3.0.0, )", "Speckle.DoubleNumerics": "[4.0.1, )", "Speckle.Newtonsoft.Json": "[13.0.2, )", - "Speckle.Sdk.Logging": "[1.0.0, )", "System.Text.Json": "[5.0.2, )" } }, - "speckle.sdk.logging": { - "type": "Project" - }, "GraphQL.Client": { "type": "CentralTransitive", "requested": "[6.0.0, )", @@ -257,6 +306,24 @@ "SQLitePCLRaw.bundle_e_sqlite3": "2.1.4" } }, + "Microsoft.Extensions.DependencyInjection.Abstractions": { + "type": "CentralTransitive", + "requested": "[3.1.0, )", + "resolved": "3.1.0", + "contentHash": "44rDtOf1JXXAFpNT2EXMExaDm/4OJ2RXOL9i9lE4bK427nzC7Exphv+beB6IgluyE2GIoo8zezTStMXI7MQ8WA==" + }, + "Microsoft.Extensions.Logging": { + "type": "CentralTransitive", + "requested": "[3.1.0, )", + "resolved": "3.1.0", + "contentHash": "P+8sKQ8L4ooL79sxxqwFPxGGC3aBrUDLB/dZqhs4J0XjTyrkeeyJQ4D4nzJB6OnAhy78HIIgQ/RbD6upOXLynw==", + "dependencies": { + "Microsoft.Extensions.Configuration.Binder": "3.1.0", + "Microsoft.Extensions.DependencyInjection": "3.1.0", + "Microsoft.Extensions.Logging.Abstractions": "3.1.0", + "Microsoft.Extensions.Options": "3.1.0" + } + }, "Polly": { "type": "CentralTransitive", "requested": "[7.2.3, )", diff --git a/tests/Speckle.Sdk.Tests.Integration/Api/GraphQL/Legacy/LegacyAPITests.cs b/tests/Speckle.Sdk.Tests.Integration/Api/GraphQL/Legacy/LegacyAPITests.cs deleted file mode 100644 index 9fdbd2fb..00000000 --- a/tests/Speckle.Sdk.Tests.Integration/Api/GraphQL/Legacy/LegacyAPITests.cs +++ /dev/null @@ -1,495 +0,0 @@ -using Shouldly; -using Speckle.Sdk.Api; -using Speckle.Sdk.Api.GraphQL; -using Speckle.Sdk.Credentials; -using Speckle.Sdk.Host; -using Speckle.Sdk.Models; -using Speckle.Sdk.Tests.Unit.Host; -using Speckle.Sdk.Transports; - -namespace Speckle.Sdk.Tests.Integration.Api.GraphQL.Legacy; - -public class LegacyAPITests : IDisposable -{ - [SetUp] - public void Setup() - { - TypeLoader.Reset(); - TypeLoader.Initialize(typeof(Base).Assembly, typeof(Point).Assembly); - } - - private string _branchId = ""; - private string _branchName = ""; - private string _commitId = ""; - - private Account _firstUserAccount, - _secondUserAccount; - - private Client _myClient, - _secondClient; - - private ServerTransport _myServerTransport, - _otherServerTransport; - - private string _objectId = ""; - - private string _streamId = ""; - - [OneTimeSetUp] - public async Task OneTimeSetup() - { - TypeLoader.Reset(); - TypeLoader.Initialize(typeof(Base).Assembly); - _firstUserAccount = await Fixtures.SeedUser(); - _secondUserAccount = await Fixtures.SeedUser(); - - _myClient = new Client(_firstUserAccount); - _secondClient = new Client(_secondUserAccount); - } - - private void InitServerTransport() - { - _myServerTransport = new ServerTransport(_firstUserAccount, _streamId); - _myServerTransport.Api.CompressPayloads = false; - _otherServerTransport = new ServerTransport(_firstUserAccount, _streamId); - _otherServerTransport.Api.CompressPayloads = false; - } - - [Test] - public async Task ActiveUserGet() - { - var res = await _myClient.ActiveUserGet(); - Assert.That(res!.id, Is.EqualTo(_myClient.Account.userInfo.id)); - } - - [Test] - public async Task OtherUserGet() - { - var res = await _myClient.OtherUserGet(_secondUserAccount.userInfo.id); - res.ShouldNotBeNull(); - Assert.That(res.name, Is.EqualTo(_secondUserAccount.userInfo.name)); - } - - [Test] - public async Task UserSearch() - { - var res = await _myClient.UserSearch(_firstUserAccount.userInfo.email); - Assert.That(res, Has.Count.EqualTo(1)); - Assert.That(res[0].id, Is.EqualTo(_firstUserAccount.userInfo.id)); - } - - [Test] - public async Task ServerVersion() - { - var res = await _myClient.GetServerVersion(); - - Assert.That(res, Is.Not.Null); - } - - [Test, Order(0)] - public async Task StreamCreate() - { - var res = await _myClient.StreamCreate( - new StreamCreateInput { description = "Hello World", name = "Super Stream 01" } - ); - - Assert.That(res, Is.Not.Null); - _streamId = res; - InitServerTransport(); - } - - [Test, Order(11)] - public async Task StreamGet() - { - var res = await _myClient.StreamGet(_streamId); - - Assert.That(res, Is.Not.Null); - Assert.That(res.branches.items[0].name, Is.EqualTo("main")); - Assert.That(res.collaborators, Is.Not.Empty); - } - - [Test, Order(12)] - public async Task IsStreamAccessible() - { - var res = await _myClient.IsStreamAccessible(_streamId); - - Assert.That(res, Is.True); - } - - [Test, Order(20)] - public async Task StreamUpdate() - { - var res = await _myClient.StreamUpdate( - new StreamUpdateInput - { - id = _streamId, - description = "Hello World", - name = "Super Stream 01 EDITED" - } - ); - - Assert.That(res, Is.True); - } - - [Test, Order(31)] - public async Task StreamInviteCreate() - { - var res = await _myClient.StreamInviteCreate( - new StreamInviteCreateInput - { - streamId = _streamId, - email = _secondUserAccount.userInfo.email, - message = "Whasssup!" - } - ); - - Assert.That(res, Is.True); - - Assert.ThrowsAsync( - async () => await _myClient.StreamInviteCreate(new StreamInviteCreateInput { streamId = _streamId }) - ); - } - - [Test, Order(32)] - public async Task StreamInviteGet() - { - var invites = await _secondClient.GetAllPendingInvites(); - - Assert.That(invites, Is.Not.Null); - } - - [Test, Order(33)] - public async Task StreamInviteUse() - { - var invites = await _secondClient.GetAllPendingInvites(); - - var res = await _secondClient.StreamInviteUse(invites[0].streamId, invites[0].token); - - Assert.That(res, Is.True); - } - - [Test, Order(34)] - public async Task StreamUpdatePermission() - { - var res = await _myClient.StreamUpdatePermission( - new StreamPermissionInput - { - role = StreamRoles.STREAM_REVIEWER, - streamId = _streamId, - userId = _secondUserAccount.userInfo.id - } - ); - - Assert.That(res, Is.True); - } - - [Test, Order(40)] - public async Task StreamRevokePermission() - { - var res = await _myClient.StreamRevokePermission( - new StreamRevokePermissionInput { streamId = _streamId, userId = _secondUserAccount.userInfo.id } - ); - - Assert.That(res, Is.True); - } - - #region activity - - [Test, Order(51)] - public async Task StreamGetActivity() - { - var res = await _myClient.StreamGetActivity(_streamId); - - Assert.That(res, Is.Not.Null); - //Assert.AreEqual(commitId, res[0].); - } - - #endregion - - #region comments - - [Test, Order(52)] - public async Task StreamGetComments() - { - var res = await _myClient.StreamGetActivity(_streamId); - - Assert.That(res, Is.Not.Null); - //Assert.AreEqual(commitId, res[0].); - } - - #endregion - - [Test, Order(60)] - public async Task StreamDelete() - { - var res = await _myClient.StreamDelete(_streamId); - Assert.That(res, Is.True); - } - - #region branches - - [Test, Order(41)] - public async Task BranchCreate() - { - var res = await _myClient.BranchCreate( - new BranchCreateInput - { - streamId = _streamId, - description = "this is a sample branch", - name = "sample-branch" - } - ); - Assert.That(res, Is.Not.Null); - _branchId = res; - _branchName = "sample-branch"; - } - - [Test, Order(42)] - public async Task BranchGet() - { - var res = await _myClient.BranchGet(_streamId, _branchName); - - Assert.That(res, Is.Not.Null); - Assert.That(res.description, Is.EqualTo("this is a sample branch")); - } - - [Test, Order(43)] - public async Task StreamGetBranches() - { - var res = await _myClient.StreamGetBranches(_streamId); - - Assert.That(res, Is.Not.Null); - // Branches are now returned in order of creation so 'main' should always go first. - Assert.That(res[0].name, Is.EqualTo("main")); - } - - [Test, Order(51)] - public async Task StreamGetBranches_Throws_WhenRequestingOverLimit() - { - Assert.ThrowsAsync>( - async () => await _myClient.StreamGetBranches(_streamId, ServerLimits.BRANCH_GET_LIMIT + 1) - ); - var res = await _myClient.StreamGetBranches(_streamId, ServerLimits.BRANCH_GET_LIMIT); - - Assert.That(res, Is.Not.Null); - } - - [Test, Order(52)] - public async Task StreamGetBranches_WithManyBranches() - { - var newStreamId = await _myClient.StreamCreate(new StreamCreateInput { name = "Many branches stream" }); - - await CreateEmptyBranches(_myClient, newStreamId, ServerLimits.BRANCH_GET_LIMIT); - - var res = await _myClient.StreamGetBranches(newStreamId, ServerLimits.BRANCH_GET_LIMIT); - - Assert.That(res, Is.Not.Null); - Assert.That(res, Has.Count.EqualTo(ServerLimits.BRANCH_GET_LIMIT)); - } - - private async Task CreateEmptyBranches( - Client client, - string streamId, - int branchCount, - string branchPrefix = "Test branch" - ) - { - // now let's send HTTP requests to each of these URLs in parallel - var options = new ParallelOptions { MaxDegreeOfParallelism = 2 }; - - // now let's send HTTP requests to each of these URLs in parallel - await Parallel.ForEachAsync( - Enumerable.Range(0, branchCount), - options, - async (i, cancellationToken) => - { - await client.BranchCreate( - new BranchCreateInput { name = $"{branchPrefix} {i}", streamId = streamId }, - cancellationToken - ); - } - ); - } - - #region commit - - [Test, Order(43)] - public async Task CommitCreate() - { - var myObject = new Base(); - var ptsList = new List(); - for (int i = 0; i < 100; i++) - { - ptsList.Add(new Point(i, i, i)); - } - - myObject["@Points"] = ptsList; - - (_objectId, _) = await Operations.Send(myObject, new List { _myServerTransport }); - - Assert.That(_objectId, Is.Not.Null); - - var res = await _myClient.CommitCreate( - new CommitCreateInput - { - streamId = _streamId, - branchName = _branchName, - objectId = _objectId, - message = "Fibber Fibbo", - sourceApplication = "Tests", - totalChildrenCount = 100 - } - ); - - Assert.That(res, Is.Not.Null); - _commitId = res; - - var res2 = await _myClient.CommitCreate( - new CommitCreateInput - { - streamId = _streamId, - branchName = _branchName, - objectId = _objectId, - message = "Fabber Fabbo", - sourceApplication = "Tests", - totalChildrenCount = 100, - parents = new List { _commitId } - } - ); - - Assert.That(res2, Is.Not.Null); - _commitId = res2; - } - - [Test, Order(44)] - public async Task CommitGet() - { - var res = await _myClient.CommitGet(_streamId, _commitId); - - Assert.That(res, Is.Not.Null); - Assert.That(res.message, Is.EqualTo("Fabber Fabbo")); - } - - [Test, Order(45)] - public async Task StreamGetCommits() - { - var res = await _myClient.StreamGetCommits(_streamId); - - Assert.That(res, Is.Not.Null); - Assert.That(res[0].id, Is.EqualTo(_commitId)); - } - - #region object - - [Test, Order(45)] - public async Task ObjectGet() - { - var res = await _myClient.ObjectGet(_streamId, _objectId); - - Assert.That(res, Is.Not.Null); - Assert.That(res.totalChildrenCount, Is.EqualTo(100)); - } - - #endregion - - [Test, Order(46)] - public async Task CommitUpdate() - { - var res = await _myClient.CommitUpdate( - new CommitUpdateInput - { - streamId = _streamId, - id = _commitId, - message = "DIM IS DA BEST" - } - ); - - Assert.That(res, Is.True); - } - - [Test, Order(47)] - public async Task CommitReceived() - { - var res = await _myClient.CommitReceived( - new CommitReceivedInput - { - commitId = _commitId, - streamId = _streamId, - sourceApplication = "sharp-tests", - message = "The test message" - } - ); - - Assert.That(res, Is.True); - } - - [Test, Order(48)] - public async Task CommitDelete() - { - var res = await _myClient.CommitDelete(new CommitDeleteInput { id = _commitId, streamId = _streamId }); - Assert.That(res, Is.True); - } - - #endregion - - - [Test, Order(49)] - public async Task BranchUpdate() - { - var res = await _myClient.BranchUpdate( - new BranchUpdateInput - { - streamId = _streamId, - id = _branchId, - name = "sample-branch EDITED" - } - ); - - Assert.That(res, Is.True); - } - - [Test, Order(50)] - public async Task BranchDelete() - { - var res = await _myClient.BranchDelete(new BranchDeleteInput { id = _branchId, streamId = _streamId }); - Assert.That(res, Is.True); - } - - #endregion - - #region send/receive bare - - //[Test, Order(60)] - //public async Task SendDetached() - //{ - // var myObject = new Base(); - // var ptsList = new List(); - // for (int i = 0; i < 100; i++) - // ptsList.Add(new Point(i, i, i)); - - // myObject["@Points"] = ptsList; - - // var otherTransport = new ServerTransport(firstUserAccount, null); - // otherTransport.StreamId = - - // objectId = await Operations.Send(myObject, new List() { myServerTransport }, disposeTransports: true); - //} - - //[Test, Order(61)] - //public async Task ReceiveAndCompose() - //{ - // var myObject = await Operations.Receive(objectId, myServerTransport); - // Assert.NotNull(myObject); - // Assert.AreEqual(100, ((List)myObject["@Points"]).Count); - //} - - #endregion - - public void Dispose() - { - _myClient?.Dispose(); - _secondClient?.Dispose(); - _myServerTransport?.Dispose(); - _otherServerTransport?.Dispose(); - } -} diff --git a/tests/Speckle.Sdk.Tests.Integration/Credentials/UserServerInfoTests.cs b/tests/Speckle.Sdk.Tests.Integration/Credentials/UserServerInfoTests.cs index 7dc9b1a8..782244f4 100644 --- a/tests/Speckle.Sdk.Tests.Integration/Credentials/UserServerInfoTests.cs +++ b/tests/Speckle.Sdk.Tests.Integration/Credentials/UserServerInfoTests.cs @@ -1,4 +1,5 @@ using GraphQL.Client.Http; +using Microsoft.Extensions.DependencyInjection; using Speckle.Sdk.Api.GraphQL.Models; using Speckle.Sdk.Credentials; @@ -8,7 +9,7 @@ public class UserServerInfoTests { private Account _acc; - [OneTimeSetUp] + [SetUp] public async Task Setup() { _acc = await Fixtures.SeedUser(); @@ -17,7 +18,9 @@ public async Task Setup() [Test] public async Task IsFrontEnd2True() { - ServerInfo? result = await AccountManager.GetServerInfo(new("https://app.speckle.systems/")); + ServerInfo? result = await Fixtures + .ServiceProvider.GetRequiredService() + .GetServerInfo(new("https://app.speckle.systems/")); Assert.That(result, Is.Not.Null); Assert.That(result!.frontend2, Is.True); @@ -26,7 +29,9 @@ public async Task IsFrontEnd2True() [Test] public async Task IsFrontEnd2False() { - ServerInfo? result = await AccountManager.GetServerInfo(new("https://speckle.xyz/")); + ServerInfo? result = await Fixtures + .ServiceProvider.GetRequiredService() + .GetServerInfo(new("https://speckle.xyz/")); Assert.That(result, Is.Not.Null); Assert.That(result!.frontend2, Is.False); @@ -43,7 +48,9 @@ public void GetServerInfo_ExpectFail_CantPing() { Uri serverUrl = new(_acc.serverInfo.url); - Assert.ThrowsAsync(async () => await AccountManager.GetServerInfo(serverUrl)); + Assert.ThrowsAsync( + async () => await Fixtures.ServiceProvider.GetRequiredService().GetServerInfo(serverUrl) + ); } [Test] @@ -51,14 +58,18 @@ public void GetServerInfo_ExpectFail_NoServer() { Uri serverUrl = new("http://invalidserver.local"); - Assert.ThrowsAsync(async () => await AccountManager.GetServerInfo(serverUrl)); + Assert.ThrowsAsync( + async () => await Fixtures.ServiceProvider.GetRequiredService().GetServerInfo(serverUrl) + ); } [Test] public async Task GetUserInfo() { Uri serverUrl = new(_acc.serverInfo.url); - UserInfo result = await AccountManager.GetUserInfo(_acc.token, serverUrl); + UserInfo result = await Fixtures + .ServiceProvider.GetRequiredService() + .GetUserInfo(_acc.token, serverUrl); Assert.That(result.id, Is.EqualTo(_acc.userInfo.id)); Assert.That(result.name, Is.EqualTo(_acc.userInfo.name)); @@ -72,7 +83,9 @@ public void GetUserInfo_ExpectFail_NoServer() { Uri serverUrl = new("http://invalidserver.local"); - Assert.ThrowsAsync(async () => await AccountManager.GetUserInfo("", serverUrl)); + Assert.ThrowsAsync( + async () => await Fixtures.ServiceProvider.GetRequiredService().GetUserInfo("", serverUrl) + ); } [Test] @@ -81,7 +94,10 @@ public void GetUserInfo_ExpectFail_NoUser() Uri serverUrl = new(_acc.serverInfo.url); Assert.ThrowsAsync( - async () => await AccountManager.GetUserInfo("Bearer 08913c3c1e7ac65d779d1e1f11b942a44ad9672ca9", serverUrl) + async () => + await Fixtures + .ServiceProvider.GetRequiredService() + .GetUserInfo("Bearer 08913c3c1e7ac65d779d1e1f11b942a44ad9672ca9", serverUrl) ); } } diff --git a/tests/Speckle.Sdk.Tests.Integration/Fixtures.cs b/tests/Speckle.Sdk.Tests.Integration/Fixtures.cs index 45dacf31..32d7403d 100644 --- a/tests/Speckle.Sdk.Tests.Integration/Fixtures.cs +++ b/tests/Speckle.Sdk.Tests.Integration/Fixtures.cs @@ -2,13 +2,16 @@ using System.Net.Mime; using System.Text; using System.Web; +using Microsoft.Extensions.DependencyInjection; using Newtonsoft.Json; using Speckle.Sdk.Api; using Speckle.Sdk.Api.GraphQL.Inputs; using Speckle.Sdk.Api.GraphQL.Models; using Speckle.Sdk.Common; using Speckle.Sdk.Credentials; +using Speckle.Sdk.Host; using Speckle.Sdk.Models; +using Speckle.Sdk.Tests.Unit.Serialisation; using Speckle.Sdk.Transports; namespace Speckle.Sdk.Tests.Integration; @@ -17,17 +20,33 @@ public static class Fixtures { public static readonly ServerInfo Server = new() { url = "http://localhost:3000", name = "Docker Server" }; - public static Client Unauthed => new Client(new Account { serverInfo = Server, userInfo = new UserInfo() }); + public static IServiceProvider ServiceProvider { get; set; } + + static Fixtures() + { + TypeLoader.Reset(); + TypeLoader.Initialize(typeof(Base).Assembly, typeof(IgnoreTest).Assembly); + var serviceCollection = new ServiceCollection(); + serviceCollection.AddSpeckleSdk(HostApplications.Navisworks, HostAppVersion.v2023); + ServiceProvider = serviceCollection.BuildServiceProvider(); + } + + public static Client Unauthed => + ServiceProvider + .GetRequiredService() + .Create(new Account { serverInfo = Server, userInfo = new UserInfo() }); public static async Task SeedUserWithClient() { - return new Client(await SeedUser()); + return ServiceProvider.GetRequiredService().Create(await SeedUser()); } public static async Task CreateVersion(Client client, string projectId, string modelId) { - using ServerTransport remote = new(client.Account, projectId); - var (objectId, _) = await Operations.Send(new() { applicationId = "ASDF" }, remote, false); + using var remote = ServiceProvider.GetRequiredService().Create(client.Account, projectId); + var (objectId, _) = await ServiceProvider + .GetRequiredService() + .Send(new() { applicationId = "ASDF" }, remote, false); CreateVersionInput input = new(objectId, modelId, projectId); return await client.Version.Create(input); } @@ -97,7 +116,9 @@ await tokenResponse.Content.ReadAsStringAsync() serverInfo = Server }; - var user1 = await AccountManager.GetUserInfo(acc.token, new(acc.serverInfo.url)); + var user1 = await ServiceProvider + .GetRequiredService() + .GetUserInfo(acc.token, new(acc.serverInfo.url)); acc.userInfo = user1; return acc; } @@ -149,10 +170,10 @@ internal static async Task CreateComment(Client client, string projectI internal static async Task SendBlobData(Account account, string projectId) { - using ServerTransport remote = new(account, projectId); + using var remote = ServiceProvider.GetRequiredService().Create(account, projectId); var blobs = Fixtures.GenerateThreeBlobs(); Base myObject = new() { ["blobs"] = blobs }; - await Operations.Send(myObject, remote, false); + await ServiceProvider.GetRequiredService().Send(myObject, remote, false); return blobs; } } diff --git a/tests/Speckle.Sdk.Tests.Integration/GraphQLCLient.cs b/tests/Speckle.Sdk.Tests.Integration/GraphQLCLient.cs index 1503c129..3a97db68 100644 --- a/tests/Speckle.Sdk.Tests.Integration/GraphQLCLient.cs +++ b/tests/Speckle.Sdk.Tests.Integration/GraphQLCLient.cs @@ -1,6 +1,9 @@ using GraphQL; +using Microsoft.Extensions.DependencyInjection; using Speckle.Sdk.Api; using Speckle.Sdk.Credentials; +using Speckle.Sdk.Host; +using Speckle.Sdk.Models; namespace Speckle.Sdk.Tests.Integration; @@ -8,12 +11,19 @@ public class GraphQLClientTests : IDisposable { private Account _account; private Client _client; + private IOperations _operations; - [OneTimeSetUp] + [SetUp] public async Task Setup() { + TypeLoader.Reset(); + TypeLoader.Initialize(typeof(Base).Assembly, typeof(DataChunk).Assembly); + var serviceCollection = new ServiceCollection(); + serviceCollection.AddSpeckleSdk(HostApplications.Navisworks, HostAppVersion.v2023); + var serviceProvider = serviceCollection.BuildServiceProvider(); + _operations = serviceProvider.GetRequiredService(); _account = await Fixtures.SeedUser(); - _client = new Client(_account); + _client = serviceProvider.GetRequiredService().Create(_account); } [Test] diff --git a/tests/Speckle.Sdk.Tests.Integration/MemoryTransportTests.cs b/tests/Speckle.Sdk.Tests.Integration/MemoryTransportTests.cs index ab155e91..4168d649 100644 --- a/tests/Speckle.Sdk.Tests.Integration/MemoryTransportTests.cs +++ b/tests/Speckle.Sdk.Tests.Integration/MemoryTransportTests.cs @@ -1,5 +1,6 @@ using System.Collections.Concurrent; using System.Reflection; +using Microsoft.Extensions.DependencyInjection; using Shouldly; using Speckle.Sdk.Api; using Speckle.Sdk.Host; @@ -11,6 +12,7 @@ namespace Speckle.Sdk.Tests.Integration; public class MemoryTransportTests { private readonly MemoryTransport _memoryTransport = new(blobStorageEnabled: true); + private IOperations _operations; [SetUp] public void Setup() @@ -18,6 +20,10 @@ public void Setup() CleanData(); TypeLoader.Reset(); TypeLoader.Initialize(typeof(Base).Assembly, Assembly.GetExecutingAssembly()); + var serviceCollection = new ServiceCollection(); + serviceCollection.AddSpeckleSdk(HostApplications.Navisworks, HostAppVersion.v2023); + var serviceProvider = serviceCollection.BuildServiceProvider(); + _operations = serviceProvider.GetRequiredService(); } [TearDown] @@ -38,12 +44,12 @@ public async Task SendAndReceiveObjectWithBlobs() var myObject = Fixtures.GenerateSimpleObject(); myObject["blobs"] = Fixtures.GenerateThreeBlobs(); - var sendResult = await Operations.Send(myObject, _memoryTransport, false); + var sendResult = await _operations.Send(myObject, _memoryTransport, false); // NOTE: used to debug diffing // await Operations.Send(myObject, new List { transport }); - var receivedObject = await Operations.Receive(sendResult.rootObjId, _memoryTransport, new MemoryTransport()); + var receivedObject = await _operations.Receive(sendResult.rootObjId, _memoryTransport, new MemoryTransport()); var allFiles = Directory .GetFiles(_memoryTransport.BlobStorageFolder) diff --git a/tests/Speckle.Sdk.Tests.Integration/ServerTransportTests.cs b/tests/Speckle.Sdk.Tests.Integration/ServerTransportTests.cs deleted file mode 100644 index 4fb10a19..00000000 --- a/tests/Speckle.Sdk.Tests.Integration/ServerTransportTests.cs +++ /dev/null @@ -1,175 +0,0 @@ -using System.Reflection; -using Shouldly; -using Speckle.Sdk.Api; -using Speckle.Sdk.Credentials; -using Speckle.Sdk.Host; -using Speckle.Sdk.Logging; -using Speckle.Sdk.Models; -using Speckle.Sdk.Transports; - -namespace Speckle.Sdk.Tests.Integration; - -public class ServerTransportTests : IDisposable -{ - private string _basePath; - private Account _account; - private Client _client; - private string _streamId; - private ServerTransport _transport; - - [OneTimeSetUp] - public async Task InitialSetup() - { - _basePath = Path.Join(Path.GetTempPath(), "speckleTest"); - - CleanData(); - Directory.CreateDirectory(_basePath); - SpecklePathProvider.OverrideApplicationDataPath(_basePath); - - _account = await Fixtures.SeedUser(); - _client = new Client(_account); - _streamId = await _client.StreamCreate(new StreamCreateInput { description = "Flobber", name = "Blobber" }); - } - - [SetUp] - public void Setup() - { - CleanData(); - // need to recreate the server transport object for each test - // to make sure all folders are properly initialized - _transport = new ServerTransport(_account, _streamId); - TypeLoader.Reset(); - TypeLoader.Initialize(typeof(Base).Assembly, Assembly.GetExecutingAssembly()); - } - - [TearDown] - public void TearDown() => CleanData(); - - private void CleanData() - { - _transport?.Dispose(); - if (Directory.Exists(_basePath)) - { - Directory.Delete(_basePath, true); - } - Directory.CreateDirectory(_basePath); - } - - [Test] - public async Task SendObject() - { - var myObject = Fixtures.GenerateNestedObject(); - - var objectId = await Operations.Send(myObject, _transport, false); - - Assert.That(objectId, Is.Not.Null); - } - - [Test] - public async Task SendAndReceiveObjectWithBlobs() - { - var myObject = Fixtures.GenerateSimpleObject(); - myObject["@blobs"] = Fixtures.GenerateThreeBlobs(); - - var sendResult = await Operations.Send(myObject, _transport, false); - - // NOTE: used to debug diffing - // await Operations.Send(myObject, new List { transport }); - - var receivedObject = await Operations.Receive(sendResult.rootObjId, _transport, new MemoryTransport()); - - var allFiles = Directory - .GetFiles(_transport.BlobStorageFolder) - .Select(fp => fp.Split(Path.DirectorySeparatorChar).Last()) - .ToList(); - var blobPaths = allFiles - .Where(fp => fp.Length > Blob.LocalHashPrefixLength) // excludes things like .DS_store - .ToList(); - - // Check that there are three downloaded blobs! - Assert.That(blobPaths, Has.Count.EqualTo(3)); - var objectBlobs = receivedObject["@blobs"] as IList; - objectBlobs.ShouldNotBeNull(); - var blobs = objectBlobs.Cast().ToList(); - // Check that we have three blobs - Assert.That(blobs, Has.Count.EqualTo(3)); - // Check that received blobs point to local path (where they were received) - Assert.That(blobs[0].filePath, Contains.Substring(_transport.BlobStorageFolder)); - Assert.That(blobs[1].filePath, Contains.Substring(_transport.BlobStorageFolder)); - Assert.That(blobs[2].filePath, Contains.Substring(_transport.BlobStorageFolder)); - } - - [Test] - public async Task SendWithBlobsWithoutSQLiteSendCache() - { - var myObject = Fixtures.GenerateSimpleObject(); - myObject["@blobs"] = Fixtures.GenerateThreeBlobs(); - - var memTransport = new MemoryTransport(); - var sendResult = await Operations.Send(myObject, new List { _transport, memTransport }); - - var receivedObject = await Operations.Receive(sendResult.rootObjId, _transport, new MemoryTransport()); - - var allFiles = Directory - .GetFiles(_transport.BlobStorageFolder) - .Select(fp => fp.Split(Path.DirectorySeparatorChar).Last()) - .ToList(); - var blobPaths = allFiles - .Where(fp => fp.Length > Blob.LocalHashPrefixLength) // excludes things like .DS_store - .ToList(); - - // Check that there are three downloaded blobs! - Assert.That(blobPaths, Has.Count.EqualTo(3)); - - var objectBlobs = receivedObject["@blobs"] as IList; - objectBlobs.ShouldNotBeNull(); - var blobs = objectBlobs.Cast().ToList(); - // Check that we have three blobs - Assert.That(blobs, Has.Count.EqualTo(3)); - // Check that received blobs point to local path (where they were received) - Assert.That(blobs[0].filePath, Contains.Substring(_transport.BlobStorageFolder)); - Assert.That(blobs[1].filePath, Contains.Substring(_transport.BlobStorageFolder)); - Assert.That(blobs[2].filePath, Contains.Substring(_transport.BlobStorageFolder)); - } - - [Test] - public async Task SendReceiveWithCleanedMemoryCache() - { - var myObject = Fixtures.GenerateSimpleObject(); - myObject["@blobs"] = Fixtures.GenerateThreeBlobs(); - - var memTransport = new MemoryTransport(); - var sendResult = await Operations.Send(myObject, [_transport, memTransport]); - - memTransport = new MemoryTransport(); - Base receivedObject = await Operations.Receive(sendResult.rootObjId, _transport, memTransport); - Assert.That(receivedObject, Is.Not.Null); - - var allFiles = Directory - .GetFiles(_transport.BlobStorageFolder) - .Select(fp => fp.Split(Path.DirectorySeparatorChar).Last()) - .ToList(); - var blobPaths = allFiles - .Where(fp => fp.Length > Blob.LocalHashPrefixLength) // excludes things like .DS_store - .ToList(); - - // Check that there are three downloaded blobs! - Assert.That(blobPaths.Count, Is.EqualTo(3)); - - var objectBlobs = receivedObject["@blobs"] as IList; - objectBlobs.ShouldNotBeNull(); - var blobs = objectBlobs.Cast().ToList(); - // Check that we have three blobs - Assert.That(blobs, Has.Count.EqualTo(3)); - // Check that received blobs point to local path (where they were received) - Assert.That(blobs[0].filePath, Contains.Substring(_transport.BlobStorageFolder)); - Assert.That(blobs[1].filePath, Contains.Substring(_transport.BlobStorageFolder)); - Assert.That(blobs[2].filePath, Contains.Substring(_transport.BlobStorageFolder)); - } - - public void Dispose() - { - _client?.Dispose(); - _transport?.Dispose(); - } -} diff --git a/tests/Speckle.Sdk.Tests.Integration/packages.lock.json b/tests/Speckle.Sdk.Tests.Integration/packages.lock.json index c31c21b1..86eaa41e 100644 --- a/tests/Speckle.Sdk.Tests.Integration/packages.lock.json +++ b/tests/Speckle.Sdk.Tests.Integration/packages.lock.json @@ -121,6 +121,57 @@ "SQLitePCLRaw.core": "2.1.4" } }, + "Microsoft.Extensions.Configuration": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "Lu41BWNmwhKr6LgyQvcYBOge0pPvmiaK8R5UHXX4//wBhonJyWcT2OK1mqYfEM5G7pTf31fPrpIHOT6sN7EGOA==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "3.1.0" + } + }, + "Microsoft.Extensions.Configuration.Abstractions": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "ESz6bVoDQX7sgWdKHF6G9Pq672T8k+19AFb/txDXwdz7MoqaNQj2/in3agm/3qae9V+WvQZH86LLTNVo0it8vQ==", + "dependencies": { + "Microsoft.Extensions.Primitives": "3.1.0" + } + }, + "Microsoft.Extensions.Configuration.Binder": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "o9eELDBfNkR7sUtYysFZ1Q7BQ1mYt27DMkups/3vu7xgPyOpMD+iAfrBZFzUXT2iw0fmFb8s1gfNBZS+IgjKdQ==", + "dependencies": { + "Microsoft.Extensions.Configuration": "3.1.0" + } + }, + "Microsoft.Extensions.DependencyInjection": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "KVkv3aF2MQpmGFRh4xRx2CNbc2sjDFk+lH4ySrjWSOS+XoY1Xc+sJphw3N0iYOpoeCCq8976ceVYDH8sdx2qIQ==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.0" + } + }, + "Microsoft.Extensions.Logging.Abstractions": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "jjo4YXRx6MIpv6DiRxJjSpl+sPP0+5VW0clMEdLyIAz44PPwrDTFrd5PZckIxIXl1kKZ2KK6IL2nkt0+ug2MQg==" + }, + "Microsoft.Extensions.Options": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "9b6JHY7TAXrSfZ6EEGf+j8XnqKIiMPErfmaNXhJYSCb+BUW2H4RtzkNJvwLJzwgzqBP0wtTjyA6Uw4BPPdmkMw==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.0", + "Microsoft.Extensions.Primitives": "3.1.0" + } + }, + "Microsoft.Extensions.Primitives": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "LEKAnX7lhUhSoIc2XraCTK3M4IU/LdVUzCe464Sa4+7F4ZJuXHHRzZli2mDbiT4xzAZhgqXbvfnb5+CNDcQFfg==" + }, "Microsoft.SourceLink.Common": { "type": "Transitive", "resolved": "8.0.0", @@ -212,18 +263,16 @@ "GraphQL.Client": "[6.0.0, )", "Microsoft.CSharp": "[4.7.0, )", "Microsoft.Data.Sqlite": "[7.0.7, )", + "Microsoft.Extensions.DependencyInjection.Abstractions": "[3.1.0, )", + "Microsoft.Extensions.Logging": "[3.1.0, )", "Polly": "[7.2.3, )", "Polly.Contrib.WaitAndRetry": "[1.1.1, )", "Polly.Extensions.Http": "[3.0.0, )", "Speckle.DoubleNumerics": "[4.0.1, )", "Speckle.Newtonsoft.Json": "[13.0.2, )", - "Speckle.Sdk.Logging": "[1.0.0, )", "System.Text.Json": "[5.0.2, )" } }, - "speckle.sdk.logging": { - "type": "Project" - }, "speckle.sdk.tests.unit": { "type": "Project", "dependencies": { @@ -263,6 +312,24 @@ "SQLitePCLRaw.bundle_e_sqlite3": "2.1.4" } }, + "Microsoft.Extensions.DependencyInjection.Abstractions": { + "type": "CentralTransitive", + "requested": "[3.1.0, )", + "resolved": "3.1.0", + "contentHash": "44rDtOf1JXXAFpNT2EXMExaDm/4OJ2RXOL9i9lE4bK427nzC7Exphv+beB6IgluyE2GIoo8zezTStMXI7MQ8WA==" + }, + "Microsoft.Extensions.Logging": { + "type": "CentralTransitive", + "requested": "[3.1.0, )", + "resolved": "3.1.0", + "contentHash": "P+8sKQ8L4ooL79sxxqwFPxGGC3aBrUDLB/dZqhs4J0XjTyrkeeyJQ4D4nzJB6OnAhy78HIIgQ/RbD6upOXLynw==", + "dependencies": { + "Microsoft.Extensions.Configuration.Binder": "3.1.0", + "Microsoft.Extensions.DependencyInjection": "3.1.0", + "Microsoft.Extensions.Logging.Abstractions": "3.1.0", + "Microsoft.Extensions.Options": "3.1.0" + } + }, "Polly": { "type": "CentralTransitive", "requested": "[7.2.3, )", diff --git a/tests/Speckle.Sdk.Tests.Performance/Benchmarks/GeneralDeserializerTest.cs b/tests/Speckle.Sdk.Tests.Performance/Benchmarks/GeneralDeserializerTest.cs index d9cd2a4b..a14ec73c 100644 --- a/tests/Speckle.Sdk.Tests.Performance/Benchmarks/GeneralDeserializerTest.cs +++ b/tests/Speckle.Sdk.Tests.Performance/Benchmarks/GeneralDeserializerTest.cs @@ -1,6 +1,8 @@ using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Engines; +using Microsoft.Extensions.Logging.Abstractions; using Speckle.Objects.Geometry; +using Speckle.Sdk.Credentials; using Speckle.Sdk.Host; using Speckle.Sdk.Models; using Speckle.Sdk.Serialisation; @@ -22,7 +24,14 @@ public async Task Setup() TypeLoader.Initialize(typeof(Base).Assembly, typeof(Point).Assembly); _dataSource = new TestDataHelper(); await _dataSource - .SeedTransport(new("https://latest.speckle.systems/projects/2099ac4b5f/models/da511c4d1e")) + .SeedTransport( + new Account() + { + serverInfo = new() { url = "https://latest.speckle.systems/projects/2099ac4b5f/models/da511c4d1e" } + }, + "2099ac4b5f", + "30fb4cbe6eb2202b9e7b4a4fcc3dd2b6" + ) .ConfigureAwait(false); } @@ -31,7 +40,7 @@ public async Task RunTest() { SpeckleObjectDeserializer sut = new() { ReadTransport = _dataSource.Transport }; string data = await _dataSource.Transport.GetObject(_dataSource.ObjectId)!; - return await sut.DeserializeJsonAsync(data); + return await sut.DeserializeAsync(data); } [GlobalCleanup] diff --git a/tests/Speckle.Sdk.Tests.Performance/Benchmarks/GeneralSerializerTest.cs b/tests/Speckle.Sdk.Tests.Performance/Benchmarks/GeneralSerializerTest.cs index 5fdd0d8c..97a6e6f4 100644 --- a/tests/Speckle.Sdk.Tests.Performance/Benchmarks/GeneralSerializerTest.cs +++ b/tests/Speckle.Sdk.Tests.Performance/Benchmarks/GeneralSerializerTest.cs @@ -1,7 +1,9 @@ using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Engines; +using Microsoft.Extensions.Logging.Abstractions; using Speckle.Objects.Geometry; using Speckle.Sdk.Common; +using Speckle.Sdk.Credentials; using Speckle.Sdk.Host; using Speckle.Sdk.Models; using Speckle.Sdk.Serialisation; @@ -24,20 +26,27 @@ public async Task Setup() TypeLoader.Initialize(typeof(Base).Assembly, typeof(Point).Assembly); using var dataSource = new TestDataHelper(); await dataSource - .SeedTransport(new("https://latest.speckle.systems/projects/2099ac4b5f/models/da511c4d1e")) + .SeedTransport( + new Account() + { + serverInfo = new() { url = "https://latest.speckle.systems/projects/2099ac4b5f/models/da511c4d1e" } + }, + "2099ac4b5f", + "30fb4cbe6eb2202b9e7b4a4fcc3dd2b6" + ) .ConfigureAwait(false); SpeckleObjectDeserializer deserializer = new() { ReadTransport = dataSource.Transport }; string data = await dataSource.Transport.GetObject(dataSource.ObjectId).NotNull(); - _testData = await deserializer.DeserializeJsonAsync(data).NotNull(); + _testData = await deserializer.DeserializeAsync(data).NotNull(); } [Benchmark] - public async Task RunTest() + public string RunTest() { var remote = new NullTransport(); SpeckleObjectSerializer sut = new([remote]); - var x = await sut.SerializeAsync(_testData); + var x = sut.Serialize(_testData); return x; } } diff --git a/tests/Speckle.Sdk.Tests.Performance/Speckle.Sdk.Tests.Performance.csproj b/tests/Speckle.Sdk.Tests.Performance/Speckle.Sdk.Tests.Performance.csproj index 50443113..c72caa14 100644 --- a/tests/Speckle.Sdk.Tests.Performance/Speckle.Sdk.Tests.Performance.csproj +++ b/tests/Speckle.Sdk.Tests.Performance/Speckle.Sdk.Tests.Performance.csproj @@ -11,8 +11,8 @@ - - + + diff --git a/tests/Speckle.Sdk.Tests.Performance/TestDataHelper.cs b/tests/Speckle.Sdk.Tests.Performance/TestDataHelper.cs index 1e3e3e3d..4996ed89 100644 --- a/tests/Speckle.Sdk.Tests.Performance/TestDataHelper.cs +++ b/tests/Speckle.Sdk.Tests.Performance/TestDataHelper.cs @@ -1,6 +1,8 @@ using Microsoft.Data.Sqlite; +using Microsoft.Extensions.DependencyInjection; using Speckle.Sdk.Api; using Speckle.Sdk.Credentials; +using Speckle.Sdk.Host; using Speckle.Sdk.Models; using Speckle.Sdk.Transports; @@ -9,28 +11,32 @@ namespace Speckle.Sdk.Tests.Performance; public sealed class TestDataHelper : IDisposable { private static readonly string s_basePath = $"./temp {Guid.NewGuid()}"; - public SQLiteTransport Transport { get; private set; } + + public static IServiceProvider ServiceProvider { get; set; } public string ObjectId { get; private set; } - public async Task SeedTransport(StreamWrapper sw) + public TestDataHelper() + { + var serviceCollection = new ServiceCollection(); + serviceCollection.AddSpeckleSdk(HostApplications.Navisworks, HostAppVersion.v2023); + ServiceProvider = serviceCollection.BuildServiceProvider(); + } + + public async Task SeedTransport(Account account, string streamId, string objectId) { // Transport = new SQLiteTransport(s_basePath, APPLICATION_NAME); Transport = new SQLiteTransport(); //seed SQLite transport with test data - ObjectId = await SeedTransport(sw, Transport).ConfigureAwait(false); + ObjectId = await SeedTransport(account, streamId, objectId, Transport).ConfigureAwait(false); } - public static async Task SeedTransport(StreamWrapper sw, ITransport transport) + public async Task SeedTransport(Account account, string streamId, string objectId, ITransport transport) { - //seed SQLite transport with test data - var acc = await sw.GetAccount().ConfigureAwait(false); - using var client = new Client(acc); - var branch = await client.BranchGet(sw.StreamId, sw.BranchName!, 1).ConfigureAwait(false); - var objectId = branch.commits.items[0].referencedObject; - - using ServerTransport remoteTransport = new(acc, sw.StreamId); + using ServerTransport remoteTransport = ServiceProvider + .GetRequiredService() + .Create(account, streamId); transport.BeginWrite(); await remoteTransport.CopyObjectAndChildren(objectId, transport).ConfigureAwait(false); transport.EndWrite(); @@ -41,7 +47,10 @@ public static async Task SeedTransport(StreamWrapper sw, ITransport tran public async Task DeserializeBase() { - return await Operations.Receive(ObjectId, null, Transport).ConfigureAwait(false); + return await ServiceProvider + .GetRequiredService() + .Receive(ObjectId, null, Transport) + .ConfigureAwait(false); } public void Dispose() diff --git a/tests/Speckle.Sdk.Tests.Performance/packages.lock.json b/tests/Speckle.Sdk.Tests.Performance/packages.lock.json index 1fdc5aea..974d633a 100644 --- a/tests/Speckle.Sdk.Tests.Performance/packages.lock.json +++ b/tests/Speckle.Sdk.Tests.Performance/packages.lock.json @@ -48,15 +48,6 @@ "resolved": "0.9.6", "contentHash": "HKH7tYrYYlCK1ct483hgxERAdVdMtl7gUKW9ijWXxA1UsYR4Z+TrRHYmzZ9qmpu1NnTycSrp005NYM78GDKV1w==" }, - "Speckle.Objects": { - "type": "Direct", - "requested": "[3.1.0-dev.133, )", - "resolved": "3.1.0-dev.133", - "contentHash": "QXeF4QAFRRGiH04V4z3EjA6Hvyjv3wc3nRwKDm02IUAgHlb8J1RHQIkhPBAXYwv/r2lcmpDMHj87Vzcd7HBSJw==", - "dependencies": { - "Speckle.Sdk": "3.1.0-dev.133" - } - }, "BenchmarkDotNet.Annotations": { "type": "Transitive", "resolved": "0.14.0", @@ -178,66 +169,54 @@ }, "Microsoft.Extensions.Configuration": { "type": "Transitive", - "resolved": "2.1.1", - "contentHash": "LjVKO6P2y52c5ZhTLX/w8zc5H4Y3J/LJsgqTBj49TtFq/hAtVNue/WA0F6/7GMY90xhD7K0MDZ4qpOeWXbLvzg==", + "resolved": "3.1.0", + "contentHash": "Lu41BWNmwhKr6LgyQvcYBOge0pPvmiaK8R5UHXX4//wBhonJyWcT2OK1mqYfEM5G7pTf31fPrpIHOT6sN7EGOA==", "dependencies": { - "Microsoft.Extensions.Configuration.Abstractions": "2.1.1" + "Microsoft.Extensions.Configuration.Abstractions": "3.1.0" } }, "Microsoft.Extensions.Configuration.Abstractions": { "type": "Transitive", - "resolved": "2.1.1", - "contentHash": "VfuZJNa0WUshZ/+8BFZAhwFKiKuu/qOUCFntfdLpHj7vcRnsGHqd3G2Hse78DM+pgozczGM63lGPRLmy+uhUOA==", + "resolved": "3.1.0", + "contentHash": "ESz6bVoDQX7sgWdKHF6G9Pq672T8k+19AFb/txDXwdz7MoqaNQj2/in3agm/3qae9V+WvQZH86LLTNVo0it8vQ==", "dependencies": { - "Microsoft.Extensions.Primitives": "2.1.1" + "Microsoft.Extensions.Primitives": "3.1.0" } }, "Microsoft.Extensions.Configuration.Binder": { "type": "Transitive", - "resolved": "2.1.1", - "contentHash": "fcLCTS03poWE4v9tSNBr3pWn0QwGgAn1vzqHXlXgvqZeOc7LvQNzaWcKRQZTdEc3+YhQKwMsOtm3VKSA2aWQ8w==", + "resolved": "3.1.0", + "contentHash": "o9eELDBfNkR7sUtYysFZ1Q7BQ1mYt27DMkups/3vu7xgPyOpMD+iAfrBZFzUXT2iw0fmFb8s1gfNBZS+IgjKdQ==", "dependencies": { - "Microsoft.Extensions.Configuration": "2.1.1" + "Microsoft.Extensions.Configuration": "3.1.0" } }, - "Microsoft.Extensions.DependencyInjection.Abstractions": { - "type": "Transitive", - "resolved": "2.1.1", - "contentHash": "MgYpU5cwZohUMKKg3sbPhvGG+eAZ/59E9UwPwlrUkyXU+PGzqwZg9yyQNjhxuAWmoNoFReoemeCku50prYSGzA==" - }, - "Microsoft.Extensions.Logging": { + "Microsoft.Extensions.DependencyInjection": { "type": "Transitive", - "resolved": "2.1.1", - "contentHash": "hh+mkOAQDTp6XH80xJt3+wwYVzkbwYQl9XZRCz4Um0JjP/o7N9vHM3rZ6wwwtr+BBe/L6iBO2sz0px6OWBzqZQ==", + "resolved": "3.1.0", + "contentHash": "KVkv3aF2MQpmGFRh4xRx2CNbc2sjDFk+lH4ySrjWSOS+XoY1Xc+sJphw3N0iYOpoeCCq8976ceVYDH8sdx2qIQ==", "dependencies": { - "Microsoft.Extensions.Configuration.Binder": "2.1.1", - "Microsoft.Extensions.DependencyInjection.Abstractions": "2.1.1", - "Microsoft.Extensions.Logging.Abstractions": "2.1.1", - "Microsoft.Extensions.Options": "2.1.1" + "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.0" } }, "Microsoft.Extensions.Logging.Abstractions": { "type": "Transitive", - "resolved": "2.1.1", - "contentHash": "XRzK7ZF+O6FzdfWrlFTi1Rgj2080ZDsd46vzOjadHUB0Cz5kOvDG8vI7caa5YFrsHQpcfn0DxtjS4E46N4FZsA==" + "resolved": "3.1.0", + "contentHash": "jjo4YXRx6MIpv6DiRxJjSpl+sPP0+5VW0clMEdLyIAz44PPwrDTFrd5PZckIxIXl1kKZ2KK6IL2nkt0+ug2MQg==" }, "Microsoft.Extensions.Options": { "type": "Transitive", - "resolved": "2.1.1", - "contentHash": "V7lXCU78lAbzaulCGFKojcCyG8RTJicEbiBkPJjFqiqXwndEBBIehdXRMWEVU3UtzQ1yDvphiWUL9th6/4gJ7w==", + "resolved": "3.1.0", + "contentHash": "9b6JHY7TAXrSfZ6EEGf+j8XnqKIiMPErfmaNXhJYSCb+BUW2H4RtzkNJvwLJzwgzqBP0wtTjyA6Uw4BPPdmkMw==", "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "2.1.1", - "Microsoft.Extensions.Primitives": "2.1.1" + "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.0", + "Microsoft.Extensions.Primitives": "3.1.0" } }, "Microsoft.Extensions.Primitives": { "type": "Transitive", - "resolved": "2.1.1", - "contentHash": "scJ1GZNIxMmjpENh0UZ8XCQ6vzr/LzeF9WvEA51Ix2OQGAs9WPgPu8ABVUdvpKPLuor/t05gm6menJK3PwqOXg==", - "dependencies": { - "System.Memory": "4.5.1", - "System.Runtime.CompilerServices.Unsafe": "4.5.1" - } + "resolved": "3.1.0", + "contentHash": "LEKAnX7lhUhSoIc2XraCTK3M4IU/LdVUzCe464Sa4+7F4ZJuXHHRzZli2mDbiT4xzAZhgqXbvfnb5+CNDcQFfg==" }, "Microsoft.NETCore.Platforms": { "type": "Transitive", @@ -263,28 +242,6 @@ "resolved": "0.3.17", "contentHash": "FQgtCoF2HFwvzKWulAwBS5BGLlh8pgbrJtOp47jyBwh2CW16juVtacN1azOA2BqdrJXkXTNLNRMo7ZlHHiuAnA==" }, - "Speckle.Sdk": { - "type": "Transitive", - "resolved": "3.1.0-dev.133", - "contentHash": "MeQHvdKHcO85JRuq7dyMT6hKnWEoGl0dfDapLgRwVIw4LPiDDtURH6te3teFUPwKP1on4Oo3y2N3dKCidEwsrw==", - "dependencies": { - "GraphQL.Client": "6.0.0", - "Microsoft.CSharp": "4.7.0", - "Microsoft.Data.Sqlite": "7.0.7", - "Polly": "7.2.3", - "Polly.Contrib.WaitAndRetry": "1.1.1", - "Polly.Extensions.Http": "3.0.0", - "Speckle.DoubleNumerics": "4.0.1", - "Speckle.Newtonsoft.Json": "13.0.2", - "Speckle.Sdk.Logging": "3.1.0-dev.133", - "System.Text.Json": "5.0.2" - } - }, - "Speckle.Sdk.Logging": { - "type": "Transitive", - "resolved": "3.1.0-dev.133", - "contentHash": "rStcFXkVGZZ32HQ7zZYC7HMZHRtxxTkCVn92sur852gLVhpOWY3PUPhIyaelx2xItDzv7klEWSXgAdlqfdNOwQ==" - }, "SQLitePCLRaw.bundle_e_sqlite3": { "type": "Transitive", "resolved": "2.1.4", @@ -383,6 +340,28 @@ "resolved": "4.5.4", "contentHash": "zteT+G8xuGu6mS+mzDzYXbzS7rd3K6Fjb9RiZlYlJPam2/hU7JCBZBVEcywNuR+oZ1ncTvc/cq0faRr3P01OVg==" }, + "speckle.objects": { + "type": "Project", + "dependencies": { + "Speckle.Sdk": "[1.0.0, )" + } + }, + "speckle.sdk": { + "type": "Project", + "dependencies": { + "GraphQL.Client": "[6.0.0, )", + "Microsoft.CSharp": "[4.7.0, )", + "Microsoft.Data.Sqlite": "[7.0.7, )", + "Microsoft.Extensions.DependencyInjection.Abstractions": "[3.1.0, )", + "Microsoft.Extensions.Logging": "[3.1.0, )", + "Polly": "[7.2.3, )", + "Polly.Contrib.WaitAndRetry": "[1.1.1, )", + "Polly.Extensions.Http": "[3.0.0, )", + "Speckle.DoubleNumerics": "[4.0.1, )", + "Speckle.Newtonsoft.Json": "[13.0.2, )", + "System.Text.Json": "[5.0.2, )" + } + }, "GraphQL.Client": { "type": "CentralTransitive", "requested": "[6.0.0, )", @@ -410,6 +389,24 @@ "SQLitePCLRaw.bundle_e_sqlite3": "2.1.4" } }, + "Microsoft.Extensions.DependencyInjection.Abstractions": { + "type": "CentralTransitive", + "requested": "[3.1.0, )", + "resolved": "3.1.0", + "contentHash": "44rDtOf1JXXAFpNT2EXMExaDm/4OJ2RXOL9i9lE4bK427nzC7Exphv+beB6IgluyE2GIoo8zezTStMXI7MQ8WA==" + }, + "Microsoft.Extensions.Logging": { + "type": "CentralTransitive", + "requested": "[3.1.0, )", + "resolved": "3.1.0", + "contentHash": "P+8sKQ8L4ooL79sxxqwFPxGGC3aBrUDLB/dZqhs4J0XjTyrkeeyJQ4D4nzJB6OnAhy78HIIgQ/RbD6upOXLynw==", + "dependencies": { + "Microsoft.Extensions.Configuration.Binder": "3.1.0", + "Microsoft.Extensions.DependencyInjection": "3.1.0", + "Microsoft.Extensions.Logging.Abstractions": "3.1.0", + "Microsoft.Extensions.Options": "3.1.0" + } + }, "Polly": { "type": "CentralTransitive", "requested": "[7.2.3, )", diff --git a/tests/Speckle.Sdk.Tests.Unit/Api/GraphQLClient.cs b/tests/Speckle.Sdk.Tests.Unit/Api/GraphQLClient.cs index 535608a8..5c03fb7d 100644 --- a/tests/Speckle.Sdk.Tests.Unit/Api/GraphQLClient.cs +++ b/tests/Speckle.Sdk.Tests.Unit/Api/GraphQLClient.cs @@ -1,10 +1,12 @@ using System.Diagnostics; using GraphQL; +using Microsoft.Extensions.DependencyInjection; using NUnit.Framework; using Speckle.Sdk.Api; using Speckle.Sdk.Api.GraphQL; using Speckle.Sdk.Api.GraphQL.Models; using Speckle.Sdk.Credentials; +using Speckle.Sdk.Host; namespace Speckle.Sdk.Tests.Unit.Api; @@ -16,13 +18,18 @@ public sealed class GraphQLClientTests : IDisposable [OneTimeSetUp] public void Setup() { - _client = new Client( - new Account - { - token = "this is a scam", - serverInfo = new ServerInfo { url = "http://goto.testing" } - } - ); + var serviceCollection = new ServiceCollection(); + serviceCollection.AddSpeckleSdk(HostApplications.Navisworks, HostAppVersion.v2023); + var serviceProvider = serviceCollection.BuildServiceProvider(); + _client = serviceProvider + .GetRequiredService() + .Create( + new Account + { + token = "this is a scam", + serverInfo = new ServerInfo { url = "http://goto.testing" } + } + ); } public void Dispose() diff --git a/tests/Speckle.Sdk.Tests.Unit/Api/HelpersTests.cs b/tests/Speckle.Sdk.Tests.Unit/Api/HelpersTests.cs deleted file mode 100644 index 2ae8fa95..00000000 --- a/tests/Speckle.Sdk.Tests.Unit/Api/HelpersTests.cs +++ /dev/null @@ -1,35 +0,0 @@ -using NUnit.Framework; - -namespace Speckle.Sdk.Tests.Unit.Api; - -[TestFixture] -[TestOf(typeof(Sdk.Api.Helpers))] -public class HelpersTests -{ - [Test] - [TestCase(30, "just now")] - [TestCase(60, "1 minute ago")] - [TestCase(60 * 2, "2 minutes ago")] - [TestCase(60 * 60 * 1, "1 hour ago")] - [TestCase(60 * 60 * 2, "2 hours ago")] - [TestCase(60 * 60 * 24 * 1, "1 day ago")] - [TestCase(60 * 60 * 24 * 2, "2 days ago")] - [TestCase(60 * 60 * 24 * 7 * 1, "1 week ago")] - [TestCase(60 * 60 * 24 * 7 * 2, "2 weeks ago")] - [TestCase(60 * 60 * 24 * 31 * 1, "1 month ago")] - [TestCase(60 * 60 * 24 * 31 * 2, "2 months ago")] - [TestCase(60 * 60 * 24 * 365 * 1, "1 year ago")] - [TestCase(60 * 60 * 24 * 365 * 2, "2 years ago")] - public void TimeAgo_DisplaysTextCorrectly(int secondsAgo, string expectedText) - { - // Get current time and subtract the input amount - var dateTime = DateTime.UtcNow; - - dateTime = dateTime.Subtract(new TimeSpan(0, 0, secondsAgo)); - - // Get the timeAgo text representation - var actual = Sdk.Api.Helpers.TimeAgo(dateTime); - - Assert.That(actual, Is.EqualTo(expectedText)); - } -} diff --git a/tests/Speckle.Sdk.Tests.Unit/Api/Operations/ClosureTests.cs b/tests/Speckle.Sdk.Tests.Unit/Api/Operations/ClosureTests.cs index a8a3e98b..435f149a 100644 --- a/tests/Speckle.Sdk.Tests.Unit/Api/Operations/ClosureTests.cs +++ b/tests/Speckle.Sdk.Tests.Unit/Api/Operations/ClosureTests.cs @@ -1,5 +1,7 @@ +using Microsoft.Extensions.DependencyInjection; using Newtonsoft.Json; using NUnit.Framework; +using Speckle.Sdk.Api; using Speckle.Sdk.Common; using Speckle.Sdk.Host; using Speckle.Sdk.Models; @@ -12,11 +14,17 @@ namespace Speckle.Sdk.Tests.Unit.Api.Operations; [TestOf(typeof(Sdk.Api.Operations))] public class Closures { + private IOperations _operations; + [SetUp] public void Setup() { TypeLoader.Reset(); TypeLoader.Initialize(typeof(Base).Assembly, typeof(TableLegFixture).Assembly); + var serviceCollection = new ServiceCollection(); + serviceCollection.AddSpeckleSdk(HostApplications.Navisworks, HostAppVersion.v2023); + var serviceProvider = serviceCollection.BuildServiceProvider(); + _operations = serviceProvider.GetRequiredService(); } [Test(Description = "Checks whether closures are generated correctly by the serialiser.")] @@ -45,9 +53,9 @@ public async Task CorrectDecompositionTracking() var transport = new MemoryTransport(); - var sendResult = await Sdk.Api.Operations.Send(d1, transport, false); + var sendResult = await _operations.Send(d1, transport, false); - var test = await Sdk.Api.Operations.Receive(sendResult.rootObjId, localTransport: transport); + var test = await _operations.Receive(sendResult.rootObjId, localTransport: transport); test.id.NotNull(); Assert.That(d1.GetId(true), Is.EqualTo(test.id)); diff --git a/tests/Speckle.Sdk.Tests.Unit/Api/Operations/OperationsReceiveTests.Exceptional.cs b/tests/Speckle.Sdk.Tests.Unit/Api/Operations/OperationsReceiveTests.Exceptional.cs index 3acafdd7..14caa794 100644 --- a/tests/Speckle.Sdk.Tests.Unit/Api/Operations/OperationsReceiveTests.Exceptional.cs +++ b/tests/Speckle.Sdk.Tests.Unit/Api/Operations/OperationsReceiveTests.Exceptional.cs @@ -1,4 +1,8 @@ -using NUnit.Framework; +using Microsoft.Extensions.DependencyInjection; +using NUnit.Framework; +using Speckle.Sdk.Api; +using Speckle.Sdk.Host; +using Speckle.Sdk.Models; using Speckle.Sdk.Transports; namespace Speckle.Sdk.Tests.Unit.Api.Operations; @@ -12,7 +16,7 @@ public void Receive_ObjectsDontExist_ExceptionThrown(string id) MemoryTransport emptyTransport2 = new(); Assert.ThrowsAsync(async () => { - await Sdk.Api.Operations.Receive(id, emptyTransport1, emptyTransport2); + await _operations.Receive(id, emptyTransport1, emptyTransport2); }); } @@ -22,7 +26,7 @@ public void Receive_ObjectsDontExistNullRemote_ExceptionThrown(string id) MemoryTransport emptyTransport = new(); Assert.ThrowsAsync(async () => { - await Sdk.Api.Operations.Receive(id, null, emptyTransport); + await _operations.Receive(id, null, emptyTransport); }); } @@ -35,7 +39,7 @@ public void Receive_OperationCanceled_ExceptionThrown(string id) MemoryTransport emptyTransport2 = new(); Assert.CatchAsync(async () => { - await Sdk.Api.Operations.Receive(id, _testCaseTransport, emptyTransport2, cancellationToken: ctc.Token); + await _operations.Receive(id, _testCaseTransport, emptyTransport2, cancellationToken: ctc.Token); }); } } diff --git a/tests/Speckle.Sdk.Tests.Unit/Api/Operations/OperationsReceiveTests.cs b/tests/Speckle.Sdk.Tests.Unit/Api/Operations/OperationsReceiveTests.cs index a387a5ca..45da12d4 100644 --- a/tests/Speckle.Sdk.Tests.Unit/Api/Operations/OperationsReceiveTests.cs +++ b/tests/Speckle.Sdk.Tests.Unit/Api/Operations/OperationsReceiveTests.cs @@ -1,5 +1,7 @@ using System.Reflection; +using Microsoft.Extensions.DependencyInjection; using NUnit.Framework; +using Speckle.Sdk.Api; using Speckle.Sdk.Host; using Speckle.Sdk.Models; using Speckle.Sdk.Transports; @@ -10,6 +12,7 @@ namespace Speckle.Sdk.Tests.Unit.Api.Operations; public sealed partial class OperationsReceiveTests { private static readonly Base[] s_testObjects; + private IOperations _operations; static OperationsReceiveTests() { @@ -49,20 +52,31 @@ private static void Reset() public async Task GlobalSetup() { Reset(); + var serviceCollection = new ServiceCollection(); + serviceCollection.AddSpeckleSdk(HostApplications.Navisworks, HostAppVersion.v2023); + var serviceProvider = serviceCollection.BuildServiceProvider(); + _operations = serviceProvider.GetRequiredService(); _testCaseTransport = new MemoryTransport(); foreach (var b in s_testObjects) { - await Sdk.Api.Operations.Send(b, _testCaseTransport, false); + await _operations.Send(b, _testCaseTransport, false); } } [SetUp] - public void Setup() => Reset(); + public void Setup() + { + Reset(); + var serviceCollection = new ServiceCollection(); + serviceCollection.AddSpeckleSdk(HostApplications.Navisworks, HostAppVersion.v2023); + var serviceProvider = serviceCollection.BuildServiceProvider(); + _operations = serviceProvider.GetRequiredService(); + } [Test, TestCaseSource(nameof(TestCases))] public async Task Receive_FromLocal_ExistingObjects(string id) { - Base result = await Sdk.Api.Operations.Receive(id, null, _testCaseTransport); + Base result = await _operations.Receive(id, null, _testCaseTransport); Assert.That(result.id, Is.EqualTo(id)); } @@ -71,7 +85,7 @@ public async Task Receive_FromLocal_ExistingObjects(string id) public async Task Receive_FromRemote_ExistingObjects(string id) { MemoryTransport localTransport = new(); - Base result = await Sdk.Api.Operations.Receive(id, _testCaseTransport, localTransport); + Base result = await _operations.Receive(id, _testCaseTransport, localTransport); Assert.That(result.id, Is.EqualTo(id)); } @@ -80,7 +94,7 @@ public async Task Receive_FromRemote_ExistingObjects(string id) public async Task Receive_FromLocal_OnProgressActionCalled(string id) { bool wasCalled = false; - _ = await Sdk.Api.Operations.Receive(id, null, _testCaseTransport, onProgressAction: _ => wasCalled = true); + _ = await _operations.Receive(id, null, _testCaseTransport, onProgressAction: _ => wasCalled = true); Assert.That(wasCalled, Is.True); } @@ -90,7 +104,7 @@ public async Task Receive_FromLocal_OnTotalChildrenCountKnownCalled(string id) { bool wasCalled = false; int children = 0; - var result = await Sdk.Api.Operations.Receive( + var result = await _operations.Receive( id, null, _testCaseTransport, diff --git a/tests/Speckle.Sdk.Tests.Unit/Api/Operations/SendObjectReferences.cs b/tests/Speckle.Sdk.Tests.Unit/Api/Operations/SendObjectReferences.cs index 77e0b63e..0c37deb5 100644 --- a/tests/Speckle.Sdk.Tests.Unit/Api/Operations/SendObjectReferences.cs +++ b/tests/Speckle.Sdk.Tests.Unit/Api/Operations/SendObjectReferences.cs @@ -1,4 +1,7 @@ -using NUnit.Framework; +using Microsoft.Extensions.DependencyInjection; +using NUnit.Framework; +using Speckle.Sdk.Api; +using Speckle.Sdk.Host; using Speckle.Sdk.Models; using Speckle.Sdk.Transports; @@ -6,6 +9,19 @@ namespace Speckle.Sdk.Tests.Unit.Api.Operations; public class SendObjectReferences { + private IOperations _operations; + + [SetUp] + public void Setup() + { + TypeLoader.Reset(); + TypeLoader.Initialize(typeof(Base).Assembly, typeof(DataChunk).Assembly); + var serviceCollection = new ServiceCollection(); + serviceCollection.AddSpeckleSdk(HostApplications.Navisworks, HostAppVersion.v2023); + var serviceProvider = serviceCollection.BuildServiceProvider(); + _operations = serviceProvider.GetRequiredService(); + } + [TestCase(0)] [TestCase(1)] [TestCase(10)] @@ -13,7 +29,7 @@ public async Task SendObjectsWithApplicationIds(int testDepth) { Base testData = GenerateTestCase(testDepth, true); MemoryTransport transport = new(); - var result = await Speckle.Sdk.Api.Operations.Send(testData, [transport]); + var result = await _operations.Send(testData, [transport]); Assert.That(result.rootObjId, Is.Not.Null); Assert.That(result.rootObjId, Has.Length.EqualTo(32)); @@ -28,7 +44,7 @@ public async Task SendObjectsWithoutApplicationIds(int testDepth) { Base testData = GenerateTestCase(testDepth, false); MemoryTransport transport = new(); - var result = await Speckle.Sdk.Api.Operations.Send(testData, [transport]); + var result = await _operations.Send(testData, [transport]); Assert.That(result.rootObjId, Is.Not.Null); Assert.That(result.rootObjId, Has.Length.EqualTo(32)); diff --git a/tests/Speckle.Sdk.Tests.Unit/Api/Operations/SendReceiveLocal.cs b/tests/Speckle.Sdk.Tests.Unit/Api/Operations/SendReceiveLocal.cs index ba2f3c95..41df6898 100644 --- a/tests/Speckle.Sdk.Tests.Unit/Api/Operations/SendReceiveLocal.cs +++ b/tests/Speckle.Sdk.Tests.Unit/Api/Operations/SendReceiveLocal.cs @@ -1,5 +1,7 @@ using System.Collections.Concurrent; +using Microsoft.Extensions.DependencyInjection; using NUnit.Framework; +using Speckle.Sdk.Api; using Speckle.Sdk.Common; using Speckle.Sdk.Host; using Speckle.Sdk.Models; @@ -11,11 +13,17 @@ namespace Speckle.Sdk.Tests.Unit.Api.Operations; [TestFixture] public sealed class SendReceiveLocal : IDisposable { + private IOperations _operations; + [SetUp] public void Setup() { TypeLoader.Reset(); TypeLoader.Initialize(typeof(Base).Assembly, typeof(Point).Assembly); + var serviceCollection = new ServiceCollection(); + serviceCollection.AddSpeckleSdk(HostApplications.Navisworks, HostAppVersion.v2023); + var serviceProvider = serviceCollection.BuildServiceProvider(); + _operations = serviceProvider.GetRequiredService(); } private string? _objId01; @@ -41,7 +49,7 @@ public async Task LocalUpload() } using SQLiteTransport localTransport = new(); - (_objId01, var references) = await Sdk.Api.Operations.Send(myObject, localTransport, false); + (_objId01, var references) = await _operations.Send(myObject, localTransport, false); Assert.That(_objId01, Is.Not.Null); Assert.That(references, Has.Count.EqualTo(NUM_OBJECTS)); @@ -52,7 +60,7 @@ public async Task LocalUpload() [Test(Description = "Pulling a commit locally"), Order(2)] public async Task LocalDownload() { - var commitPulled = await Sdk.Api.Operations.Receive(_objId01.NotNull()); + var commitPulled = await _operations.Receive(_objId01.NotNull()); Assert.That(((List)commitPulled["@items"].NotNull())[0], Is.TypeOf()); Assert.That(((List)commitPulled["@items"].NotNull()), Has.Count.EqualTo(NUM_OBJECTS)); @@ -73,9 +81,9 @@ public async Task LocalUploadDownload() ); } - (_objId01, _) = await Sdk.Api.Operations.Send(myObject, _sut, false); + (_objId01, _) = await _operations.Send(myObject, _sut, false); - var commitPulled = await Sdk.Api.Operations.Receive(_objId01); + var commitPulled = await _operations.Receive(_objId01); List items = (List)commitPulled["@items"].NotNull(); Assert.That(items, Has.All.TypeOf()); @@ -97,12 +105,12 @@ public async Task LocalUploadDownloadSmall() ); } - (_objId01, _) = await Sdk.Api.Operations.Send(myObject, _sut, false); + (_objId01, _) = await _operations.Send(myObject, _sut, false); Assert.That(_objId01, Is.Not.Null); TestContext.Out.WriteLine($"Written {NUM_OBJECTS + 1} objects. Commit id is {_objId01}"); - var objsPulled = await Sdk.Api.Operations.Receive(_objId01); + var objsPulled = await _operations.Receive(_objId01); Assert.That(((List)objsPulled["@items"].NotNull()), Has.Count.EqualTo(30)); } @@ -121,11 +129,11 @@ public async Task LocalUploadDownloadListDic() myObject["@dictionary"] = myDic; myObject["@list"] = myList; - (_objId01, _) = await Sdk.Api.Operations.Send(myObject, _sut, false); + (_objId01, _) = await _operations.Send(myObject, _sut, false); Assert.That(_objId01, Is.Not.Null); - var objsPulled = await Sdk.Api.Operations.Receive(_objId01); + var objsPulled = await _operations.Receive(_objId01); Assert.That( ((List)((Dictionary)objsPulled["@dictionary"].NotNull())["a"]).First(), Is.EqualTo(1) @@ -159,12 +167,12 @@ public async Task UploadDownloadNonCommitObject() ((List)((dynamic)obj)["@LayerC"]).Add(new Point(i, i, i + rand.NextDouble()) { applicationId = i + "baz" }); } - (_objId01, _) = await Sdk.Api.Operations.Send(obj, _sut, false); + (_objId01, _) = await _operations.Send(obj, _sut, false); Assert.That(_objId01, Is.Not.Null); TestContext.Out.WriteLine($"Written {NUM_OBJECTS + 1} objects. Commit id is {_objId01}"); - var objPulled = await Sdk.Api.Operations.Receive(_objId01); + var objPulled = await _operations.Receive(_objId01); Assert.That(objPulled, Is.TypeOf()); @@ -197,7 +205,7 @@ public async Task UploadProgressReports() } ConcurrentBag? progress = null; - (_commitId02, _) = await Sdk.Api.Operations.Send( + (_commitId02, _) = await _operations.Send( myObject, _sut, false, @@ -214,7 +222,7 @@ public async Task UploadProgressReports() public async Task DownloadProgressReports() { ConcurrentBag? progress = null; - await Sdk.Api.Operations.Receive( + await _operations.Receive( _commitId02.NotNull(), onProgressAction: dict => { @@ -232,11 +240,11 @@ public async Task ShouldNotDisposeTransports() @base["test"] = "the best"; SQLiteTransport myLocalTransport = new(); - var sendResult = await Sdk.Api.Operations.Send(@base, myLocalTransport, false); - await Sdk.Api.Operations.Send(@base, myLocalTransport, false); + var sendResult = await _operations.Send(@base, myLocalTransport, false); + await _operations.Send(@base, myLocalTransport, false); - _ = await Sdk.Api.Operations.Receive(sendResult.rootObjId, null, myLocalTransport); - await Sdk.Api.Operations.Receive(sendResult.rootObjId, null, myLocalTransport); + _ = await _operations.Receive(sendResult.rootObjId, null, myLocalTransport); + await _operations.Receive(sendResult.rootObjId, null, myLocalTransport); } public void Dispose() diff --git a/tests/Speckle.Sdk.Tests.Unit/Api/Operations/SerializationTests.cs b/tests/Speckle.Sdk.Tests.Unit/Api/Operations/SerializationTests.cs index 2f66279b..3e5f2a1d 100644 --- a/tests/Speckle.Sdk.Tests.Unit/Api/Operations/SerializationTests.cs +++ b/tests/Speckle.Sdk.Tests.Unit/Api/Operations/SerializationTests.cs @@ -1,5 +1,9 @@ using System.Drawing; +using Microsoft.Extensions.DependencyInjection; using NUnit.Framework; +using Speckle.Sdk.Api; +using Speckle.Sdk.Api.GraphQL.Models; +using Speckle.Sdk.Credentials; using Speckle.Sdk.Host; using Speckle.Sdk.Models; using Speckle.Sdk.Tests.Unit.Host; @@ -11,11 +15,17 @@ namespace Speckle.Sdk.Tests.Unit.Api.Operations; [TestOf(typeof(Sdk.Api.Operations))] public class ObjectSerialization { + private IOperations _operations; + [SetUp] public void Setup() { TypeLoader.Reset(); TypeLoader.Initialize(typeof(Base).Assembly, typeof(DataChunk).Assembly, typeof(ColorMock).Assembly); + var serviceCollection = new ServiceCollection(); + serviceCollection.AddSpeckleSdk(HostApplications.Navisworks, HostAppVersion.v2023); + var serviceProvider = serviceCollection.BuildServiceProvider(); + _operations = serviceProvider.GetRequiredService(); } [Test] @@ -24,9 +34,9 @@ public async Task IgnoreCircularReferences() var pt = new Point(1, 2, 3); pt["circle"] = pt; - var test = Sdk.Api.Operations.Serialize(pt); + var test = _operations.Serialize(pt); - var result = await Sdk.Api.Operations.DeserializeAsync(test); + var result = await _operations.DeserializeAsync(test); var circle = result["circle"]; Assert.That(circle, Is.Null); } @@ -63,9 +73,9 @@ public async Task InterfacePropHandling() cat.Fur[i] = new Line { Start = new Point(i, i, i), End = new Point(i + 3.14, i + 3.14, i + 3.14) }; } - var result = Sdk.Api.Operations.Serialize(cat); + var result = _operations.Serialize(cat); - var deserialisedFeline = await Sdk.Api.Operations.DeserializeAsync(result); + var deserialisedFeline = await _operations.DeserializeAsync(result); Assert.That(deserialisedFeline.GetId(), Is.EqualTo(cat.GetId())); // If we're getting the same hash... we're probably fine! } @@ -81,8 +91,8 @@ public async Task InheritanceTests() W = 42 }; - var str = Sdk.Api.Operations.Serialize(superPoint); - var sstr = await Sdk.Api.Operations.DeserializeAsync(str); + var str = _operations.Serialize(superPoint); + var sstr = await _operations.DeserializeAsync(str); Assert.That(sstr.speckle_type, Is.EqualTo(superPoint.speckle_type)); } @@ -100,8 +110,8 @@ public async Task ListDynamicProp() point["test"] = test; - var str = Sdk.Api.Operations.Serialize(point); - var dsrls = await Sdk.Api.Operations.DeserializeAsync(str); + var str = _operations.Serialize(point); + var dsrls = await _operations.DeserializeAsync(str); var list = dsrls["test"] as List; // NOTE: on dynamically added lists, we cannot infer the inner type and we always fall back to a generic list. Assert.That(list, Has.Count.EqualTo(100)); @@ -128,13 +138,13 @@ public async Task ChunkSerialisation() doubleBasedChunk.data.Add(i + 0.33); } - var baseChunkString = Sdk.Api.Operations.Serialize(baseBasedChunk); - var stringChunkString = Sdk.Api.Operations.Serialize(stringBasedChunk); - var doubleChunkString = Sdk.Api.Operations.Serialize(doubleBasedChunk); + var baseChunkString = _operations.Serialize(baseBasedChunk); + var stringChunkString = _operations.Serialize(stringBasedChunk); + var doubleChunkString = _operations.Serialize(doubleBasedChunk); - var baseChunkDeserialised = (DataChunk)await Sdk.Api.Operations.DeserializeAsync(baseChunkString); - var stringChunkDeserialised = (DataChunk)await Sdk.Api.Operations.DeserializeAsync(stringChunkString); - var doubleChunkDeserialised = (DataChunk)await Sdk.Api.Operations.DeserializeAsync(doubleChunkString); + var baseChunkDeserialised = (DataChunk)await _operations.DeserializeAsync(baseChunkString); + var stringChunkDeserialised = (DataChunk)await _operations.DeserializeAsync(stringChunkString); + var doubleChunkDeserialised = (DataChunk)await _operations.DeserializeAsync(doubleChunkString); Assert.That(baseChunkDeserialised.data, Has.Count.EqualTo(baseBasedChunk.data.Count)); Assert.That(stringChunkDeserialised.data, Has.Count.EqualTo(stringBasedChunk.data.Count)); @@ -163,8 +173,8 @@ public async Task ObjectWithChunksSerialisation() mesh["@(800)CustomChunk"] = customChunk; mesh["@()DefaultChunk"] = defaultChunk; - var serialised = Sdk.Api.Operations.Serialize(mesh); - var deserialised = await Sdk.Api.Operations.DeserializeAsync(serialised); + var serialised = _operations.Serialize(mesh); + var deserialised = await _operations.DeserializeAsync(serialised); Assert.That(mesh.GetId(), Is.EqualTo(deserialised.GetId())); } @@ -184,7 +194,7 @@ public void EmptyListSerialisationTests() test["nestedList"] = new List { new List { new List() } }; test["@nestedDetachableList"] = new List { new List { new List() } }; - var serialised = Sdk.Api.Operations.Serialize(test); + var serialised = _operations.Serialize(test); var isCorrect = serialised.Contains("\"@(5)emptyChunks\":[]") && serialised.Contains("\"emptyList\":[]") @@ -207,8 +217,8 @@ public async Task DateSerialisation() var date = new DateTime(2020, 1, 14); var mockBase = new DateMock { TestField = date }; - var result = Sdk.Api.Operations.Serialize(mockBase); - var test = (DateMock)await Sdk.Api.Operations.DeserializeAsync(result); + var result = _operations.Serialize(mockBase); + var test = (DateMock)await _operations.DeserializeAsync(result); Assert.That(test.TestField, Is.EqualTo(date)); } @@ -225,8 +235,8 @@ public async Task GuidSerialisation() var guid = Guid.NewGuid(); var mockBase = new GUIDMock { TestField = guid }; - var result = Sdk.Api.Operations.Serialize(mockBase); - var test = (GUIDMock)await Sdk.Api.Operations.DeserializeAsync(result); + var result = _operations.Serialize(mockBase); + var test = (GUIDMock)await _operations.DeserializeAsync(result); Assert.That(test.TestField, Is.EqualTo(guid)); } @@ -243,8 +253,8 @@ public async Task ColorSerialisation() var color = Color.FromArgb(255, 4, 126, 251); var mockBase = new ColorMock { TestField = color }; - var result = Sdk.Api.Operations.Serialize(mockBase); - var test = (ColorMock)await Sdk.Api.Operations.DeserializeAsync(result); + var result = _operations.Serialize(mockBase); + var test = (ColorMock)await _operations.DeserializeAsync(result); Assert.That(test.TestField, Is.EqualTo(color)); } @@ -260,8 +270,8 @@ public async Task StringDateTimeRegression() { var mockBase = new StringDateTimeRegressionMock { TestField = "2021-11-12T11:32:01" }; - var result = Sdk.Api.Operations.Serialize(mockBase); - var test = (StringDateTimeRegressionMock)await Sdk.Api.Operations.DeserializeAsync(result); + var result = _operations.Serialize(mockBase); + var test = (StringDateTimeRegressionMock)await _operations.DeserializeAsync(result); Assert.That(test.TestField, Is.EqualTo(mockBase.TestField)); } diff --git a/tests/Speckle.Sdk.Tests.Unit/Credentials/AccountServerMigrationTests.cs b/tests/Speckle.Sdk.Tests.Unit/Credentials/AccountServerMigrationTests.cs index 6f153240..52f11c3c 100644 --- a/tests/Speckle.Sdk.Tests.Unit/Credentials/AccountServerMigrationTests.cs +++ b/tests/Speckle.Sdk.Tests.Unit/Credentials/AccountServerMigrationTests.cs @@ -1,6 +1,8 @@ +using Microsoft.Extensions.DependencyInjection; using NUnit.Framework; using Speckle.Sdk.Api.GraphQL.Models; using Speckle.Sdk.Credentials; +using Speckle.Sdk.Host; namespace Speckle.Sdk.Tests.Unit.Credentials; @@ -40,8 +42,11 @@ public static IEnumerable MigrationTestCase() public void TestServerMigration(IList accounts, string requestedUrl, IList expectedSequence) { AddAccounts(accounts); + var serviceCollection = new ServiceCollection(); + serviceCollection.AddSpeckleSdk(HostApplications.Navisworks, HostAppVersion.v2023); + var serviceProvider = serviceCollection.BuildServiceProvider(); - var result = AccountManager.GetAccounts(requestedUrl).ToList(); + var result = serviceProvider.GetRequiredService().GetAccounts(requestedUrl).ToList(); Assert.That(result, Is.EquivalentTo(expectedSequence)); } diff --git a/tests/Speckle.Sdk.Tests.Unit/Credentials/Accounts.cs b/tests/Speckle.Sdk.Tests.Unit/Credentials/Accounts.cs index fafa8808..3706cc36 100644 --- a/tests/Speckle.Sdk.Tests.Unit/Credentials/Accounts.cs +++ b/tests/Speckle.Sdk.Tests.Unit/Credentials/Accounts.cs @@ -1,12 +1,17 @@ +using Microsoft.Extensions.DependencyInjection; using NUnit.Framework; +using Speckle.Sdk.Api; using Speckle.Sdk.Api.GraphQL.Models; using Speckle.Sdk.Credentials; +using Speckle.Sdk.Host; namespace Speckle.Sdk.Tests.Unit.Credentials; [TestFixture] public class CredentialInfrastructure { + private IAccountManager _accountManager; + [OneTimeSetUp] public static void SetUp() { @@ -43,6 +48,15 @@ public static void SetUp() Fixtures.SaveLocalAccount(s_testAccount3); } + [SetUp] + public void Setup2() + { + var serviceCollection = new ServiceCollection(); + serviceCollection.AddSpeckleSdk(HostApplications.Navisworks, HostAppVersion.v2023); + var serviceProvider = serviceCollection.BuildServiceProvider(); + _accountManager = serviceProvider.GetRequiredService(); + } + [OneTimeTearDown] public static void TearDown() { @@ -58,14 +72,14 @@ public static void TearDown() [Test] public void GetAllAccounts() { - var accs = AccountManager.GetAccounts().ToList(); + var accs = _accountManager.GetAccounts().ToList(); Assert.That(accs, Has.Count.GreaterThanOrEqualTo(3)); // Tests are adding three accounts, you might have extra accounts on your machine when testing :D } [Test] public void GetAccount_ById() { - var result = AccountManager.GetAccount(s_testAccount1.id); + var result = _accountManager.GetAccount(s_testAccount1.id); Assert.That(result, Is.EqualTo(s_testAccount1)); } @@ -73,7 +87,7 @@ public void GetAccount_ById() [Test] public void GetAccount_ById_ThrowsWhenNotFound() { - Assert.Throws(() => AccountManager.GetAccount("Non_existent_id")); + Assert.Throws(() => _accountManager.GetAccount("Non_existent_id")); } public static IEnumerable TestCases() @@ -86,7 +100,7 @@ public static IEnumerable TestCases() [TestCaseSource(nameof(TestCases))] public void GetAccountsForServer(Account target) { - var accs = AccountManager.GetAccounts(target.serverInfo.url).ToList(); + var accs = _accountManager.GetAccounts(target.serverInfo.url).ToList(); Assert.That(accs, Has.Count.EqualTo(1)); diff --git a/tests/Speckle.Sdk.Tests.Unit/Credentials/FE2WrapperTests.cs b/tests/Speckle.Sdk.Tests.Unit/Credentials/FE2WrapperTests.cs deleted file mode 100644 index cd7bba65..00000000 --- a/tests/Speckle.Sdk.Tests.Unit/Credentials/FE2WrapperTests.cs +++ /dev/null @@ -1,68 +0,0 @@ -using NUnit.Framework; -using Speckle.Sdk.Credentials; -using Speckle.Sdk.Logging; - -namespace Speckle.Sdk.Tests.Unit.Credentials; - -[TestFixture] -[TestOf(typeof(StreamWrapper))] -public class Fe2WrapperTests -{ - [TestCase( - "https://latest.speckle.systems/projects/92b620fb17/models/76fd8a01c8", - StreamWrapperType.Branch, - "92b620fb17", - "76fd8a01c8" - )] - [TestCase( - "https://latest.speckle.systems/projects/92b620fb17/models/76fd8a01c8@7dc324e4bb", - StreamWrapperType.Commit, - "92b620fb17", - "76fd8a01c8", - "7dc324e4bb" - )] - [TestCase( - "https://latest.speckle.systems/projects/92b620fb17/models/bdd52d7fd174328a080770e2a7fef98a", - StreamWrapperType.Object, - "92b620fb17", - null, - null, - "bdd52d7fd174328a080770e2a7fef98a" - )] - public void ParseFe2Links( - string url, - StreamWrapperType expectedType, - string expectedProjectId, - string? expectedBranchId = null, - string? expectedCommitId = null, - string? expectedObjectId = null - ) - { - var streamWrapper = new StreamWrapper(url); - Assert.That(streamWrapper, Is.Not.Null); - Assert.That(streamWrapper.Type, Is.EqualTo(expectedType)); - Assert.That(streamWrapper.StreamId, Is.EqualTo(expectedProjectId)); - Assert.That(streamWrapper.BranchName, Is.EqualTo(expectedBranchId)); - Assert.That(streamWrapper.CommitId, Is.EqualTo(expectedCommitId)); - Assert.That(streamWrapper.ObjectId, Is.EqualTo(expectedObjectId)); - } - - [TestCase("https://latest.speckle.systems/projects/92b620fb17/models/all")] - [TestCase("https://latest.speckle.systems/projects/92b620fb17/models/0fe8ca21c0,76fd8a01c8")] - [TestCase("https://latest.speckle.systems/projects/92b620fb17/models/A,76fd8a01c8@7dc324e4bb,B@C,D@E,F")] - public void ParseFe2NotSupportedLinks(string url) - { - Assert.Throws(() => new StreamWrapper(url)); - } - - [TestCase("https://latest.speckle.systems/")] - [TestCase("https://latest.speckle.systems/projects")] - [TestCase("https://latest.speckle.systems/projects/")] - [TestCase("https://latest.speckle.systems/projects/92b620fb17")] - [TestCase("https://latest.speckle.systems/projects/92b620fb17/")] - [TestCase("https://latest.speckle.systems/projects/92b620fb17/models/")] - public void ParseFe2InvalidLinks(string url) - { - Assert.Throws(() => new StreamWrapper(url)); - } -} diff --git a/tests/Speckle.Sdk.Tests.Unit/Credentials/StreamWrapperTests.cs b/tests/Speckle.Sdk.Tests.Unit/Credentials/StreamWrapperTests.cs deleted file mode 100644 index c16784c7..00000000 --- a/tests/Speckle.Sdk.Tests.Unit/Credentials/StreamWrapperTests.cs +++ /dev/null @@ -1,82 +0,0 @@ -using NUnit.Framework; -using Speckle.Sdk.Credentials; - -namespace Speckle.Sdk.Tests.Unit.Credentials; - -[TestFixture] -[TestOf(typeof(StreamWrapper))] -public class StreamWrapperTests -{ - [Test] - public void ParseStream() - { - var wrapper = new StreamWrapper("https://testing.speckle.dev/streams/a75ab4f10f"); - Assert.That(wrapper.Type, Is.EqualTo(StreamWrapperType.Stream)); - } - - [Test] - public void ParseBranch() - { - var wrapperCrazy = new StreamWrapper( - "https://testing.speckle.dev/streams/4c3ce1459c/branches/%F0%9F%8D%95%E2%AC%85%F0%9F%8C%9F%20you%20wat%3F" - ); - Assert.That(wrapperCrazy.BranchName, Is.EqualTo("🍕⬅🌟 you wat?")); - Assert.That(wrapperCrazy.Type, Is.EqualTo(StreamWrapperType.Branch)); - - wrapperCrazy = new StreamWrapper("https://testing.speckle.dev/streams/4c3ce1459c/branches/next%20level"); - Assert.That(wrapperCrazy.BranchName, Is.EqualTo("next level")); - Assert.That(wrapperCrazy.Type, Is.EqualTo(StreamWrapperType.Branch)); - } - - [Test] - public void ParseObject() - { - var wrapper = new StreamWrapper( - "https://testing.speckle.dev/streams/a75ab4f10f/objects/5530363e6d51c904903dafc3ea1d2ec6" - ); - Assert.That(wrapper.Type, Is.EqualTo(StreamWrapperType.Object)); - } - - [Test] - public void ParseCommit() - { - var wrapper = new StreamWrapper("https://testing.speckle.dev/streams/4c3ce1459c/commits/8b9b831792"); - Assert.That(wrapper.Type, Is.EqualTo(StreamWrapperType.Commit)); - } - - [Test] - public void ParseGlobalAsBranch() - { - var wrapper = new StreamWrapper("https://testing.speckle.dev/streams/0c6ad366c4/globals/"); - Assert.That(wrapper.Type, Is.EqualTo(StreamWrapperType.Branch)); - } - - [Test] - public void ParseGlobalAsCommit() - { - var wrapper = new StreamWrapper("https://testing.speckle.dev/streams/0c6ad366c4/globals/abd3787893"); - Assert.That(wrapper.Type, Is.EqualTo(StreamWrapperType.Commit)); - } - - [TestCase("https://testing.speckle.dev/projects/0c6ad366c4/models/abd3787893", StreamWrapperType.Branch)] - [TestCase("https://testing.speckle.dev/projects/28dd9ad7ba/models/117eb16f2c@b1b8579d93", StreamWrapperType.Commit)] - [TestCase( - "https://testing.speckle.dev/projects/28dd9ad7ba/models/6ae9712d6a8bad80a3efd4a29a21c31a", - StreamWrapperType.Object - )] - public void ParseFe2Urls(string speckleUrl, StreamWrapperType expectedType) - { - var wrapper = new StreamWrapper(speckleUrl); - Assert.That(wrapper.Type, Is.EqualTo(expectedType)); - Assert.That(wrapper.ToString(), Is.EqualTo(speckleUrl)); - } - - [TestCase( - "https://testing.speckle.dev/projects/28dd9ad7ba/models/117eb16f2c@b1b8579d93,abd3787893,6ae9712d6a8bad80a3efd4a29a21c31a", - StreamWrapperType.Object - )] - public void ParseFe2MultiModelUrls_IsNotSupported(string speckleUrl, StreamWrapperType expectedType) - { - Assert.Throws(() => new StreamWrapper(speckleUrl)); - } -} diff --git a/tests/Speckle.Sdk.Tests.Unit/Helpers/Path.cs b/tests/Speckle.Sdk.Tests.Unit/Helpers/Path.cs index f3e9bd2b..ab992217 100644 --- a/tests/Speckle.Sdk.Tests.Unit/Helpers/Path.cs +++ b/tests/Speckle.Sdk.Tests.Unit/Helpers/Path.cs @@ -42,15 +42,6 @@ public void TestUserApplicationDataPath() Assert.That(userPath, Does.Match(pattern)); } - [Test] - public void TestUserApplicationDataPathOverride() - { - var newPath = Path.GetTempPath(); - SpecklePathProvider.OverrideApplicationDataPath(newPath); - Assert.That(SpecklePathProvider.UserApplicationDataPath(), Is.EqualTo(newPath)); - SpecklePathProvider.OverrideApplicationDataPath(null); - } - [Test] public void TestInstallApplicationDataPath() { diff --git a/tests/Speckle.Sdk.Tests.Unit/Models/UtilitiesTests.cs b/tests/Speckle.Sdk.Tests.Unit/Models/UtilitiesTests.cs index 0f1a10e9..32286cc5 100644 --- a/tests/Speckle.Sdk.Tests.Unit/Models/UtilitiesTests.cs +++ b/tests/Speckle.Sdk.Tests.Unit/Models/UtilitiesTests.cs @@ -30,19 +30,17 @@ public sealed class HashUtilityTests ); } - public static IEnumerable<(string input, string sha256, string md5)> LargeTestCases() + public static IEnumerable LargeTestCases() { Random random = new(420); - yield return ( + yield return new TestCaseData( new string(Enumerable.Range(0, 1_000_000).Select(_ => (char)random.Next(32, 127)).ToArray()), - "b919b9e60cd6bb86ab395ee1408e12efd4d3e4e7b58f02b4cda6b4120086959a", - "d38572fdb20fe90c4871178df3f9570d" - ); - yield return ( + "b919b9e60cd6bb86ab395ee1408e12efd4d3e4e7b58f02b4cda6b4120086959a" + ).SetName("1_000_000 random chars"); + yield return new TestCaseData( new string(Enumerable.Range(0, 10_000_000).Select(_ => (char)random.Next(32, 127)).ToArray()), - "f2e83101c3066c8a2983acdb92df53504ec00ac1e5afb71b7c3798cb4daf6162", - "a7eecf20d68f836f462963928cd0f1a1" - ); + "f2e83101c3066c8a2983acdb92df53504ec00ac1e5afb71b7c3798cb4daf6162" + ).SetName("10_000_000 random chars"); } [Test, TestOf(nameof(Crypt.Md5))] @@ -86,10 +84,9 @@ public void Sha256_Span( [Test, TestOf(nameof(Crypt.Sha256))] [TestCaseSource(nameof(LargeTestCases))] - public void Sha256_LargeDataTests((string input, string expected, string _) testCase) + public void Sha256_LargeDataTests(string input, string expected) { - var test = Crypt.Sha256(testCase.input.AsSpan()); - - Assert.That(test, Is.EqualTo(testCase.expected)); + var test = Crypt.Sha256(input.AsSpan()); + Assert.That(test, Is.EqualTo(expected)); } } diff --git a/tests/Speckle.Sdk.Tests.Unit/Serialisation/SerializerBreakingChanges.cs b/tests/Speckle.Sdk.Tests.Unit/Serialisation/SerializerBreakingChanges.cs index 65339a81..1d8487dd 100644 --- a/tests/Speckle.Sdk.Tests.Unit/Serialisation/SerializerBreakingChanges.cs +++ b/tests/Speckle.Sdk.Tests.Unit/Serialisation/SerializerBreakingChanges.cs @@ -1,4 +1,6 @@ +using Microsoft.Extensions.DependencyInjection; using NUnit.Framework; +using Speckle.Sdk.Api; using Speckle.Sdk.Host; using Speckle.Sdk.Models; using Speckle.Sdk.Serialisation; @@ -17,11 +19,17 @@ namespace Speckle.Sdk.Tests.Unit.Serialisation; )] public class SerializerBreakingChanges : PrimitiveTestFixture { + private IOperations _operations; + [SetUp] public void Setup() { TypeLoader.Reset(); TypeLoader.Initialize(typeof(Base).Assembly, typeof(Point).Assembly); + var serviceCollection = new ServiceCollection(); + serviceCollection.AddSpeckleSdk(HostApplications.Navisworks, HostAppVersion.v2023); + var serviceProvider = serviceCollection.BuildServiceProvider(); + _operations = serviceProvider.GetRequiredService(); } [Test] @@ -29,7 +37,9 @@ public void StringToInt_ShouldThrow() { var from = new StringValueMock { value = "testValue" }; - Assert.ThrowsAsync(async () => await from.SerializeAsTAndDeserialize()); + Assert.ThrowsAsync( + async () => await from.SerializeAsTAndDeserialize(_operations) + ); } [Test, TestCaseSource(nameof(MyEnums))] @@ -39,7 +49,7 @@ public void StringToEnum_ShouldThrow(MyEnum testCase) Assert.ThrowsAsync(async () => { - var res = await from.SerializeAsTAndDeserialize(); + var res = await from.SerializeAsTAndDeserialize(_operations); }); } @@ -52,6 +62,8 @@ public void StringToEnum_ShouldThrow(MyEnum testCase) public void DoubleToInt_ShouldThrow(double testCase) { var from = new DoubleValueMock { value = testCase }; - Assert.ThrowsAsync(async () => await from.SerializeAsTAndDeserialize()); + Assert.ThrowsAsync( + async () => await from.SerializeAsTAndDeserialize(_operations) + ); } } diff --git a/tests/Speckle.Sdk.Tests.Unit/Serialisation/SerializerNonBreakingChanges.cs b/tests/Speckle.Sdk.Tests.Unit/Serialisation/SerializerNonBreakingChanges.cs index 2d01ff12..32a3906e 100644 --- a/tests/Speckle.Sdk.Tests.Unit/Serialisation/SerializerNonBreakingChanges.cs +++ b/tests/Speckle.Sdk.Tests.Unit/Serialisation/SerializerNonBreakingChanges.cs @@ -1,9 +1,12 @@ using System.Drawing; +using Microsoft.Extensions.DependencyInjection; using NUnit.Framework; +using Shouldly; using Speckle.Sdk.Api; using Speckle.Sdk.Helpers; using Speckle.Sdk.Host; using Speckle.Sdk.Models; +using Speckle.Sdk.Serialisation; using Matrix4x4 = Speckle.DoubleNumerics.Matrix4x4; namespace Speckle.Sdk.Tests.Unit.Serialisation; @@ -17,11 +20,17 @@ namespace Speckle.Sdk.Tests.Unit.Serialisation; [Description("For certain types, changing property from one type to another should be implicitly backwards compatible")] public class SerializerNonBreakingChanges : PrimitiveTestFixture { + private IOperations _operations; + [SetUp] public void Setup() { TypeLoader.Reset(); TypeLoader.Initialize(typeof(StringValueMock).Assembly); + var serviceCollection = new ServiceCollection(); + serviceCollection.AddSpeckleSdk(HostApplications.Navisworks, HostAppVersion.v2023); + var serviceProvider = serviceCollection.BuildServiceProvider(); + _operations = serviceProvider.GetRequiredService(); } [Test, TestCaseSource(nameof(Int8TestCases)), TestCaseSource(nameof(Int32TestCases))] @@ -29,7 +38,7 @@ public async Task IntToColor(int argb) { var from = new IntValueMock { value = argb }; - var res = await from.SerializeAsTAndDeserialize(); + var res = await from.SerializeAsTAndDeserialize(_operations); Assert.That(res.value.ToArgb(), Is.EqualTo(argb)); } @@ -38,7 +47,7 @@ public async Task ColorToInt(int argb) { var from = new ColorValueMock { value = Color.FromArgb(argb) }; - var res = await from.SerializeAsTAndDeserialize(); + var res = await from.SerializeAsTAndDeserialize(_operations); Assert.That(res.value, Is.EqualTo(argb)); } @@ -52,7 +61,7 @@ public async Task IntToDouble(long testCase) { var from = new IntValueMock { value = testCase }; - var res = await from.SerializeAsTAndDeserialize(); + var res = await from.SerializeAsTAndDeserialize(_operations); Assert.That(res.value, Is.EqualTo(testCase)); } @@ -61,7 +70,7 @@ public async Task NullToInt() { var from = new ObjectValueMock { value = null }; - var res = await from.SerializeAsTAndDeserialize(); + var res = await from.SerializeAsTAndDeserialize(_operations); Assert.That(res.value, Is.EqualTo(default(int))); } @@ -70,7 +79,7 @@ public async Task NullToDouble() { var from = new ObjectValueMock { value = null }; - var res = await from.SerializeAsTAndDeserialize(); + var res = await from.SerializeAsTAndDeserialize(_operations); Assert.That(res.value, Is.EqualTo(default(double))); } @@ -84,7 +93,7 @@ public async Task UIntToDouble(ulong testCase) { var from = new UIntValueMock { value = testCase }; - var res = await from.SerializeAsTAndDeserialize(); + var res = await from.SerializeAsTAndDeserialize(_operations); Assert.That(res.value, Is.EqualTo(testCase)); } @@ -98,7 +107,7 @@ public async Task IntToString(long testCase) { var from = new IntValueMock { value = testCase }; - var res = await from.SerializeAsTAndDeserialize(); + var res = await from.SerializeAsTAndDeserialize(_operations); Assert.That(res.value, Is.EqualTo(testCase.ToString())); } @@ -114,7 +123,7 @@ public async Task ArrayToList(double[] testCase) { var from = new ArrayDoubleValueMock { value = testCase }; - var res = await from.SerializeAsTAndDeserialize(); + var res = await from.SerializeAsTAndDeserialize(_operations); Assert.That(res.value, Is.EquivalentTo(testCase)); } @@ -123,7 +132,7 @@ public async Task ListToArray(double[] testCase) { var from = new ListDoubleValueMock { value = testCase.ToList() }; - var res = await from.SerializeAsTAndDeserialize(); + var res = await from.SerializeAsTAndDeserialize(_operations); Assert.That(res.value, Is.EquivalentTo(testCase)); } @@ -132,7 +141,7 @@ public async Task ListToIList(double[] testCase) { var from = new ListDoubleValueMock { value = testCase.ToList() }; - var res = await from.SerializeAsTAndDeserialize(); + var res = await from.SerializeAsTAndDeserialize(_operations); Assert.That(res.value, Is.EquivalentTo(testCase)); } @@ -141,7 +150,7 @@ public async Task ListToIReadOnlyList(double[] testCase) { var from = new ListDoubleValueMock { value = testCase.ToList() }; - var res = await from.SerializeAsTAndDeserialize(); + var res = await from.SerializeAsTAndDeserialize(_operations); Assert.That(res.value, Is.EquivalentTo(testCase)); } @@ -150,7 +159,7 @@ public async Task IListToList(double[] testCase) { var from = new IListDoubleValueMock { value = testCase.ToList() }; - var res = await from.SerializeAsTAndDeserialize(); + var res = await from.SerializeAsTAndDeserialize(_operations); Assert.That(res.value, Is.EquivalentTo(testCase)); } @@ -159,7 +168,7 @@ public async Task IReadOnlyListToList(double[] testCase) { var from = new IReadOnlyListDoubleValueMock { value = testCase.ToList() }; - var res = await from.SerializeAsTAndDeserialize(); + var res = await from.SerializeAsTAndDeserialize(_operations); Assert.That(res.value, Is.EquivalentTo(testCase)); } @@ -168,7 +177,7 @@ public async Task EnumToInt(MyEnum testCase) { var from = new EnumValueMock { value = testCase }; - var res = await from.SerializeAsTAndDeserialize(); + var res = await from.SerializeAsTAndDeserialize(_operations); Assert.That(res.value, Is.EqualTo((int)testCase)); } @@ -177,7 +186,7 @@ public async Task IntToEnum(MyEnum testCase) { var from = new IntValueMock { value = (int)testCase }; - var res = await from.SerializeAsTAndDeserialize(); + var res = await from.SerializeAsTAndDeserialize(_operations); Assert.That(res.value, Is.EqualTo(testCase)); } @@ -188,7 +197,7 @@ public async Task DoubleToDouble(double testCase) { var from = new DoubleValueMock { value = testCase }; - var res = await from.SerializeAsTAndDeserialize(); + var res = await from.SerializeAsTAndDeserialize(_operations); Assert.That(res.value, Is.EqualTo(testCase)); } @@ -204,12 +213,12 @@ public async Task ListToMatrix64(int seed, double scalar) ListDoubleValueMock from = new() { value = testCase, }; //Test List -> Matrix - var res = await from.SerializeAsTAndDeserialize(); + var res = await from.SerializeAsTAndDeserialize(_operations); Assert.That(res.value.M11, Is.EqualTo(testCase[0])); Assert.That(res.value.M44, Is.EqualTo(testCase[testCase.Count - 1])); //Test Matrix -> List - var backAgain = await res.SerializeAsTAndDeserialize(); + var backAgain = await res.SerializeAsTAndDeserialize(_operations); Assert.That(backAgain.value, Is.Not.Null); Assert.That(backAgain.value, Is.EquivalentTo(testCase)); } @@ -218,7 +227,7 @@ public async Task ListToMatrix64(int seed, double scalar) [TestCase(123, 255)] [TestCase(256, 1)] [DefaultFloatingPointTolerance(Constants.EPS)] - public async Task Matrix32ToMatrix64(int seed, float scalar) + public void Matrix32ToMatrix64(int seed, float scalar) { Random rand = new(seed); List testCase = Enumerable.Range(0, 16).Select(_ => rand.NextDouble() * scalar).ToList(); @@ -226,14 +235,10 @@ public async Task Matrix32ToMatrix64(int seed, float scalar) ListDoubleValueMock from = new() { value = testCase }; //Test List -> Matrix - var res = await from.SerializeAsTAndDeserialize(); - Assert.That(res.value.M11, Is.EqualTo(testCase[0])); - Assert.That(res.value.M44, Is.EqualTo(testCase[testCase.Count - 1])); - - //Test Matrix -> List - var backAgain = await res.SerializeAsTAndDeserialize(); - Assert.That(backAgain.value, Is.Not.Null); - Assert.That(backAgain.value, Is.EquivalentTo(testCase)); + var exception = Assert.ThrowsAsync( + async () => await from.SerializeAsTAndDeserialize(_operations) + ); + exception.ShouldNotBeNull(); } } @@ -350,14 +355,14 @@ public void SerializeAs() _speckle_type = target.speckle_type; } - internal async Task SerializeAsTAndDeserialize() + internal async Task SerializeAsTAndDeserialize(IOperations operations) where TTo : Base, new() { SerializeAs(); - var json = Operations.Serialize(this); + var json = operations.Serialize(this); - Base result = await Operations.DeserializeAsync(json); + Base result = await operations.DeserializeAsync(json); Assert.That(result, Is.Not.Null); Assert.That(result, Is.TypeOf()); return (TTo)result; diff --git a/tests/Speckle.Sdk.Tests.Unit/Serialisation/SimpleRoundTripTests.cs b/tests/Speckle.Sdk.Tests.Unit/Serialisation/SimpleRoundTripTests.cs index b977ce72..8e8cba3a 100644 --- a/tests/Speckle.Sdk.Tests.Unit/Serialisation/SimpleRoundTripTests.cs +++ b/tests/Speckle.Sdk.Tests.Unit/Serialisation/SimpleRoundTripTests.cs @@ -1,5 +1,7 @@ using System.Reflection; +using Microsoft.Extensions.DependencyInjection; using NUnit.Framework; +using Speckle.Sdk.Api; using Speckle.Sdk.Host; using Speckle.Sdk.Models; using Speckle.Sdk.Tests.Unit.Host; @@ -8,6 +10,8 @@ namespace Speckle.Sdk.Tests.Unit.Serialisation; public class SimpleRoundTripTests { + private IOperations _operations; + static SimpleRoundTripTests() { Reset(); @@ -32,13 +36,21 @@ public static IEnumerable TestData() } [SetUp] - public void Setup() => Reset(); + public void Setup() + { + Reset(); + + var serviceCollection = new ServiceCollection(); + serviceCollection.AddSpeckleSdk(HostApplications.Navisworks, HostAppVersion.v2023); + var serviceProvider = serviceCollection.BuildServiceProvider(); + _operations = serviceProvider.GetRequiredService(); + } [TestCaseSource(nameof(TestData))] public async Task SimpleSerialization(Base testData) { - var result = Sdk.Api.Operations.Serialize(testData); - var test = await Sdk.Api.Operations.DeserializeAsync(result); + var result = _operations.Serialize(testData); + var test = await _operations.DeserializeAsync(result); Assert.That(testData.GetId(), Is.EqualTo(test.GetId())); } diff --git a/tests/Speckle.Sdk.Tests.Unit/packages.lock.json b/tests/Speckle.Sdk.Tests.Unit/packages.lock.json index c012b969..4b8dc6ec 100644 --- a/tests/Speckle.Sdk.Tests.Unit/packages.lock.json +++ b/tests/Speckle.Sdk.Tests.Unit/packages.lock.json @@ -127,6 +127,57 @@ "SQLitePCLRaw.core": "2.1.4" } }, + "Microsoft.Extensions.Configuration": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "Lu41BWNmwhKr6LgyQvcYBOge0pPvmiaK8R5UHXX4//wBhonJyWcT2OK1mqYfEM5G7pTf31fPrpIHOT6sN7EGOA==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "3.1.0" + } + }, + "Microsoft.Extensions.Configuration.Abstractions": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "ESz6bVoDQX7sgWdKHF6G9Pq672T8k+19AFb/txDXwdz7MoqaNQj2/in3agm/3qae9V+WvQZH86LLTNVo0it8vQ==", + "dependencies": { + "Microsoft.Extensions.Primitives": "3.1.0" + } + }, + "Microsoft.Extensions.Configuration.Binder": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "o9eELDBfNkR7sUtYysFZ1Q7BQ1mYt27DMkups/3vu7xgPyOpMD+iAfrBZFzUXT2iw0fmFb8s1gfNBZS+IgjKdQ==", + "dependencies": { + "Microsoft.Extensions.Configuration": "3.1.0" + } + }, + "Microsoft.Extensions.DependencyInjection": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "KVkv3aF2MQpmGFRh4xRx2CNbc2sjDFk+lH4ySrjWSOS+XoY1Xc+sJphw3N0iYOpoeCCq8976ceVYDH8sdx2qIQ==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.0" + } + }, + "Microsoft.Extensions.Logging.Abstractions": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "jjo4YXRx6MIpv6DiRxJjSpl+sPP0+5VW0clMEdLyIAz44PPwrDTFrd5PZckIxIXl1kKZ2KK6IL2nkt0+ug2MQg==" + }, + "Microsoft.Extensions.Options": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "9b6JHY7TAXrSfZ6EEGf+j8XnqKIiMPErfmaNXhJYSCb+BUW2H4RtzkNJvwLJzwgzqBP0wtTjyA6Uw4BPPdmkMw==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.0", + "Microsoft.Extensions.Primitives": "3.1.0" + } + }, + "Microsoft.Extensions.Primitives": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "LEKAnX7lhUhSoIc2XraCTK3M4IU/LdVUzCe464Sa4+7F4ZJuXHHRzZli2mDbiT4xzAZhgqXbvfnb5+CNDcQFfg==" + }, "Microsoft.SourceLink.Common": { "type": "Transitive", "resolved": "8.0.0", @@ -218,18 +269,16 @@ "GraphQL.Client": "[6.0.0, )", "Microsoft.CSharp": "[4.7.0, )", "Microsoft.Data.Sqlite": "[7.0.7, )", + "Microsoft.Extensions.DependencyInjection.Abstractions": "[3.1.0, )", + "Microsoft.Extensions.Logging": "[3.1.0, )", "Polly": "[7.2.3, )", "Polly.Contrib.WaitAndRetry": "[1.1.1, )", "Polly.Extensions.Http": "[3.0.0, )", "Speckle.DoubleNumerics": "[4.0.1, )", "Speckle.Newtonsoft.Json": "[13.0.2, )", - "Speckle.Sdk.Logging": "[1.0.0, )", "System.Text.Json": "[5.0.2, )" } }, - "speckle.sdk.logging": { - "type": "Project" - }, "GraphQL.Client": { "type": "CentralTransitive", "requested": "[6.0.0, )", @@ -257,6 +306,24 @@ "SQLitePCLRaw.bundle_e_sqlite3": "2.1.4" } }, + "Microsoft.Extensions.DependencyInjection.Abstractions": { + "type": "CentralTransitive", + "requested": "[3.1.0, )", + "resolved": "3.1.0", + "contentHash": "44rDtOf1JXXAFpNT2EXMExaDm/4OJ2RXOL9i9lE4bK427nzC7Exphv+beB6IgluyE2GIoo8zezTStMXI7MQ8WA==" + }, + "Microsoft.Extensions.Logging": { + "type": "CentralTransitive", + "requested": "[3.1.0, )", + "resolved": "3.1.0", + "contentHash": "P+8sKQ8L4ooL79sxxqwFPxGGC3aBrUDLB/dZqhs4J0XjTyrkeeyJQ4D4nzJB6OnAhy78HIIgQ/RbD6upOXLynw==", + "dependencies": { + "Microsoft.Extensions.Configuration.Binder": "3.1.0", + "Microsoft.Extensions.DependencyInjection": "3.1.0", + "Microsoft.Extensions.Logging.Abstractions": "3.1.0", + "Microsoft.Extensions.Options": "3.1.0" + } + }, "Polly": { "type": "CentralTransitive", "requested": "[7.2.3, )",