Skip to content

Sofiane-77/Thresh

Repository files navigation

Thresh — A Modern .NET Library for League Client (LCU)

Thresh logo

Thresh is a production-minded .NET library for integrating with the League Client API (LCU). It is a low-level, modular, DI-first infrastructure library designed for composability, operational reliability, and clear ownership boundaries.

License: MIT .NET CI Docs

Highlights

  • Async-first, DI-first API design
  • Resilient HTTP primitives built on HttpClientFactory + Polly v8
  • Real-time event streaming over WAMP WebSocket (OnJsonApiEvent)
  • Flexible subscriptions by URI and Regex, with optional initial snapshot hydration
  • Observability hooks via ILogger, Meter, and ActivitySource("Thresh")
  • Production-ready repository structure with tests, samples, benchmarks, and DocFX docs

Runtime and platform support

Supported target frameworks for runtime packages:

  • net8.0
  • net10.0

Officially supported operating systems:

  • Windows
  • macOS

Lockfile discovery follows a platform-aware, deterministic order:

  1. LCU_LOCKFILE environment override
  2. cached lockfile path (when still valid)
  3. process-derived lockfile candidates
  4. known install paths per platform

For unsupported layouts (custom launchers, Wine/Proton variants), use LCU_LOCKFILE explicitly. Process-based discovery is best-effort and may depend on local process inspection permissions.

Typical use cases

Thresh is intended for developers who want reliable LCU primitives without adopting a high-level application framework.

Common uses include:

  • building typed clients or endpoint groups on top of ILcuHttpClient
  • subscribing to LCU JSON API events through IEventStream with URI- or regex-based matching
  • running LCU integrations inside hosted services, workers, or background agents with DI and structured logging
  • composing your own retry, health, observability, and lifecycle boundaries around a small set of focused abstractions

Thresh intentionally stops at transport, discovery, and event primitives. Higher-level workflows remain in consumer code or optional packages.

Choosing a package

Package Use when Includes
Thresh.Extensions You want the core runtime stack with DI registration ILcuHttpClient, IEventStream, retries, auth handler, observability wiring
Thresh.Endpoints You want typed endpoint groups on top of ILcuHttpClient Summoner, gameflow, champ select, and lobby typed clients
Thresh.Hosting You run Thresh inside a hosted/background process Hosting integration and lifecycle-friendly wiring
Thresh.HealthChecks You expose health probes in service environments LCU health check integration
Thresh.Reactive You prefer reactive composition over callbacks Rx-friendly wrappers around stream events

For most applications, start with Thresh.Extensions, then add optional packages only where they fit your composition model.

Thresh.Extensions is the main entry package for runtime composition.

Installation

dotnet add package Thresh.Extensions

Quick Start

Thresh.Extensions wires the low-level runtime stack into DI. The example below uses one relative HTTP request to read the current gameflow state, then subscribes to the same route for subsequent updates.

using System.Text.Json;

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

using Thresh.Abstractions;
using Thresh.Extensions;

var services = new ServiceCollection()
    .AddLogging(b => b.AddSimpleConsole())
    .AddThresh(o =>
    {
        o.AcceptSelfSignedCertificates = true;    // LCU HTTP (loopback only)
        o.WsAcceptSelfSignedCertificates = true;  // LCU WebSocket (loopback only)
    });

await using var provider = services.BuildServiceProvider();

var api = provider.GetRequiredService<ILcuHttpClient>();
var ws = provider.GetRequiredService<IEventStream>();

var session = await api.GetAsync<JsonElement>("/lol-gameflow/v1/session");
var initialPhase = session.TryGetProperty("phase", out var phaseValue) ? phaseValue.GetString() : "?";
Console.WriteLine($"Current phase = {initialPhase}");

await ws.ConnectAsync();
await ws.WaitUntilConnectedAsync(TimeSpan.FromSeconds(3));

using var sub = ws.Subscribe<JsonElement>("/lol-gameflow/v1/session", data =>
{
    var phase = data.TryGetProperty("phase", out var p) ? p.GetString() : "?";
    Console.WriteLine($"Phase changed = {phase}");
}, withSnapshot: false);

var listenFor = TimeSpan.FromSeconds(10);
await Task.Delay(listenFor);

Use relative LCU paths where possible; Thresh rebases them to the active lockfile-derived base address. The short delay keeps the sample alive long enough for subscription callbacks to fire. For longer-running examples, see samples/Thresh.Samples.Console.

Ensure the League Client is running, or set the LCU_LOCKFILE environment variable.

Sample runner

Try the sample project to validate your local environment quickly:

dotnet run --project samples/Thresh.Samples.Console/Thresh.Samples.Console.csproj -- --help

Then run a specific demo (for example http-get or sub-typed-snapshot) once the client is running.

Safety and trust model

Thresh assumes a local LCU trust boundary and intentionally applies a strict fail-fast policy for LCU-authenticated HTTP calls.

  • Prefer relative LCU paths. Thresh rebases them to the active lockfile-derived LCU base address.
  • Thresh enforces credentials only for safe destinations.
  • Absolute URIs are accepted only when all checks pass: HTTPS, loopback host (127.0.0.1, ::1, or localhost), and active lockfile port.
  • Any other absolute URI is rejected before credentials are attached.
  • Self-signed certificate acceptance options remain loopback-scoped.

This policy is designed to prevent credential leakage to non-local destinations.

Production readiness

Thresh is designed to be operationally safe in long-running processes while staying focused on infrastructure concerns:

  • HttpClientFactory + Polly retry/circuit-breaker policies
  • reconnect-aware event streaming
  • structured logging, metrics, and tracing hooks
  • explicit cancellation support across API surfaces
  • testability through abstractions (ILcuHttpClient, IEventStream, fakes/stubs)

Higher-level orchestration stays outside the core packages by design. See docs for production guidance on retries, observability baselines, and safe usage patterns.

Repository Layout

  • src/ — production libraries
  • tests/ — xUnit test projects
  • samples/ — executable usage examples
  • benchmarks/ — BenchmarkDotNet performance suite
  • docs/ — DocFX documentation source

Running benchmarks

Run deterministic benchmarks (default):

dotnet run -c Release --project benchmarks/Thresh.Benchmarks/Thresh.Benchmarks.csproj

When only deterministic benchmarks are available, the runner auto-selects and runs them directly—no interactive prompt.

Enable live-client benchmarks (optional, requires running League Client):

$env:THRESH_BENCH_LIVE = "1"
dotnet run -c Release --project benchmarks/Thresh.Benchmarks/Thresh.Benchmarks.csproj

When multiple benchmark groups are available, BenchmarkDotNet shows an interactive menu. You can:

  • Enter the benchmark number to run a specific group
  • Enter 0 or * to run all benchmarks
  • Enter a wildcard filter like *Deterministic* to select by name pattern

The live benchmark is environment-dependent and should be interpreted separately from deterministic runs.

Documentation

  • Start with docs/articles/overview.md
  • Build and preview docs locally:
dotnet tool update -g docfx
docfx docs/docfx.json --serve

Then open http://localhost:8080.

Build, Test, and Pack

Use the SDK pinned in global.json (currently .NET 10 feature band).

dotnet restore Thresh.slnx
dotnet build Thresh.slnx -c Release
dotnet test Thresh.slnx -c Release --no-build
dotnet pack Thresh.slnx -c Release --no-build -o ./artifacts

Release automation

Release hygiene remains lightweight and GitHub-native:

  • release-drafter keeps a rolling draft release from merged PRs.
  • Publishing runs from .github/workflows/publish.yml when a GitHub Release is published.
  • The publish job rebuilds, tests, and packs before pushing .nupkg artifacts to NuGet with duplicate-safe pushes.

For one-time setup and operational details, see docs/articles/release-process.md.

Contributing

Contributions are welcome. Please read CONTRIBUTING.md before opening an issue or pull request.

Security

If you discover a potential vulnerability, please follow the process in SECURITY.md.

License

This project is licensed under the MIT License.

About

Low-level, DI-first .NET infrastructure for League Client API (LCU) HTTP and event streaming

Topics

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages