-
-
Notifications
You must be signed in to change notification settings - Fork 722
/
OperationResultBuilder.cs
105 lines (94 loc) · 3.42 KB
/
OperationResultBuilder.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
using System;
using System.Collections.Generic;
using System.Text.Json;
using StrawberryShake.Json;
using static StrawberryShake.ResultFields;
namespace StrawberryShake;
/// <summary>
/// The operation result builder will use the transport response and build from it
/// the operation result.
/// </summary>
/// <typeparam name="TResultData">
/// The runtime result.
/// </typeparam>
public abstract class OperationResultBuilder<TResultData>
: IOperationResultBuilder<JsonDocument, TResultData>
where TResultData : class
{
protected abstract IOperationResultDataFactory<TResultData> ResultDataFactory { get; }
public IOperationResult<TResultData> Build(
Response<JsonDocument> response)
{
TResultData? data = null;
IOperationResultDataInfo? dataInfo = null;
IReadOnlyList<IClientError>? errors = null;
IReadOnlyDictionary<string, object?>? extensions = null;
try
{
if (response.Body is { } body)
{
if (body.RootElement.TryGetProperty(Data, out var dataProp) &&
dataProp.ValueKind is JsonValueKind.Object)
{
dataInfo = BuildData(dataProp);
data = ResultDataFactory.Create(dataInfo);
}
if (body.RootElement.TryGetProperty(Errors, out var errorsProp) &&
errorsProp.ValueKind is JsonValueKind.Array)
{
errors = JsonErrorParser.ParseErrors(errorsProp);
}
if (body.RootElement.TryGetProperty(
ResultFields.Extensions,
out var extensionsProp) &&
extensionsProp.ValueKind is JsonValueKind.Object)
{
extensions = JsonExtensionParser.ParseExtensions(extensionsProp);
}
}
}
catch (Exception ex)
{
var list = new List<IClientError>
{
new ClientError(
ex.Message,
ErrorCodes.InvalidResultDataStructure,
exception: ex,
extensions: new Dictionary<string, object?>
{
{ nameof(ex.StackTrace), ex.StackTrace }
})
};
if (errors is not null)
{
list.AddRange(errors);
}
errors = list;
}
// If we have a transport error but the response does not contain any client errors
// we will create a client error from the provided transport error.
if (response.Exception is not null && errors is not { Count: > 0 })
{
errors = new IClientError[]
{
new ClientError(
response.Exception.Message,
ErrorCodes.InvalidResultDataStructure,
exception: response.Exception,
extensions: new Dictionary<string, object?>
{
{ nameof(response.Exception.StackTrace), response.Exception.StackTrace }
})
};
}
return new OperationResult<TResultData>(
data,
dataInfo,
ResultDataFactory,
errors,
extensions,
response.ContextData);
}
protected abstract IOperationResultDataInfo BuildData(JsonElement obj);
}