diff --git a/Speckle.Sdk.sln b/Speckle.Sdk.sln index 747037dc..2aea6658 100644 --- a/Speckle.Sdk.sln +++ b/Speckle.Sdk.sln @@ -46,7 +46,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Speckle.Sdk.Serialization.T EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Speckle.Sdk.Dependencies", "src\Speckle.Sdk.Dependencies\Speckle.Sdk.Dependencies.csproj", "{27584AB4-8ACD-4850-8CC2-7E5BC739FB78}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Speckle.Sdk.Testing", "Speckle.Sdk.Testing\Speckle.Sdk.Testing.csproj", "{7B617C0D-2354-415C-993C-5071D4113E27}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Speckle.Sdk.Testing", "tests\Speckle.Sdk.Testing\Speckle.Sdk.Testing.csproj", "{7B617C0D-2354-415C-993C-5071D4113E27}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "performance", "performance", "{FFB07238-87E8-463A-AA39-3B38AAAA94C1}" EndProject diff --git a/src/Speckle.Sdk/Api/GraphQL/Models/Comment.cs b/src/Speckle.Sdk/Api/GraphQL/Models/Comment.cs index 5637f57c..01da6610 100644 --- a/src/Speckle.Sdk/Api/GraphQL/Models/Comment.cs +++ b/src/Speckle.Sdk/Api/GraphQL/Models/Comment.cs @@ -1,4 +1,6 @@ -namespace Speckle.Sdk.Api.GraphQL.Models; +using Speckle.Newtonsoft.Json; + +namespace Speckle.Sdk.Api.GraphQL.Models; public sealed class Comment { @@ -17,4 +19,33 @@ public sealed class Comment public DateTime updatedAt { get; init; } public DateTime? viewedAt { get; init; } public List viewerResources { get; init; } + public SerializedViewerState viewerState { get; init; } +} + +/// +/// See SerializedViewerState in /shared/src/viewer/helpers/state.ts +/// +/// +/// Note, there are many FE/Viewer specific properties on this object that are not reflected here (hence the override) +/// We can add them as needed, keeping in mind flexiblity for breaking changes (these classes are intentionally not documented in our schema!) +/// +[JsonObject(MissingMemberHandling = MissingMemberHandling.Ignore)] +public sealed class SerializedViewerState +{ + public ViewerStateUI ui { get; init; } +} + +[JsonObject(MissingMemberHandling = MissingMemberHandling.Ignore)] +public sealed class ViewerStateUI +{ + public ViewerStateCamera camera { get; init; } +} + +[JsonObject(MissingMemberHandling = MissingMemberHandling.Ignore)] +public sealed class ViewerStateCamera +{ + public List position { get; init; } + public List target { get; init; } + public bool isOrthoProjection { get; init; } + public double zoom { get; init; } } diff --git a/src/Speckle.Sdk/Api/GraphQL/Models/SubscriptionMessages.cs b/src/Speckle.Sdk/Api/GraphQL/Models/SubscriptionMessages.cs index 9d4fe88a..327bac77 100644 --- a/src/Speckle.Sdk/Api/GraphQL/Models/SubscriptionMessages.cs +++ b/src/Speckle.Sdk/Api/GraphQL/Models/SubscriptionMessages.cs @@ -77,7 +77,8 @@ public sealed class ProjectVersionsUpdatedMessage : EventArgs [JsonRequired] public ProjectVersionsUpdatedMessageType type { get; init; } - public string? modelId { get; init; } + [JsonRequired] + public string modelId { get; init; } public Version? version { get; init; } } diff --git a/src/Speckle.Sdk/Api/GraphQL/Resources/CommentResource.cs b/src/Speckle.Sdk/Api/GraphQL/Resources/CommentResource.cs index 7f173ca9..30aed5e9 100644 --- a/src/Speckle.Sdk/Api/GraphQL/Resources/CommentResource.cs +++ b/src/Speckle.Sdk/Api/GraphQL/Resources/CommentResource.cs @@ -150,6 +150,7 @@ public sealed class CommentResource objectId versionId } + viewerState } } } diff --git a/src/Speckle.Sdk/Serialisation/V2/Receive/DeserializeProcess.cs b/src/Speckle.Sdk/Serialisation/V2/Receive/DeserializeProcess.cs index 48a19ddf..33000d26 100644 --- a/src/Speckle.Sdk/Serialisation/V2/Receive/DeserializeProcess.cs +++ b/src/Speckle.Sdk/Serialisation/V2/Receive/DeserializeProcess.cs @@ -12,7 +12,8 @@ public record DeserializeProcessOptions( bool SkipCache = false, bool ThrowOnMissingReferences = true, bool SkipInvalidConverts = false, - int? MaxParallelism = null + int? MaxParallelism = null, + bool SkipServer = false ); public partial interface IDeserializeProcess : IDisposable; diff --git a/src/Speckle.Sdk/Serialisation/V2/Receive/ObjectLoader.cs b/src/Speckle.Sdk/Serialisation/V2/Receive/ObjectLoader.cs index 62f28c94..5d6aa2b5 100644 --- a/src/Speckle.Sdk/Serialisation/V2/Receive/ObjectLoader.cs +++ b/src/Speckle.Sdk/Serialisation/V2/Receive/ObjectLoader.cs @@ -49,28 +49,33 @@ public sealed class ObjectLoader( return (new(rootJson), allChildren); } } - rootJson = await serverObjectManager - .DownloadSingleObject(rootId, progress, cancellationToken) - .NotNull() - .ConfigureAwait(false); - IReadOnlyCollection allChildrenIds = ClosureParser - .GetClosures(rootJson, cancellationToken) - .OrderByDescending(x => x.Item2) - .Select(x => new Id(x.Item1)) - .Where(x => !x.Value.StartsWith("blob", StringComparison.Ordinal)) - .Freeze(); - _allChildrenCount = allChildrenIds.Count; - await GetAndCache(allChildrenIds.Select(x => x.Value), cancellationToken, _options.MaxParallelism) - .ConfigureAwait(false); - - CheckForExceptions(); - cancellationToken.ThrowIfCancellationRequested(); - //save the root last to shortcut later - if (!options.SkipCache) + if (!options.SkipServer) { - sqLiteJsonCacheManager.SaveObject(rootId, rootJson); + rootJson = await serverObjectManager + .DownloadSingleObject(rootId, progress, cancellationToken) + .NotNull() + .ConfigureAwait(false); + IReadOnlyCollection allChildrenIds = ClosureParser + .GetClosures(rootJson, cancellationToken) + .OrderByDescending(x => x.Item2) + .Select(x => new Id(x.Item1)) + .Where(x => !x.Value.StartsWith("blob", StringComparison.Ordinal)) + .Freeze(); + _allChildrenCount = allChildrenIds.Count; + await GetAndCache(allChildrenIds.Select(x => x.Value), cancellationToken, _options.MaxParallelism) + .ConfigureAwait(false); + + CheckForExceptions(); + cancellationToken.ThrowIfCancellationRequested(); + //save the root last to shortcut later + if (!options.SkipCache) + { + sqLiteJsonCacheManager.SaveObject(rootId, rootJson); + } + + return (new(rootJson), allChildrenIds); } - return (new(rootJson), allChildrenIds); + throw new SpeckleException("Cannot skip server and cache. Please choose one."); } [AutoInterfaceIgnore] diff --git a/tests/Speckle.Objects.Tests.Unit/Speckle.Objects.Tests.Unit.csproj b/tests/Speckle.Objects.Tests.Unit/Speckle.Objects.Tests.Unit.csproj index a307c540..15eb3455 100644 --- a/tests/Speckle.Objects.Tests.Unit/Speckle.Objects.Tests.Unit.csproj +++ b/tests/Speckle.Objects.Tests.Unit/Speckle.Objects.Tests.Unit.csproj @@ -15,7 +15,7 @@ - + diff --git a/tests/Speckle.Sdk.Serialization.Tests/ExceptionTests.Test_Exceptions_Receive_Server_Skip_Both.verified.json b/tests/Speckle.Sdk.Serialization.Tests/ExceptionTests.Test_Exceptions_Receive_Server_Skip_Both.verified.json new file mode 100644 index 00000000..ec4502d8 --- /dev/null +++ b/tests/Speckle.Sdk.Serialization.Tests/ExceptionTests.Test_Exceptions_Receive_Server_Skip_Both.verified.json @@ -0,0 +1,5 @@ +{ + "Type": "Speckle.Sdk.SpeckleException", + "Message": "Cannot skip server and cache. Please choose one.", + "Source": "Speckle.Sdk" +} diff --git a/tests/Speckle.Sdk.Serialization.Tests/ExceptionTests.cs b/tests/Speckle.Sdk.Serialization.Tests/ExceptionTests.cs index 4b14b5b7..7cdd2b89 100644 --- a/tests/Speckle.Sdk.Serialization.Tests/ExceptionTests.cs +++ b/tests/Speckle.Sdk.Serialization.Tests/ExceptionTests.cs @@ -60,6 +60,30 @@ public class ExceptionTests await Verify(ex); } + [Fact] + public async Task Test_Exceptions_Receive_Server_Skip_Both() + { + var o = new ObjectLoader( + new DummySqLiteReceiveManager(new Dictionary()), + new ExceptionServerObjectManager(), + null + ); + using var process = new DeserializeProcess( + null, + o, + new BaseDeserializer(new ObjectDeserializerFactory()), + new NullLoggerFactory(), + default, + new(SkipCache: true, MaxParallelism: 1, SkipServer: true) + ); + + var ex = await Assert.ThrowsAsync(async () => + { + var root = await process.Deserialize(Guid.NewGuid().ToString()); + }); + await Verify(ex); + } + [Theory] [InlineData("RevitObject.json.gz", "3416d3fe01c9196115514c4a2f41617b", 7818)] public async Task Test_Exceptions_Receive_Server(string fileName, string rootId, int oldCount) diff --git a/tests/Speckle.Sdk.Serialization.Tests/Speckle.Sdk.Serialization.Tests.csproj b/tests/Speckle.Sdk.Serialization.Tests/Speckle.Sdk.Serialization.Tests.csproj index 7984465a..47352da9 100644 --- a/tests/Speckle.Sdk.Serialization.Tests/Speckle.Sdk.Serialization.Tests.csproj +++ b/tests/Speckle.Sdk.Serialization.Tests/Speckle.Sdk.Serialization.Tests.csproj @@ -15,7 +15,7 @@ - + diff --git a/Speckle.Sdk.Testing/Framework/AggregationExceptionScrubber.cs b/tests/Speckle.Sdk.Testing/Framework/AggregationExceptionScrubber.cs similarity index 100% rename from Speckle.Sdk.Testing/Framework/AggregationExceptionScrubber.cs rename to tests/Speckle.Sdk.Testing/Framework/AggregationExceptionScrubber.cs diff --git a/Speckle.Sdk.Testing/Framework/DummyReceiveServerObjectManager.cs b/tests/Speckle.Sdk.Testing/Framework/DummyReceiveServerObjectManager.cs similarity index 100% rename from Speckle.Sdk.Testing/Framework/DummyReceiveServerObjectManager.cs rename to tests/Speckle.Sdk.Testing/Framework/DummyReceiveServerObjectManager.cs diff --git a/Speckle.Sdk.Testing/Framework/DummySendServerObjectManager.cs b/tests/Speckle.Sdk.Testing/Framework/DummySendServerObjectManager.cs similarity index 100% rename from Speckle.Sdk.Testing/Framework/DummySendServerObjectManager.cs rename to tests/Speckle.Sdk.Testing/Framework/DummySendServerObjectManager.cs diff --git a/Speckle.Sdk.Testing/Framework/DummySqLiteReceiveManager.cs b/tests/Speckle.Sdk.Testing/Framework/DummySqLiteReceiveManager.cs similarity index 100% rename from Speckle.Sdk.Testing/Framework/DummySqLiteReceiveManager.cs rename to tests/Speckle.Sdk.Testing/Framework/DummySqLiteReceiveManager.cs diff --git a/Speckle.Sdk.Testing/Framework/DummySqLiteSendManager.cs b/tests/Speckle.Sdk.Testing/Framework/DummySqLiteSendManager.cs similarity index 100% rename from Speckle.Sdk.Testing/Framework/DummySqLiteSendManager.cs rename to tests/Speckle.Sdk.Testing/Framework/DummySqLiteSendManager.cs diff --git a/Speckle.Sdk.Testing/Framework/ExceptionScrubber.cs b/tests/Speckle.Sdk.Testing/Framework/ExceptionScrubber.cs similarity index 100% rename from Speckle.Sdk.Testing/Framework/ExceptionScrubber.cs rename to tests/Speckle.Sdk.Testing/Framework/ExceptionScrubber.cs diff --git a/Speckle.Sdk.Testing/Framework/IdStringSerializer.cs b/tests/Speckle.Sdk.Testing/Framework/IdStringSerializer.cs similarity index 100% rename from Speckle.Sdk.Testing/Framework/IdStringSerializer.cs rename to tests/Speckle.Sdk.Testing/Framework/IdStringSerializer.cs diff --git a/Speckle.Sdk.Testing/Framework/JsonStringSerializer.cs b/tests/Speckle.Sdk.Testing/Framework/JsonStringSerializer.cs similarity index 100% rename from Speckle.Sdk.Testing/Framework/JsonStringSerializer.cs rename to tests/Speckle.Sdk.Testing/Framework/JsonStringSerializer.cs diff --git a/Speckle.Sdk.Testing/Global.cs b/tests/Speckle.Sdk.Testing/Global.cs similarity index 100% rename from Speckle.Sdk.Testing/Global.cs rename to tests/Speckle.Sdk.Testing/Global.cs diff --git a/Speckle.Sdk.Testing/Speckle.Sdk.Testing.csproj b/tests/Speckle.Sdk.Testing/Speckle.Sdk.Testing.csproj similarity index 85% rename from Speckle.Sdk.Testing/Speckle.Sdk.Testing.csproj rename to tests/Speckle.Sdk.Testing/Speckle.Sdk.Testing.csproj index ba4b54c6..b5ecb4ed 100644 --- a/Speckle.Sdk.Testing/Speckle.Sdk.Testing.csproj +++ b/tests/Speckle.Sdk.Testing/Speckle.Sdk.Testing.csproj @@ -13,7 +13,7 @@ - + diff --git a/Speckle.Sdk.Testing/SpeckleVerify.cs b/tests/Speckle.Sdk.Testing/SpeckleVerify.cs similarity index 100% rename from Speckle.Sdk.Testing/SpeckleVerify.cs rename to tests/Speckle.Sdk.Testing/SpeckleVerify.cs diff --git a/Speckle.Sdk.Testing/VerifyTests.cs b/tests/Speckle.Sdk.Testing/VerifyTests.cs similarity index 100% rename from Speckle.Sdk.Testing/VerifyTests.cs rename to tests/Speckle.Sdk.Testing/VerifyTests.cs diff --git a/Speckle.Sdk.Testing/packages.lock.json b/tests/Speckle.Sdk.Testing/packages.lock.json similarity index 100% rename from Speckle.Sdk.Testing/packages.lock.json rename to tests/Speckle.Sdk.Testing/packages.lock.json