### Full Program.cs Example with Event Handling Source: https://github.com/rcommon-team/rcommon/blob/main/website/build/llms-full.txt A complete Program.cs example demonstrating how to build a host, configure RCommon with event handling, and produce events. Ensure you have the necessary RCommon and MediatR packages installed. ```csharp using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using RCommon; using RCommon.EventHandling.Producers; using RCommon.MediatR; using RCommon.MediatR.Producers; var host = Host.CreateDefaultBuilder(args) .ConfigureServices(services => { services.AddRCommon() .WithEventHandling(eventHandling => { eventHandling.AddProducer(); eventHandling.AddSubscriber(); }); }).Build(); Console.WriteLine("Example Starting"); var eventProducers = host.Services.GetServices(); var testEvent = new TestEvent(DateTime.Now, Guid.NewGuid()); foreach (var producer in eventProducers) { await producer.ProduceEventAsync(testEvent); } Console.WriteLine("Example Complete"); ``` -------------------------------- ### Basic RCommon Setup Source: https://github.com/rcommon-team/rcommon/blob/main/website/build/docs/core-concepts/fluent-configuration.html Use this minimal configuration when only the built-in event infrastructure is needed and GUID generation or system time abstractions are not required. ```csharp builder.Services.AddRCommon(); ``` -------------------------------- ### Basic Finbuckle and RCommon Setup Source: https://github.com/rcommon-team/rcommon/blob/main/website/build/docs/multi-tenancy/finbuckle.html Configure Finbuckle for tenant resolution and then integrate it with RCommon using the `WithMultiTenancy` extension. This example uses a header strategy for tenant identification. ```csharp using RCommon; using RCommon.Finbuckle; using Finbuckle.MultiTenant; var builder = WebApplication.CreateBuilder(args); // 1. Configure Finbuckle tenant resolution. builder.Services.AddMultiTenant() .WithHeaderStrategy("X-Tenant-Id") .WithConfigurationStore(); // 2. Configure RCommon, including the Finbuckle multi-tenancy adapter. builder.Services.AddRCommon(config => { config .WithClaimsAndPrincipalAccessorForWeb() .WithPersistence(ef => { ef.AddDbContext( "App", options => options.UseSqlServer( builder.Configuration.GetConnectionString("Default"))); ef.SetDefaultDataStore(ds => ds.DefaultDataStoreName = "App"); }) .WithMultiTenancy>(mt => { // FinbuckleTenantIdAccessor is registered automatically. }); }); var app = builder.Build(); // 3. Add the Finbuckle middleware so tenant resolution runs on every request. app.UseMultiTenant(); app.MapControllers(); app.Run(); ``` -------------------------------- ### Full Program Example with InMemoryEventBus Source: https://github.com/rcommon-team/rcommon/blob/main/website/build/docs/examples-recipes/event-handling.html A complete Program.cs example demonstrating the setup and usage of RCommon's event handling with an in-memory event bus. Includes service configuration and event publishing. ```csharp using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using RCommon; using RCommon.EventHandling; using RCommon.EventHandling.Producers; var host = Host.CreateDefaultBuilder(args) .ConfigureServices(services => { services.AddRCommon() .WithEventHandling(eventHandling => { eventHandling.AddProducer(); eventHandling.AddSubscriber(); }); }).Build(); Console.WriteLine("Example Starting"); var eventProducers = host.Services.GetServices(); var testEvent = new TestEvent(DateTime.Now, Guid.NewGuid()); foreach (var producer in eventProducers) { await producer.ProduceEventAsync(testEvent); } Console.WriteLine("Example Complete"); ``` -------------------------------- ### Full Program Setup with Event Handling Source: https://github.com/rcommon-team/rcommon/blob/main/website/build/docs/examples-recipes/event-handling.html Configures RCommon with MediatR event handling, adding a producer and a subscriber. This is a complete program example. ```csharp using Microsoft.Extensions.DependencyInjection;using Microsoft.Extensions.Hosting;using RCommon;using RCommon.EventHandling.Producers;using RCommon.MediatR;using RCommon.MediatR.Producers;var host = Host.CreateDefaultBuilder(args) .ConfigureServices(services => { services.AddRCommon() .WithEventHandling(eventHandling => { eventHandling.AddProducer(); eventHandling.AddSubscriber(); }); }).Build();Console.WriteLine("Example Starting");var eventProducers = host.Services.GetServices();var testEvent = new TestEvent(DateTime.Now, Guid.NewGuid());foreach (var producer in eventProducers){ await producer.ProduceEventAsync(testEvent);} Console.WriteLine("Example Complete"); ``` -------------------------------- ### Full Program.cs for MassTransit Example Source: https://github.com/rcommon-team/rcommon/blob/main/website/docs/examples-recipes/messaging.mdx The complete `Program.cs` file for a MassTransit-based messaging example. It includes RCommon setup, MassTransit configuration with in-memory transport, and registers a background worker for publishing events. ```csharp using MassTransit; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using RCommon; using RCommon.EventHandling.Producers; using RCommon.MassTransit; using RCommon.MassTransit.Producers; var host = Host.CreateDefaultBuilder(args) .ConfigureServices(services => { services.AddRCommon() .WithEventHandling(eventHandling => { eventHandling.UsingInMemory((context, cfg) => { cfg.ConfigureEndpoints(context); }); eventHandling.AddProducer(); eventHandling.AddSubscriber(); }); services.AddHostedService(); }).Build(); await host.RunAsync(); ``` -------------------------------- ### RCommon Composition Root Setup Source: https://github.com/rcommon-team/rcommon/blob/main/website/docs/examples-recipes/hr-leave-management.mdx Configures RCommon services, including email, date/time, GUID generation, mediator, persistence, unit of work, and validation. This setup should be done in the Program.cs file. ```csharp builder.Services.AddRCommon() .WithClaimsAndPrincipalAccessor() .WithSendGridEmailServices(x => { var settings = builder.Configuration.Get(); x.SendGridApiKey = settings.SendGridApiKey; x.FromNameDefault = settings.FromNameDefault; x.FromEmailDefault = settings.FromEmailDefault; }) .WithDateTimeSystem(dateTime => dateTime.Kind = DateTimeKind.Utc) .WithSequentialGuidGenerator(guid => guid.DefaultSequentialGuidType = SequentialGuidType.SequentialAsString) .WithMediator(mediator => { mediator.AddRequest(); mediator.AddRequest, GetLeaveTypeListRequestHandler>(); // ... all other request/handler pairs mediator.Configure(config => { config.RegisterServicesFromAssemblies( typeof(ApplicationServicesRegistration).GetTypeInfo().Assembly); }); mediator.AddLoggingToRequestPipeline(); mediator.AddUnitOfWorkToRequestPipeline(); }) .WithPersistence(ef => { ef.AddDbContext( DataStoreNamesConst.LeaveManagement, options => options.UseSqlServer( builder.Configuration.GetConnectionString( DataStoreNamesConst.LeaveManagement))); ef.SetDefaultDataStore(dataStore => dataStore.DefaultDataStoreName = DataStoreNamesConst.LeaveManagement); }) .WithUnitOfWork(unitOfWork => { unitOfWork.SetOptions(options => { options.AutoCompleteScope = true; options.DefaultIsolation = IsolationLevel.ReadCommitted; }); }) .WithValidation(validation => { validation.AddValidatorsFromAssemblyContaining( typeof(ApplicationServicesRegistration)); }); ``` -------------------------------- ### Commit Documentation Changes Source: https://github.com/rcommon-team/rcommon/blob/main/docs/superpowers/plans/2026-03-23-rcommon-website.md Stages the documentation files within the 'website/docs/getting-started/' directory and commits the changes with a message indicating the writing of the 'Getting Started' section. ```bash git add website/docs/getting-started/ git commit -m "docs: write Getting Started section (5 pages)" ``` -------------------------------- ### Build Example Project Source: https://github.com/rcommon-team/rcommon/blob/main/docs/superpowers/plans/2026-04-05-security-abstractions-string-id.md Builds the HR.LeaveManagement.Persistence project within the CleanWithCQRS example to verify compilation after changes. ```bash dotnet build Examples/CleanWithCQRS/HR.LeaveManagement.Persistence/ --no-restore -v quiet ``` -------------------------------- ### Start Local Development Server Source: https://github.com/rcommon-team/rcommon/blob/main/website/README.md Starts a local development server for previewing documentation. Changes are reflected automatically without server restarts. ```bash yarn start ``` -------------------------------- ### Full Program for In-Memory Event Bus Example Source: https://github.com/rcommon-team/rcommon/blob/main/website/build/llms-full.txt Demonstrates a complete console application setup for RCommon's in-memory event bus, including service configuration and event publishing. ```csharp using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using RCommon; using RCommon.EventHandling; using RCommon.EventHandling.Producers; var host = Host.CreateDefaultBuilder(args) .ConfigureServices(services => { services.AddRCommon() .WithEventHandling(eventHandling => { eventHandling.AddProducer(); eventHandling.AddSubscriber(); }); }).Build(); Console.WriteLine("Example Starting"); var eventProducers = host.Services.GetServices(); var testEvent = new TestEvent(DateTime.Now, Guid.NewGuid()); foreach (var producer in eventProducers) { await producer.ProduceEventAsync(testEvent); } Console.WriteLine("Example Complete"); ``` -------------------------------- ### Usage Example for Distributed Caching Source: https://github.com/rcommon-team/rcommon/blob/main/website/build/docs/examples-recipes/caching.html Demonstrates how to retrieve an application service and use it to set and get data from the distributed cache. ```csharp var appService = host.Services.GetRequiredService(); appService.SetDistributedMemoryCache("test-key", typeof(TestDto), new TestDto("test data 1")); var testData1 = appService.GetDistributedMemoryCache("test-key"); Console.WriteLine(testData1.Message); // test data 1 ``` -------------------------------- ### Install Dependencies with Yarn Source: https://github.com/rcommon-team/rcommon/blob/main/website/README.md Run this command to install all necessary project dependencies. ```bash yarn ``` -------------------------------- ### EF Core Outbox Configuration Example Source: https://github.com/rcommon-team/rcommon/blob/main/docs/superpowers/specs/2026-03-21-transactional-outbox-design.md Example of configuring the EF Core persistence and its outbox using the generic builder extension. ```csharp builder.WithPersistence(ef => { ef.AddDbContext("default", options => ...); ef.AddOutbox(outbox => { outbox.PollingInterval = TimeSpan.FromSeconds(5); outbox.MaxRetries = 5; outbox.BatchSize = 100; }); }); ``` -------------------------------- ### Install dependencies with pnpm Source: https://github.com/rcommon-team/rcommon/blob/main/docs/superpowers/plans/2026-03-23-rcommon-website.md Navigates into the website directory and installs project dependencies using pnpm. This command should be run after updating the package.json. ```bash cd website && pnpm install ``` -------------------------------- ### Full Program.cs Example Source: https://github.com/rcommon-team/rcommon/blob/main/website/build/docs/next/examples-recipes/event-handling.html Demonstrates a complete Program.cs file for setting up RCommon with event handling, including adding producers and subscribers. ```csharp using Microsoft.Extensions.DependencyInjection;using Microsoft.Extensions.Hosting;using RCommon;using RCommon.EventHandling.Producers;using RCommon.MediatR;using RCommon.MediatR.Producers;var host = Host.CreateDefaultBuilder(args) .ConfigureServices(services => { services.AddRCommon() .WithEventHandling(eventHandling => { eventHandling.AddProducer(); eventHandling.AddSubscriber(); }); }).Build(); Console.WriteLine("Example Starting"); var eventProducers = host.Services.GetServices(); var testEvent = new TestEvent(DateTime.Now, Guid.NewGuid()); foreach (var producer in eventProducers) { await producer.ProduceEventAsync(testEvent); } Console.WriteLine("Example Complete"); ``` -------------------------------- ### Bootstrap RCommon Services with DI Source: https://github.com/rcommon-team/rcommon/blob/main/Src/RCommon.Core/README.md Configure RCommon services within your Microsoft Dependency Injection setup using the fluent AddRCommon() builder. This example shows how to configure GUID generation, system time, and event handling with a custom subscriber. ```csharp using RCommon; using RCommon.EventHandling; // Bootstrap RCommon in your DI configuration services.AddRCommon(builder => { builder .WithSequentialGuidGenerator(options => options.DefaultSequentialGuidType = SequentialGuidType.SequentialAsString) .WithDateTimeSystem(options => options.Kind = DateTimeKind.Utc) .WithEventHandling(eventHandling => { eventHandling.AddSubscriber(); }); }); ``` -------------------------------- ### Using a Fake GUID Generator in Unit Tests Source: https://github.com/rcommon-team/rcommon/blob/main/website/build/docs/next/core-concepts/guid-generation.html Provides an example of creating a test double for `IGuidGenerator` to control the GUID values returned during unit testing, ensuring predictable test outcomes. ```APIDOC ## Using a Fake GUID Generator in Unit Tests ### Description Illustrates how to substitute `IGuidGenerator` with a test double (fake implementation) that returns a known, predictable value. This is crucial for writing reliable unit tests. ### Fake Implementation Example ```csharp public class FakeGuidGenerator : IGuidGenerator { private readonly Guid _value; public FakeGuidGenerator(Guid value) { _value = value; } public Guid Create() => _value; } ``` ### Unit Test Usage Example ```csharp // Arrange var knownId = Guid.Parse("00000000-0000-0000-0000-000000000001"); var service = new OrderService(new FakeGuidGenerator(knownId)); // Act var order = service.CreateOrder(customerId); // Assert Assert.Equal(knownId, order.Id); ``` ``` -------------------------------- ### TestRepository Setup and Test Method Source: https://github.com/rcommon-team/rcommon/blob/main/website/build/docs/next/testing/test-base-classes.html Demonstrates setting up TestRepository with a DbContext and performing a basic test to find a customer by primary key. Includes setup and teardown logic for managing test data. ```csharp using RCommon.TestBase.Data; using RCommon.TestBase; [TestFixture] public class CustomerRepositoryTests{ private TestRepository _testRepo; [SetUp] public void SetUp() { // Initialize with a real or in-memory DbContext var context = /* resolve AppDbContext */; _testRepo = new TestRepository(context); } [TearDown] public void TearDown() { // Remove only the entities created during this test _testRepo.CleanUpSeedData(); } [Test] public async Task FindAsync_ByPrimaryKey_ReturnsMatchingCustomer() { // Arrange — seed a known customer var seeded = _testRepo.Prepare_Can_Find_Async_By_Primary_Key(); // Act var found = await _customerRepository.FindAsync(seeded.Id); // Assert Assert.That(found, Is.Not.Null); Assert.That(found.FirstName, Is.EqualTo("Albus")); }} ``` -------------------------------- ### Build Website Components Source: https://github.com/rcommon-team/rcommon/blob/main/docs/superpowers/plans/2026-03-23-rcommon-website.md This command navigates to the website directory and executes the build process, displaying the first 50 lines of the output. This is used to verify that the newly created components compile correctly. ```bash cd website && pnpm build 2>&1 | head -50 ``` -------------------------------- ### Update Claims Identity Helper Example Source: https://github.com/rcommon-team/rcommon/blob/main/docs/superpowers/specs/2026-04-05-security-abstractions-string-id-design.md Illustrates the change in the return type for FindUserId from Guid? to string?. ```csharp string? userId = principal.FindUserId() ``` -------------------------------- ### Build and Serve for Version Verification Source: https://github.com/rcommon-team/rcommon/blob/main/docs/superpowers/plans/2026-03-23-rcommon-website.md Build the website and serve it locally to verify that the version dropdown in the navbar correctly displays '1.0' and 'Next'. ```bash cd website && pnpm build && pnpm serve ``` -------------------------------- ### Build Website Source: https://github.com/rcommon-team/rcommon/blob/main/docs/superpowers/plans/2026-03-25-website-seo-llm.md Build the website to verify changes. Navigate to the website directory and run the build command. ```bash cd website && pnpm build ``` -------------------------------- ### Full RCommon Configuration Chain Source: https://github.com/rcommon-team/rcommon/blob/main/website/build/llms-full.txt Example of a comprehensive RCommon configuration chain, including GUID generation, system time, and common factory services. ```csharp builder.Services.AddRCommon() .WithSimpleGuidGenerator() .WithDateTimeSystem(options => options.Kind = DateTimeKind.Utc) .WithCommonFactory(); ``` -------------------------------- ### Basic Finbuckle and RCommon Setup Source: https://github.com/rcommon-team/rcommon/blob/main/website/docs/multi-tenancy/finbuckle.mdx Configure Finbuckle tenant resolution and RCommon with the Finbuckle adapter. Ensure Finbuckle middleware is added to the request pipeline. ```csharp using RCommon; using RCommon.Finbuckle; using Finbuckle.MultiTenant; var builder = WebApplication.CreateBuilder(args); // 1. Configure Finbuckle tenant resolution. builder.Services.AddMultiTenant() .WithHeaderStrategy("X-Tenant-Id") .WithConfigurationStore(); // 2. Configure RCommon, including the Finbuckle multi-tenancy adapter. builder.Services.AddRCommon(config => { config .WithClaimsAndPrincipalAccessorForWeb() .WithPersistence(ef => { ef.AddDbContext( "App", options => options.UseSqlServer( builder.Configuration.GetConnectionString("Default"))); ef.SetDefaultDataStore(ds => ds.DefaultDataStoreName = "App"); }) .WithMultiTenancy>(mt => { // FinbuckleTenantIdAccessor is registered automatically. }); }); var app = builder.Build(); // 3. Add the Finbuckle middleware so tenant resolution runs on every request. app.UseMultiTenant(); app.MapControllers(); app.Run(); ``` -------------------------------- ### Build the Solution with .NET CLI Source: https://github.com/rcommon-team/rcommon/blob/main/docs/superpowers/plans/2026-03-23-outbox-v2.md Execute this command to build the entire solution. Verify that there are no new errors or warnings, or only pre-existing warnings. ```bash dotnet build Src/RCommon.sln ``` -------------------------------- ### Demonstrate Caching Usage Source: https://github.com/rcommon-team/rcommon/blob/main/website/build/docs/examples-recipes/caching.html This example shows how to use the caching mechanism. The first call to GetCustomers hits the database, while the second call retrieves data from the cache, demonstrating the effectiveness of caching. ```csharp var appService = host.Services.GetRequiredService(); Console.WriteLine("Hitting the database w/ a query"); var customers = await appService.GetCustomers("my-test-key"); Console.WriteLine(customers); Console.WriteLine("Hitting the cache"); customers = await appService.GetCustomers("my-test-key"); Console.WriteLine(customers); // Second call returns from cache, no database roundtrip ``` -------------------------------- ### Create an Order Line Domain Entity Source: https://github.com/rcommon-team/rcommon/blob/main/website/build/docs/domain-driven-design/entities-aggregates.html Example of a child entity, OrderLine, inheriting from DomainEntity. It has its own identity but events must be raised on the aggregate root. ```csharp public class OrderLine : DomainEntity { public string ProductId { get; private set; } public int Quantity { get; private set; } public decimal UnitPrice { get; private set; } protected OrderLine() { } public OrderLine(string productId, int quantity, decimal unitPrice) { Id = Guid.NewGuid(); ProductId = productId; Quantity = quantity; UnitPrice = unitPrice; } public decimal LineTotal => Quantity * UnitPrice; ``` -------------------------------- ### Define a DbContext derived from RCommonDbContext Source: https://github.com/rcommon-team/rcommon/blob/main/website/build/llms-full.txt Your DbContext must inherit from RCommonDbContext to integrate with the IDataStoreFactory. This example shows a basic setup with DbSet properties and OnModelCreating configuration. ```csharp using Microsoft.EntityFrameworkCore; using RCommon.Persistence.EFCore; public class LeaveManagementDbContext : RCommonDbContext { public LeaveManagementDbContext(DbContextOptions options) : base(options) { } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.ApplyConfigurationsFromAssembly(typeof(LeaveManagementDbContext).Assembly); } public DbSet LeaveRequests { get; set; } public DbSet LeaveTypes { get; set; } public DbSet LeaveAllocations { get; set; } } ``` -------------------------------- ### Full Program Configuration with Event Handling Source: https://github.com/rcommon-team/rcommon/blob/main/website/docs/examples-recipes/event-handling.mdx This example shows a complete Program.cs file demonstrating how to configure RCommon's event handling with MediatR and add event producers and subscribers. ```csharp using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using RCommon; using RCommon.EventHandling.Producers; using RCommon.MediatR; using RCommon.MediatR.Producers; var host = Host.CreateDefaultBuilder(args) .ConfigureServices(services => { services.AddRCommon() .WithEventHandling(eventHandling => { eventHandling.AddProducer(); eventHandling.AddSubscriber(); }); }).Build(); Console.WriteLine("Example Starting"); var eventProducers = host.Services.GetServices(); var testEvent = new TestEvent(DateTime.Now, Guid.NewGuid()); foreach (var producer in eventProducers) { await producer.ProduceEventAsync(testEvent); } Console.WriteLine("Example Complete"); ``` -------------------------------- ### Basic Audited Entity Usage Source: https://github.com/rcommon-team/rcommon/blob/main/website/build/docs/domain-driven-design/auditing.html Example of an Invoice entity using AuditedEntity with Guid as the key and string for user identifiers. Stores customer name, total amount, and status. ```csharp public class Invoice : AuditedEntity{ public string CustomerName { get; private set; } public decimal TotalAmount { get; private set; } public InvoiceStatus Status { get; private set; } protected Invoice() { } public Invoice(Guid id, string customerName, decimal totalAmount) { Id = id; CustomerName = customerName; TotalAmount = totalAmount; Status = InvoiceStatus.Draft; } } ``` -------------------------------- ### RCommon Configuration Example Source: https://github.com/rcommon-team/rcommon/blob/main/docs/superpowers/plans/2026-03-23-rcommon-website.md Demonstrates how to configure RCommon with various builders for MediatR, MassTransit, Caching, and Validation. ```csharp .WithMediator(mediator => mediator.AddRequest()) .WithEventHandling(events => events.AddProducer()) .WithCaching() .WithValidation(); ``` -------------------------------- ### RCommon Setup with Custom TenantInfo Source: https://github.com/rcommon-team/rcommon/blob/main/website/build/docs/multi-tenancy/finbuckle.html Configure RCommon to use a custom `AppTenantInfo` class for multi-tenancy. This example uses a route strategy for tenant identification and an EF Core store. ```csharp builder.Services.AddMultiTenant() .WithRouteStrategy("tenant") .WithEFCoreStore(); builder.Services.AddRCommon(config => { config.WithMultiTenancy>(mt => { }); }); ``` -------------------------------- ### Configure and Build State Machine Source: https://github.com/rcommon-team/rcommon/blob/main/website/static/llms-full.txt Demonstrates how to use IStateMachineConfigurator to define state transitions, entry/exit actions, and build a machine instance. ```csharp public class OrderStateMachineService { private readonly IStateMachineConfigurator _configurator; public OrderStateMachineService(IStateMachineConfigurator configurator) { _configurator = configurator; _configurator.ForState(OrderState.Pending) .Permit(OrderTrigger.Approve, OrderState.Approved) .Permit(OrderTrigger.Cancel, OrderState.Cancelled); _configurator.ForState(OrderState.Approved) .Permit(OrderTrigger.Ship, OrderState.Shipped) .Permit(OrderTrigger.Cancel, OrderState.Cancelled) .OnEntry(async ct => { await NotifyWarehouseAsync(ct); }) .OnExit(async ct => { await LogStateChangeAsync("leaving Approved", ct); }); } public IStateMachine BuildFor(OrderState currentState) => _configurator.Build(currentState); } ``` -------------------------------- ### Add Meta Description to MDX Frontmatter Source: https://github.com/rcommon-team/rcommon/blob/main/docs/superpowers/plans/2026-03-25-website-seo-llm.md Add a `description` frontmatter field to MDX files to improve SEO. This is done for architecture guides, examples, testing, and API reference documentation. ```yaml description: "How RCommon fits into Clean Architecture — layer boundaries, dependency rules, and mapping abstractions to infrastructure." ``` ```yaml description: "Building microservices with RCommon — messaging, event handling, and persistence patterns for distributed .NET systems." ``` ```yaml description: "Event-driven architecture with RCommon — domain events, transactional outbox, and distributed messaging across bounded contexts." ``` -------------------------------- ### Build the Rcommon Website Source: https://github.com/rcommon-team/rcommon/blob/main/docs/superpowers/plans/2026-03-23-rcommon-website.md Navigate to the website directory and run the build command. This command outputs build logs, and `tail -20` shows the last 20 lines of the output, useful for verifying build success. ```bash cd website && pnpm build 2>&1 | tail -20 ``` -------------------------------- ### Using ICacheService for Get or Create Pattern Source: https://github.com/rcommon-team/rcommon/blob/main/website/build/llms-full.txt Inject ICacheService to implement the get-or-create pattern for caching data, eliminating the need for manual null checks. This example demonstrates fetching active products. ```csharp public class ProductCatalogService { private readonly ICacheService _cache; private readonly IProductRepository _repository; public ProductCatalogService(ICacheService cache, IProductRepository repository) { _cache = cache; _repository = repository; } public async Task> GetActiveProductsAsync(CancellationToken ct) { var key = CacheKey.With(typeof(ProductCatalogService), "active-products"); return await _cache.GetOrCreateAsync(key, () => { return _repository.FindAsync(p => p.IsActive).Result; }); } } ``` -------------------------------- ### Install RCommon.Authorization.Web Package Source: https://github.com/rcommon-team/rcommon/blob/main/Src/RCommon.Authorization.Web/README.md Use the .NET CLI to add the RCommon.Authorization.Web package to your project. ```shell dotnet add package RCommon.Authorization.Web ``` -------------------------------- ### Resolve and Use S3 Blob Store Source: https://github.com/rcommon-team/rcommon/blob/main/website/build/docs/blob-storage/s3.html Inject `IBlobStoreFactory` into your services to resolve and use named S3 blob stores. This example demonstrates uploading a report and getting a presigned download URL. ```csharp public class ReportStorageService { private readonly IBlobStorageService _storage; public ReportStorageService(IBlobStoreFactory factory) { _storage = factory.Resolve("primary"); } public async Task StoreReportAsync(string key, Stream pdf, CancellationToken ct = default) { await _storage.UploadAsync( containerName: "reports", blobName: key, content: pdf, options: new BlobUploadOptions { ContentType = "application/pdf" }, token: ct); } public async Task GetDownloadLinkAsync(string key, CancellationToken ct = default) { return await _storage.GetPresignedDownloadUrlAsync( containerName: "reports", blobName: key, expiry: TimeSpan.FromMinutes(15), token: ct); } } ``` -------------------------------- ### Build Documentation for Production Source: https://github.com/rcommon-team/rcommon/blob/main/website/README.md Generates static documentation files into the 'build' directory, ready for deployment on any static hosting service. ```bash yarn build ``` -------------------------------- ### Build Website with Static Assets Source: https://github.com/rcommon-team/rcommon/blob/main/docs/superpowers/plans/2026-03-25-website-seo-llm.md Builds the website to verify that static assets like robots.txt, favicon, and OG image are correctly included in the output. ```bash pnpm build ``` -------------------------------- ### Modify ClaimsPrincipal.FindUserId to return string Source: https://github.com/rcommon-team/rcommon/blob/main/docs/superpowers/plans/2026-04-05-security-abstractions-string-id.md Replaces the existing ClaimsPrincipal overload to extract the user identifier as a raw string. Use this when you need to get the user ID from a ClaimsPrincipal without converting it from a Guid. ```csharp /// /// Extracts the user identifier from the principal's claims as a raw string value. /// /// The claims principal to search. /// The user ID string, or null if the claim is missing or empty. public static string? FindUserId(this ClaimsPrincipal principal) { Guard.IsNotNull(principal, nameof(principal)); var userIdOrNull = principal.Claims?.FirstOrDefault(c => c.Type == ClaimTypesConst.UserId); if (userIdOrNull == null || userIdOrNull.Value.IsNullOrWhiteSpace()) { return null; } return userIdOrNull.Value; } ``` -------------------------------- ### Configure RCommon Services in a Module Source: https://github.com/rcommon-team/rcommon/blob/main/website/static/llms-full.txt Implement the IServiceModule interface to configure RCommon services within a specific module. This example shows how to add RCommon, a GUID generator, and persistence using Entity Framework Core. ```csharp public interface IServiceModule { void Configure(IServiceCollection services); } public sealed class OrderingModule : IServiceModule { public void Configure(IServiceCollection services) { services.AddRCommon() .WithSimpleGuidGenerator() .WithPersistence(ef => ef.AddDbContext( "Ordering", o => o.UseSqlServer(orderingConnectionString))); } } public sealed class InventoryModule : IServiceModule { public void Configure(IServiceCollection services) { services.AddRCommon() .WithSimpleGuidGenerator() // Same impl as Ordering — idempotent no-op. .WithPersistence(ef => ef.AddDbContext( "Inventory", o => o.UseNpgsql(inventoryConnectionString))); } } ``` -------------------------------- ### Create Documentation Directories Source: https://github.com/rcommon-team/rcommon/blob/main/docs/superpowers/plans/2026-03-23-rcommon-website.md Use this bash command to create all necessary directories for the website documentation within the 'website/docs/' path. This ensures a structured organization for future content. ```bash cd website && mkdir -p docs/getting-started docs/core-concepts docs/domain-driven-design docs/persistence docs/cqrs-mediator docs/event-handling docs/messaging docs/state-machines docs/caching docs/blob-storage docs/serialization docs/validation docs/email docs/multi-tenancy docs/security-web docs/architecture-guides docs/examples-recipes docs/testing docs/api-reference ``` -------------------------------- ### Configure RCommon Services for Leave Management Source: https://github.com/rcommon-team/rcommon/blob/main/website/build/docs/examples-recipes/hr-leave-management.html Configures various RCommon services including email, date/time, GUID generation, mediator, persistence, unit of work, and validation. This setup is typically done in the application's composition root. ```csharp builder.Services.AddRCommon() .WithClaimsAndPrincipalAccessor() .WithSendGridEmailServices(x => { var settings = builder.Configuration.Get(); x.SendGridApiKey = settings.SendGridApiKey; x.FromNameDefault = settings.FromNameDefault; x.FromEmailDefault = settings.FromEmailDefault; }) .WithDateTimeSystem(dateTime => dateTime.Kind = DateTimeKind.Utc) .WithSequentialGuidGenerator(guid => guid.DefaultSequentialGuidType = SequentialGuidType.SequentialAsString) .WithMediator(mediator => { mediator.AddRequest(); mediator.AddRequest, GetLeaveTypeListRequestHandler>(); // ... all other request/handler pairs mediator.Configure(config => { config.RegisterServicesFromAssemblies( typeof(ApplicationServicesRegistration).GetTypeInfo().Assembly); }); mediator.AddLoggingToRequestPipeline(); mediator.AddUnitOfWorkToRequestPipeline(); }) .WithPersistence(ef => { ef.AddDbContext( DataStoreNamesConst.LeaveManagement, options => options.UseSqlServer( builder.Configuration.GetConnectionString( DataStoreNamesConst.LeaveManagement))); ef.SetDefaultDataStore(dataStore => dataStore.DefaultDataStoreName = DataStoreNamesConst.LeaveManagement); }) .WithUnitOfWork(unitOfWork => { unitOfWork.SetOptions(options => { options.AutoCompleteScope = true; options.DefaultIsolation = IsolationLevel.ReadCommitted; }); }) .WithValidation(validation => { validation.AddValidatorsFromAssemblyContaining( typeof(ApplicationServicesRegistration)); }); ``` -------------------------------- ### Build and Test Full Solution Source: https://github.com/rcommon-team/rcommon/blob/main/docs/plans/bootstrapping/2026-05-15-bootstrapping.md After each provider migration commit, build the entire solution and run package-specific tests to ensure no regressions were introduced. ```bash dotnet build Src/RCommon.sln dotnet test Tests/.Tests/.Tests.csproj ``` -------------------------------- ### Check if GUID is Not Empty Source: https://github.com/rcommon-team/rcommon/blob/main/website/build/docs/core-concepts/guards.html Use IsNotEmpty to ensure a GUID value is not Guid.Empty. Throws ArgumentException if the GUID is empty. ```csharp IsNotEmpty(Guid, string) ``` -------------------------------- ### Finbuckle Tenant Stores Source: https://github.com/rcommon-team/rcommon/blob/main/website/build/llms-full.txt Demonstrates configuring different Finbuckle tenant stores: ConfigurationStore (appsettings.json), EFCoreStore (database), and InMemoryStore (testing). ```csharp // Store tenant definitions in appsettings.json under "Finbuckle:MultiTenant:Stores:ConfigurationStore". builder.Services.AddMultiTenant() .WithHeaderStrategy("X-Tenant-Id") .WithConfigurationStore(); ``` ```csharp // Store tenants in an EF Core database table. builder.Services.AddMultiTenant() .WithHeaderStrategy("X-Tenant-Id") .WithEFCoreStore(); ``` ```csharp // In-memory store — useful for testing. builder.Services.AddMultiTenant() .WithHeaderStrategy("X-Tenant-Id") .WithInMemoryStore(options => { options.Tenants.Add(new TenantInfo { Id = "tenant-1", Identifier = "acme", Name = "Acme Corp" }); }); ``` -------------------------------- ### DomainEntity GUID Key Test Source: https://github.com/rcommon-team/rcommon/blob/main/docs/superpowers/plans/2026-03-16-ddd-entity-abstractions.md Confirms that DomainEntity with a GUID key correctly sets the Id property when initialized with a GUID. ```csharp [Fact] public void DomainEntity_GuidKey_SetsId() { // Arrange var id = Guid.NewGuid(); // Act var entity = new TestDomainEntityGuid(id); // Assert entity.Id.Should().Be(id); } ``` -------------------------------- ### Configure Simple GUID Generator Source: https://github.com/rcommon-team/rcommon/blob/main/website/build/docs/core-concepts/guid-generation.html Register the simple GUID generator service. This is suitable for non-database use cases or when the database handles GUID ordering. ```csharp builder.Services.AddRCommon() .WithSimpleGuidGenerator(); ``` -------------------------------- ### Verify pnpm installation Source: https://github.com/rcommon-team/rcommon/blob/main/docs/superpowers/plans/2026-03-23-rcommon-website.md Checks if the @docusaurus/core package exists in the website's node_modules directory after installation with pnpm. This confirms successful dependency installation. ```bash ls website/node_modules/@docusaurus/core ``` -------------------------------- ### Host Configuration and Cache Usage Example Source: https://github.com/rcommon-team/rcommon/blob/main/website/build/docs/examples-recipes/caching.html Sets up the host with RCommon caching services and demonstrates storing and retrieving data from both IMemoryCache and IDistributedCache. Ensure TestDto and its properties are correctly defined for serialization. ```csharp var host = Host.CreateDefaultBuilder(args) .ConfigureServices(services => { services.AddRCommon() .WithJsonSerialization() .WithMemoryCaching(cache => { cache.Configure(x => { x.ExpirationScanFrequency = TimeSpan.FromMinutes(1); }); }) .WithDistributedCaching(cache => { cache.Configure(x => { x.ExpirationScanFrequency = TimeSpan.FromMinutes(1); }); }); services.AddTransient(); }).Build(); var appService = host.Services.GetRequiredService(); // Store and retrieve from IMemoryCache appService.SetMemoryCache("test-key", new TestDto("test data 1")); var testData1 = appService.GetMemoryCache("test-key");// Store and retrieve from IDistributedCache appService.SetDistributedMemoryCache("test-key", typeof(TestDto), new TestDto("test data 2")); var testData2 = appService.GetDistributedMemoryCache("test-key"); Console.WriteLine(testData1.Message); // test data 1 Console.WriteLine(testData2.Message); // test data 2 ``` -------------------------------- ### Check if GUID is Not Empty (with boolean return) Source: https://github.com/rcommon-team/rcommon/blob/main/website/build/docs/core-concepts/guards.html Use the boolean-returning overload of IsNotEmpty to check if a GUID is not Guid.Empty. Throws ArgumentException or returns false if the GUID is empty. ```csharp IsNotEmpty(Guid, string, bool) ``` -------------------------------- ### Build Solution Source: https://github.com/rcommon-team/rcommon/blob/main/docs/superpowers/plans/2026-04-05-security-abstractions-string-id.md Perform a full build of the solution to confirm that all projects compile successfully without errors. ```bash dotnet build RCommon.sln -v quiet ``` -------------------------------- ### Registering Simple GUID Generator Source: https://github.com/rcommon-team/rcommon/blob/main/website/build/docs/next/core-concepts/guid-generation.html Configures the application to use a simple GUID generator, which internally uses Guid.NewGuid(). Suitable for non-database use cases or when the database handles GUID ordering. ```APIDOC ## Registering Simple GUID Generator ### Description Configures the application to use a simple GUID generator, which internally uses `Guid.NewGuid()`. This is suitable for non-database use cases or when the underlying database handles GUID ordering itself (e.g., `NEWSEQUENTIALID()` in SQL Server). ### Method Signature ```csharp builder.Services.AddRCommon().WithSimpleGuidGenerator(); ``` ``` -------------------------------- ### Configure Sequential GUID Generator Source: https://github.com/rcommon-team/rcommon/blob/main/website/build/docs/core-concepts/guid-generation.html Register the sequential GUID generator service with options to specify the GUID byte layout for different database platforms. Defaults to SequentialAtEnd for SQL Server. ```csharp builder.Services.AddRCommon() .WithSequentialGuidGenerator(options => { options.DefaultSequentialGuidType = SequentialGuidType.SequentialAtEnd; }); ``` -------------------------------- ### Multi-Tenancy Setup with Finbuckle Source: https://github.com/rcommon-team/rcommon/blob/main/website/docs/api-reference/migration-guide.mdx Integrate multi-tenancy using Finbuckle, configuring tenant resolution strategies and registering RCommon with the multi-tenancy and persistence builders. ```csharp // 1. Set up Finbuckle tenant resolution builder.Services.AddMultiTenant() .WithHeaderStrategy("X-Tenant") .WithConfigurationStore(); // 2. Register RCommon with Finbuckle builder.Services.AddRCommon(config => { config .WithClaimsAndPrincipalAccessorForWeb() .WithPersistence(ef => { ef.AddDbContext("AppDb", options => options.UseSqlServer(connectionString)); ef.SetDefaultDataStore(o => o.DefaultDataStoreName = "AppDb"); }) .WithMultiTenancy>(mt => { }); }); ``` -------------------------------- ### OrderPlacedHandler Subscriber Example Source: https://github.com/rcommon-team/rcommon/blob/main/website/build/llms-full.txt Example of implementing an ISubscriber to handle the OrderPlaced event. ```APIDOC ## OrderPlacedHandler Subscriber ### Description An example handler for the `OrderPlaced` event, logging details about the order. ### Class Definition ```csharp public class OrderPlacedHandler : ISubscriber { private readonly ILogger _logger; public OrderPlacedHandler(ILogger logger) { _logger = logger; } public async Task HandleAsync(OrderPlaced @event, CancellationToken cancellationToken = default) { _logger.LogInformation("Order {OrderId} placed at {PlacedAt}", @event.OrderId, @event.PlacedAt); await Task.CompletedTask; } } ``` ```