Skip to content

Commit eee0909

Browse files
committed
docs(client): enforce xml docs and annotate public api
1 parent a46da2e commit eee0909

17 files changed

Lines changed: 535 additions & 46 deletions

src/GoAffPro.Client/Events/AffiliateDetectedEventArgs.cs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,22 @@
22

33
namespace GoAffPro.Client.Events;
44

5-
public sealed class AffiliateDetectedEventArgs(GoAffProAffiliate affiliate) : EventArgs
5+
/// <summary>
6+
/// Event arguments for <see cref="GoAffProEventDetector.AffiliateDetected"/>.
7+
/// </summary>
8+
public sealed class AffiliateDetectedEventArgs : EventArgs
69
{
7-
public GoAffProAffiliate Affiliate { get; } = affiliate;
10+
/// <summary>
11+
/// Initializes a new instance of the <see cref="AffiliateDetectedEventArgs"/> class.
12+
/// </summary>
13+
/// <param name="affiliate">Detected affiliate payload.</param>
14+
public AffiliateDetectedEventArgs(GoAffProAffiliate affiliate)
15+
{
16+
Affiliate = affiliate;
17+
}
18+
19+
/// <summary>
20+
/// Gets the detected affiliate payload.
21+
/// </summary>
22+
public GoAffProAffiliate Affiliate { get; }
823
}

src/GoAffPro.Client/Events/AffiliateEvent.cs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,27 @@
22

33
namespace GoAffPro.Client.Events;
44

5-
public sealed record AffiliateEvent(GoAffProAffiliate Affiliate)
5+
/// <summary>
6+
/// Represents a detected affiliate/traffic feed event.
7+
/// </summary>
8+
public sealed record AffiliateEvent
69
{
10+
/// <summary>
11+
/// Initializes a new instance of the <see cref="AffiliateEvent"/> record.
12+
/// </summary>
13+
/// <param name="affiliate">The detected affiliate payload.</param>
14+
public AffiliateEvent(GoAffProAffiliate affiliate)
15+
{
16+
Affiliate = affiliate;
17+
}
18+
19+
/// <summary>
20+
/// Gets the strongly typed affiliate payload.
21+
/// </summary>
22+
public GoAffProAffiliate Affiliate { get; init; }
23+
24+
/// <summary>
25+
/// Gets the unique event identifier.
26+
/// </summary>
727
public string Id => Affiliate.Id;
828
}

src/GoAffPro.Client/Events/GoAffProEventDetector.cs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@
33

44
namespace GoAffPro.Client.Events;
55

6+
/// <summary>
7+
/// Polling-based event detector for GoAffPro feed endpoints.
8+
/// </summary>
9+
/// <remarks>
10+
/// The detector keeps in-memory seen ID sets and does not persist state.
11+
/// </remarks>
612
public sealed class GoAffProEventDetector
713
{
814
private readonly IGoAffProClient _client;
@@ -11,6 +17,12 @@ public sealed class GoAffProEventDetector
1117
private readonly HashSet<string> _seenAffiliateIds = [];
1218
private readonly HashSet<string> _seenOrderIds = [];
1319

20+
/// <summary>
21+
/// Initializes a new instance of the <see cref="GoAffProEventDetector"/> class.
22+
/// </summary>
23+
/// <param name="client">Client used for feed polling operations.</param>
24+
/// <param name="pollingInterval">Polling interval. Defaults to 30 seconds.</param>
25+
/// <param name="pageSize">Number of feed records requested per poll. Must be greater than zero.</param>
1426
public GoAffProEventDetector(
1527
IGoAffProClient client,
1628
TimeSpan? pollingInterval = null,
@@ -27,13 +39,30 @@ public GoAffProEventDetector(
2739
_pageSize = pageSize;
2840
}
2941

42+
/// <summary>
43+
/// Raised when a new order item is detected.
44+
/// </summary>
3045
public event EventHandler<OrderDetectedEventArgs>? OrderDetected;
3146

47+
/// <summary>
48+
/// Raised when a new affiliate/traffic item is detected.
49+
/// </summary>
3250
public event EventHandler<AffiliateDetectedEventArgs>? AffiliateDetected;
3351

52+
/// <summary>
53+
/// Raised when a new reward item is detected.
54+
/// </summary>
55+
/// <remarks>
56+
/// Currently disabled because <c>/user/feed/rewards</c> is returning HTTP 404
57+
/// as observed on 2026-02-18.
58+
/// </remarks>
3459
[Obsolete("Disabled because /user/feed/rewards currently returns HTTP 404 (observed on 2026-02-18).")]
3560
public event EventHandler<RewardDetectedEventArgs>? RewardDetected;
3661

62+
/// <summary>
63+
/// Starts continuous polling and raises events when new items are found.
64+
/// </summary>
65+
/// <param name="cancellationToken">Cancellation token used to stop polling.</param>
3766
public async Task StartAsync(CancellationToken cancellationToken = default)
3867
{
3968
// Referenced intentionally so the temporarily-disabled event remains part of the public surface.
@@ -57,6 +86,11 @@ public async Task StartAsync(CancellationToken cancellationToken = default)
5786
}
5887
}
5988

89+
/// <summary>
90+
/// Streams newly detected order events.
91+
/// </summary>
92+
/// <param name="cancellationToken">Cancellation token used to stop polling.</param>
93+
/// <returns>An async stream of new order events.</returns>
6094
public async IAsyncEnumerable<OrderEvent> NewOrdersAsync([EnumeratorCancellation] CancellationToken cancellationToken = default)
6195
{
6296
while (!cancellationToken.IsCancellationRequested)
@@ -71,6 +105,11 @@ public async IAsyncEnumerable<OrderEvent> NewOrdersAsync([EnumeratorCancellation
71105
}
72106
}
73107

108+
/// <summary>
109+
/// Streams newly detected affiliate events.
110+
/// </summary>
111+
/// <param name="cancellationToken">Cancellation token used to stop polling.</param>
112+
/// <returns>An async stream of new affiliate events.</returns>
74113
public async IAsyncEnumerable<AffiliateEvent> NewAffiliatesAsync([EnumeratorCancellation] CancellationToken cancellationToken = default)
75114
{
76115
while (!cancellationToken.IsCancellationRequested)
@@ -85,6 +124,15 @@ public async IAsyncEnumerable<AffiliateEvent> NewAffiliatesAsync([EnumeratorCanc
85124
}
86125
}
87126

127+
/// <summary>
128+
/// Streams newly detected reward events.
129+
/// </summary>
130+
/// <param name="cancellationToken">Cancellation token used to stop polling.</param>
131+
/// <returns>An async stream of reward events.</returns>
132+
/// <remarks>
133+
/// Currently disabled because <c>/user/feed/rewards</c> is returning HTTP 404
134+
/// as observed on 2026-02-18.
135+
/// </remarks>
88136
[Obsolete("Disabled because /user/feed/rewards currently returns HTTP 404 (observed on 2026-02-18).")]
89137
public async IAsyncEnumerable<RewardEvent> NewRewardsAsync([EnumeratorCancellation] CancellationToken cancellationToken = default)
90138
{

src/GoAffPro.Client/Events/OrderDetectedEventArgs.cs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,22 @@
22

33
namespace GoAffPro.Client.Events;
44

5-
public sealed class OrderDetectedEventArgs(GoAffProOrder order) : EventArgs
5+
/// <summary>
6+
/// Event arguments for <see cref="GoAffProEventDetector.OrderDetected"/>.
7+
/// </summary>
8+
public sealed class OrderDetectedEventArgs : EventArgs
69
{
7-
public GoAffProOrder Order { get; } = order;
10+
/// <summary>
11+
/// Initializes a new instance of the <see cref="OrderDetectedEventArgs"/> class.
12+
/// </summary>
13+
/// <param name="order">Detected order payload.</param>
14+
public OrderDetectedEventArgs(GoAffProOrder order)
15+
{
16+
Order = order;
17+
}
18+
19+
/// <summary>
20+
/// Gets the detected order payload.
21+
/// </summary>
22+
public GoAffProOrder Order { get; }
823
}

src/GoAffPro.Client/Events/OrderEvent.cs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,27 @@
22

33
namespace GoAffPro.Client.Events;
44

5-
public sealed record OrderEvent(GoAffProOrder Order)
5+
/// <summary>
6+
/// Represents a detected order feed event.
7+
/// </summary>
8+
public sealed record OrderEvent
69
{
10+
/// <summary>
11+
/// Initializes a new instance of the <see cref="OrderEvent"/> record.
12+
/// </summary>
13+
/// <param name="order">The detected order payload.</param>
14+
public OrderEvent(GoAffProOrder order)
15+
{
16+
Order = order;
17+
}
18+
19+
/// <summary>
20+
/// Gets the strongly typed order payload.
21+
/// </summary>
22+
public GoAffProOrder Order { get; init; }
23+
24+
/// <summary>
25+
/// Gets the unique event identifier.
26+
/// </summary>
727
public string Id => Order.Id;
828
}

src/GoAffPro.Client/Events/RewardDetectedEventArgs.cs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,26 @@
22

33
namespace GoAffPro.Client.Events;
44

5-
public sealed class RewardDetectedEventArgs(GoAffProReward reward) : EventArgs
5+
/// <summary>
6+
/// Event arguments for <see cref="GoAffProEventDetector.RewardDetected"/>.
7+
/// </summary>
8+
/// <remarks>
9+
/// Reward feed detection is currently disabled because <c>/user/feed/rewards</c>
10+
/// is returning HTTP 404 as observed on 2026-02-18.
11+
/// </remarks>
12+
public sealed class RewardDetectedEventArgs : EventArgs
613
{
7-
public GoAffProReward Reward { get; } = reward;
14+
/// <summary>
15+
/// Initializes a new instance of the <see cref="RewardDetectedEventArgs"/> class.
16+
/// </summary>
17+
/// <param name="reward">Detected reward payload.</param>
18+
public RewardDetectedEventArgs(GoAffProReward reward)
19+
{
20+
Reward = reward;
21+
}
22+
23+
/// <summary>
24+
/// Gets the detected reward payload.
25+
/// </summary>
26+
public GoAffProReward Reward { get; }
827
}

src/GoAffPro.Client/Events/RewardEvent.cs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,31 @@
22

33
namespace GoAffPro.Client.Events;
44

5-
public sealed record RewardEvent(GoAffProReward Reward)
5+
/// <summary>
6+
/// Represents a detected reward feed event.
7+
/// </summary>
8+
/// <remarks>
9+
/// Reward feed detection is currently disabled because <c>/user/feed/rewards</c>
10+
/// is returning HTTP 404 as observed on 2026-02-18.
11+
/// </remarks>
12+
public sealed record RewardEvent
613
{
14+
/// <summary>
15+
/// Initializes a new instance of the <see cref="RewardEvent"/> record.
16+
/// </summary>
17+
/// <param name="reward">The detected reward payload.</param>
18+
public RewardEvent(GoAffProReward reward)
19+
{
20+
Reward = reward;
21+
}
22+
23+
/// <summary>
24+
/// Gets the strongly typed reward payload.
25+
/// </summary>
26+
public GoAffProReward Reward { get; init; }
27+
28+
/// <summary>
29+
/// Gets the unique event identifier.
30+
/// </summary>
731
public string Id => Reward.Id;
832
}

src/GoAffPro.Client/Exceptions/GoAffProApiException.cs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,30 +2,61 @@
22

33
namespace GoAffPro.Client.Exceptions;
44

5+
/// <summary>
6+
/// Represents an error returned by the GoAffPro API.
7+
/// </summary>
58
public sealed class GoAffProApiException : Exception
69
{
10+
/// <summary>
11+
/// Initializes a new instance of the <see cref="GoAffProApiException"/> class.
12+
/// </summary>
713
public GoAffProApiException()
814
{
915
}
1016

17+
/// <summary>
18+
/// Initializes a new instance of the <see cref="GoAffProApiException"/> class
19+
/// with a specified error message.
20+
/// </summary>
21+
/// <param name="message">Exception message.</param>
1122
public GoAffProApiException(string message)
1223
: base(message)
1324
{
1425
}
1526

27+
/// <summary>
28+
/// Initializes a new instance of the <see cref="GoAffProApiException"/> class
29+
/// with a specified error message and inner exception.
30+
/// </summary>
31+
/// <param name="message">Exception message.</param>
32+
/// <param name="innerException">Inner exception that caused this failure.</param>
1633
public GoAffProApiException(string message, Exception innerException)
1734
: base(message, innerException)
1835
{
1936
}
2037

38+
/// <summary>
39+
/// Initializes a new instance of the <see cref="GoAffProApiException"/> class
40+
/// with status and response information.
41+
/// </summary>
42+
/// <param name="message">Exception message.</param>
43+
/// <param name="statusCode">HTTP status code returned by the API.</param>
44+
/// <param name="responseBody">Raw response body returned by the API, when available.</param>
45+
/// <param name="innerException">Underlying exception, when available.</param>
2146
public GoAffProApiException(string message, HttpStatusCode statusCode, string? responseBody = null, Exception? innerException = null)
2247
: base(message, innerException)
2348
{
2449
StatusCode = statusCode;
2550
ResponseBody = responseBody;
2651
}
2752

53+
/// <summary>
54+
/// Gets the HTTP status code returned by the API.
55+
/// </summary>
2856
public HttpStatusCode StatusCode { get; }
2957

58+
/// <summary>
59+
/// Gets the raw response body returned by the API, when available.
60+
/// </summary>
3061
public string? ResponseBody { get; }
3162
}

src/GoAffPro.Client/GoAffPro.Client.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
<ImplicitUsings>enable</ImplicitUsings>
66
<Nullable>enable</Nullable>
77
<IsPackable>true</IsPackable>
8+
<GenerateDocumentationFile>true</GenerateDocumentationFile>
89
<PackageId>GoAffPro.Client</PackageId>
910
<MinVerTagPrefix>v</MinVerTagPrefix>
1011
<Description>A modern .NET client for the GoAffPro Affiliate Marketing API with automatic code generation and event detection.</Description>

0 commit comments

Comments
 (0)