0.4.0: Claim, Models/ DTOs, compile
CI / publish (push) Failing after 39s
CI / check (push) Successful in 52s

LeaderboardSession.ClaimAsync sends onClaim. Generated DTOs live under Models/ with nullable wire fields. Remove incomplete duplicate type files.
This commit is contained in:
edmand46
2026-08-29 11:33:01 +03:00
parent 3c590294c9
commit ea20ea6d51
89 changed files with 1414 additions and 396 deletions
@@ -0,0 +1,117 @@
# Client, options, transports, abstractions
Source: `RudderClient.cs`, `RudderClientOptions.cs`, `HttpClientTransport.cs`,
`InMemoryTokenStore.cs`, `GuidDeviceIdProvider.cs`, `Abstractions/*.cs`.
## RudderClient
```csharp
public sealed class RudderClient
{
public AuthService Auth { get; }
public PlayerService Player { get; }
public RemoteConfigService RemoteConfig { get; }
public StorageService Storage { get; }
public ProjectStorageService ProjectStorage { get; }
public StoresService Stores { get; }
public LeaderboardsService Leaderboards { get; }
public InventoryService Inventory { get; }
public BattlePassService BattlePass { get; }
public QuestsService Quests { get; }
public ScenarioService Scenario { get; }
public RealtimeService Realtime { get; }
public string ProjectKey { get; }
public string? RealtimeUrl { get; }
public IClock Clock { get; } // defaults to DateTimeOffset.UtcNow
public RudderClient(RudderClientOptions options);
public void Update(float deltaTime); // pumps Scenario + Realtime; call every frame
}
```
Constructor throws `ArgumentException` when `BaseUrl` or `ProjectKey` is
missing. Every API call goes through the client: a 401 triggers one
single-flight refresh and one transparent retry (see errors.md).
## RudderClientOptions
```csharp
public sealed class RudderClientOptions
{
public string? BaseUrl { get; set; } // required
public string? RealtimeUrl { get; set; } // required only for Realtime
public string? ProjectKey { get; set; } // required
public IRudderTransport? Transport { get; set; } // default HttpClientTransport
public ITokenStore? TokenStore { get; set; } // default InMemoryTokenStore
public IDeviceIdProvider? DeviceIdProvider { get; set; }// default GuidDeviceIdProvider
public IRudderLogger? Logger { get; set; } // null = silent
public IClock? Clock { get; set; } // override in tests
public IPlanStateStore? PlanStateStore { get; set; } // scenario persistence between launches
public IPlanScheduler? Scheduler { get; set; } // optional delayed plan work
public IRealtimeTransportFactory? RealtimeTransportFactory { get; set; } // required only for Realtime
}
```
## Default implementations
- `HttpClientTransport(string baseUrl, HttpClient? httpClient = null)`
`IRudderTransport` over `HttpClient`, Newtonsoft.Json bodies, Bearer header,
10 s default timeout. Maps 401/404/429 to dedicated exception subclasses,
other non-success to `RudderApiException`, connectivity/timeout to
`RudderNetworkException`.
- `InMemoryTokenStore` — tokens in memory only; sessions do not survive an
app restart.
- `GuidDeviceIdProvider``Guid.NewGuid().ToString("N")` per instance; every
run looks like a fresh device to the backend.
## Abstractions (namespace `RudderSdk.Core.Abstractions`)
```csharp
public interface IRudderTransport
{
Task<TResponse> SendAsync<TRequest, TResponse>(
string method, string path, TRequest? request,
string? accessToken, CancellationToken cancellationToken = default);
}
public interface ITokenStore
{
string? GetAccessToken();
string? GetRefreshToken();
void SaveTokens(string accessToken, string refreshToken);
void Clear();
}
public interface IDeviceIdProvider { string DeviceId { get; } }
public interface IRudderLogger { void Log(RudderLogLevel level, string message); }
public enum RudderLogLevel { Debug, Info, Warning, Error }
public interface IClock { DateTimeOffset UtcNow { get; } }
public interface IPlanStateStore { string? State { get; set; } } // serialized scenario-run blob
public interface IPlanScheduler
{
Task ScheduleAsync(TimeSpan delay, CancellationToken cancellationToken = default);
}
public interface IRealtimeTransport
{
event Action Closed;
event Action<ArraySegment<byte>> Received;
event Action<Exception> Error;
bool IsConnected { get; }
Task ConnectAsync(Uri uri, TimeSpan timeout, CancellationToken cancellationToken = default);
Task SendAsync(ArraySegment<byte> data, CancellationToken cancellationToken = default);
Task CloseAsync(CancellationToken cancellationToken = default);
void Update(float deltaTime);
}
public interface IRealtimeTransportFactory { IRealtimeTransport Create(); }
```
Production guidance from the sources: provide a durable `ITokenStore`
(player prefs, keychain) and a persistent `IDeviceIdProvider` (Unity uses
`SystemInfo.deviceUniqueIdentifier`).