diff --git a/website/src/docs/hotchocolate/v14/migrating/migrate-from-13-to-14.md b/website/src/docs/hotchocolate/v14/migrating/migrate-from-13-to-14.md index 1bc24bacedb..736ee424e18 100644 --- a/website/src/docs/hotchocolate/v14/migrating/migrate-from-13-to-14.md +++ b/website/src/docs/hotchocolate/v14/migrating/migrate-from-13-to-14.md @@ -124,6 +124,22 @@ builder.Services .AddGlobalObjectIdentification(); ``` +## IIdSerializer replaced by INodeIdSerializer + +Previously, you could grab the `IIdSerializer` from your dependency injection container to manually parse and serialize globally unique identifiers (GID). +As part of the changes to the GID format mentioned above, the `IIdSerializer` interface has been renamed to `INodeIdSerializer`. + +The methods used for parsing and serialization have also been renamed: + +| Before | After | +| ---------------------------------- | ---------------------------------------------------------------------------------------- | +| `.Deserialize("")` | `.Parse("", typeof(string))` where `string` is the underlying type of the GID | +| `.Serialize("MyType", "")` | `.Format("MyType", "")` | + +The `Parse()` (previously `Deserialize()`) method has also changed its return type from `IdValue` to `NodeId`. The parsed Id value can now be accessed through the `NodeId.InternalId` instead of the `IdValue.Value` property. + +The ability to encode the schema name in the GID via `.Serialize("SchemaName", "MyType", "")` has been dropped and is no longer supported. + ## Node Resolver validation We now enforce that each object type implementing the `Node` interface also defines a resolver, so that the object can be refetched through the `node(id: ID!)` field. @@ -136,6 +152,11 @@ builder.Services .ModifyOptions(o => o.EnsureAllNodesCanBeResolved = false) ``` +## DataLoader.LoadAsync always returns nullable type + +Previously, the `LoadAsync` method on a DataLoader was typed as non-nullable, even though `null` could be returned. +This release changes the return type of `LoadAsync` to always be nullable. + ## Builder APIs We have aligned all builder APIs to be more consistent and easier to use. Builders can now be created by using the static method `Builder.New()` and the `Build()` method to create the final object. @@ -144,9 +165,14 @@ We have aligned all builder APIs to be more consistent and easier to use. Builde The interface `IQueryRequestBuilder` and its implementations were replaced with `OperationRequestBuilder` which now supports building standard GraphQL operation requests as well as variable batch requests. -The `Build()` method returns now a `IOperationRequest` which is implemented by `OperationRequest` and `VariableBatchRequest`. +The `Build()` method now returns a `IOperationRequest` which is implemented by `OperationRequest` and `VariableBatchRequest`. + +We've also renamed and consolidated some methods on the `OperationRequestBuilder`: -We have also simplified what the builder does and removed a lot of the convenience methods that allowed to add single variables to it. This has todo with the support of variable batching. Now, you have to provide the variable map directly. +| Before | After | +| ----------------------------------- | --------------------------------------------------------------------------- | +| `SetQuery("{ __typename }")` | `SetDocument("{ __typename }")` | +| `AddVariableValue("name", "value")` | `AddVariableValues(new Dictionary { ["name"] = "value" })` | ### IQueryResultBuilder replaced by OperationResultBuilder @@ -156,6 +182,11 @@ The interface `IQueryResultBuilder` and its implementations were replaced with ` The interface `IQueryResult` was replaced with `IOperationResult`. +### IExecutionResult.ExpectQueryResult replaced by .ExpectOperationResult + +In your unit tests you might have been using `result.ExpectQueryResult()` to assert that a result is not a streamed response and rather a completed result. +This assertion method has been renamed to `ExpectOperationResult()`. + ## Operation complexity analyzer replaced The Operation Complexity Analyzer in v13 has been replaced by Cost Analysis in v14, based on the draft [IBM Cost Analysis specification](https://ibm.github.io/graphql-specs/cost-spec.html). @@ -252,6 +283,38 @@ ModifyRequestOptions(o => o.OnlyAllowPersistedOperations = true); ModifyRequestOptions(o => o.PersistedOperations.OnlyAllowPersistedDocuments = true); ``` +## Connection getTotalCount constructor argument replaced with totalCount + +Previously, you could supply an async method to the `getTotalCount` constructor argument when instantiating a `Connection`. This method would only be evaluated to calculate the total count, if the `totalCount` field was selected on that Connection in a query. + +```csharp +return new Connection( + edges: [/* ... */], + info: new ConnectionPageInfo(/* ... */), + getTotalCount: async cancellationToken => 123) +``` + +In this release the constructor argument was renamed to `totalCount` and now only accepts an `int` for the total count, no longer a method to compute the total count. +If you want to re-create the old behavior, you can use the new `[IsSelected]` attribute to conditionally compute the total count. + +```csharp +public Connection GetMyTypes( + [IsSelected("totalCount")] bool hasSelectedTotalCount, + CancellationToken cancellationToken) +{ + var totalCount = 0; + if (hasSelectedTotalCount) + { + totalCount = /* ... */; + } + + return new Connection( + edges: [/* ... */], + info: new ConnectionPageInfo(/* ... */), + totalCount: totalCount) +} +``` + # Deprecations Things that will continue to function this release, but we encourage you to move away from.