Hapnd.Sdk
0.2.0
dotnet add package Hapnd.Sdk --version 0.2.0
NuGet\Install-Package Hapnd.Sdk -Version 0.2.0
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Hapnd.Sdk" Version="0.2.0" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Hapnd.Sdk" Version="0.2.0" />
<PackageReference Include="Hapnd.Sdk" />
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Hapnd.Sdk --version 0.2.0
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
#r "nuget: Hapnd.Sdk, 0.2.0"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Hapnd.Sdk@0.2.0
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Hapnd.Sdk&version=0.2.0
#tool nuget:?package=Hapnd.Sdk&version=0.2.0
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
Hapnd SDK for .NET
The official .NET SDK for Hapnd - the event sourcing platform built for engineers.
Installation
dotnet add package Hapnd.Sdk
Quick Start
using Hapnd.Sdk;
// Create a client
var hapnd = new HapndClient("sk_live_your_api_key");
// Append an event
var result = await hapnd.Aggregate("order_123")
.Append(new OrderPlaced { CustomerId = "cust_456" });
Console.WriteLine($"Event {result.EventId} at version {result.Version}");
// Get aggregate state (if sync projection is bound)
if (result.HasState)
{
var state = result.State<OrderState>();
Console.WriteLine($"Order total: {state.Total}");
}
Features
- Fluent API - Chain operations naturally
- Convention-based aggregate types -
order_123→ aggregate typeorder - Optimistic concurrency - Prevent lost updates with version checks
- Built-in resilience - Automatic retries and circuit breaker
- ASP.NET Core integration - First-class dependency injection support
Usage
Appending Events
// Simple append
await hapnd.Aggregate("order_123")
.Append(new ItemAdded { Item = "Widget", Price = 25.00m });
// With optimistic concurrency
await hapnd.Aggregate("order_123")
.ExpectVersion(5)
.Append(new ItemAdded { Item = "Gadget", Price = 15.00m });
// With metadata for tracing
await hapnd.Aggregate("order_123")
.WithCorrelation("req_abc123")
.WithCausation("evt_xyz789")
.WithMetadata(new { UserId = "user_456" })
.Append(new OrderShipped());
// Multiple events atomically
await hapnd.Aggregate("order_123")
.AppendMany([
new ItemAdded { Item = "Widget", Price = 25.00m },
new ItemAdded { Item = "Gadget", Price = 15.00m }
]);
Querying State
var aggregate = await hapnd.Aggregate("order_123")
.GetState<OrderState>();
if (aggregate is not null)
{
Console.WriteLine($"Version: {aggregate.Version}");
Console.WriteLine($"Total: {aggregate.State.Total}");
Console.WriteLine($"Items: {aggregate.State.ItemCount}");
}
Custom Aggregate Types
By default, aggregate type is inferred from the ID prefix:
| Aggregate ID | Inferred Type |
|---|---|
order_123 |
order |
cart-abc |
cart |
customer_456 |
customer |
For non-standard IDs, specify explicitly:
await hapnd.Aggregate("ORD-2024-00123")
.WithAggregateType("order")
.Append(new OrderPlaced());
Custom Event Type Names
By default, the class name is used as the event type. Override with an attribute:
[EventType("order_placed")]
public class OrderPlaced
{
public string CustomerId { get; init; }
}
ASP.NET Core Integration
// In Program.cs or Startup.cs
services.AddHapnd("sk_live_your_api_key");
// Or with configuration
services.AddHapnd(options =>
{
options.ApiKey = configuration["Hapnd:ApiKey"];
options.Timeout = TimeSpan.FromSeconds(60);
});
Then inject IHapndClient:
public class OrderService
{
private readonly IHapndClient _hapnd;
public OrderService(IHapndClient hapnd)
{
_hapnd = hapnd;
}
public async Task PlaceOrder(string customerId)
{
var result = await _hapnd.Aggregate($"order_{Guid.NewGuid()}")
.Append(new OrderPlaced { CustomerId = customerId });
}
}
Resilience
The SDK includes automatic retry and circuit breaker policies.
Default Behavior
- Retries: 3 attempts with exponential backoff
- Circuit Breaker: Opens after 50% failure rate (minimum 10 requests)
Configuration
services.AddHapnd(options =>
{
options.ApiKey = "sk_live_your_api_key";
options.Resilience = new HapndResilienceOptions
{
MaxRetryAttempts = 5,
RetryDelay = TimeSpan.FromMilliseconds(200),
EnableCircuitBreaker = true,
CircuitBreakerDuration = TimeSpan.FromSeconds(60)
};
});
Disable Resilience
options.Resilience = null;
Error Handling
using Hapnd.Sdk;
using Polly.CircuitBreaker;
try
{
await hapnd.Aggregate("order_123")
.ExpectVersion(5)
.Append(new ItemAdded { Item = "Widget" });
}
catch (HapndConcurrencyException ex)
{
// Version mismatch - reload and retry
Console.WriteLine($"Expected version {ex.ExpectedVersion}, actual {ex.ActualVersion}");
}
catch (HapndApiException ex)
{
// Server returned an error
Console.WriteLine($"API error {ex.StatusCode}: {ex.Message}");
}
catch (HapndNetworkException ex)
{
// Network failure or timeout
Console.WriteLine($"Network error: {ex.Message}");
}
catch (BrokenCircuitException)
{
// Circuit breaker is open - back off
Console.WriteLine("Service unavailable, try again later");
}
Exception Hierarchy
| Exception | When |
|---|---|
HapndValidationException |
Client-side validation failed |
HapndApiException |
Server returned an error |
HapndConcurrencyException |
Version mismatch (409) |
HapndAggregateTypeMismatchException |
Wrong aggregate type |
HapndNetworkException |
Network failure or timeout |
BrokenCircuitException |
Circuit breaker open (from Polly) |
Requirements
- .NET 9.0 or later
License
Apache 2.0 - see LICENSE for details.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
-
net10.0
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.2)
- Microsoft.Extensions.Http (>= 10.0.2)
- Microsoft.Extensions.Http.Resilience (>= 10.2.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.2.0 | 106 | 4/20/2026 |