diff --git a/wolverine/getting-started/AssignIssue.cs b/wolverine/getting-started/AssignIssue.cs new file mode 100644 index 0000000..533d344 --- /dev/null +++ b/wolverine/getting-started/AssignIssue.cs @@ -0,0 +1,3 @@ +namespace WolverineTutorial; + +public record AssignIssue(Guid IssueId, Guid AssigneeId); \ No newline at end of file diff --git a/wolverine/getting-started/CreateIssue.cs b/wolverine/getting-started/CreateIssue.cs new file mode 100644 index 0000000..b027eec --- /dev/null +++ b/wolverine/getting-started/CreateIssue.cs @@ -0,0 +1,3 @@ +namespace WolverineTutorial; + +public record CreateIssue(Guid OriginatorId, string Title, string Description); \ No newline at end of file diff --git a/wolverine/getting-started/CreateIssueHandler.cs b/wolverine/getting-started/CreateIssueHandler.cs new file mode 100644 index 0000000..414b262 --- /dev/null +++ b/wolverine/getting-started/CreateIssueHandler.cs @@ -0,0 +1,23 @@ +namespace WolverineTutorial; + +public class CreateIssueHandler(IssueRepository repository) +{ + // The IssueCreated event message being returned will be + // published as a new "cascaded" message by Wolverine after + // the original message and any related middleware has + // succeeded + public IssueCreated Handle(CreateIssue command) + { + var issue = new Issue(Guid.NewGuid(), command.Title, command.Description, true, DateTimeOffset.Now, + command.OriginatorId + ); + + repository.Store(issue); + + return new IssueCreated(issue.Id); + } +} + +public record Issue(Guid Id, string Title, string Description, bool IsOpen, DateTimeOffset Opened, Guid OriginatorId); + +public record IssueCreated(Guid Id); \ No newline at end of file diff --git a/wolverine/getting-started/IssueCretaedHandler.cs b/wolverine/getting-started/IssueCretaedHandler.cs new file mode 100644 index 0000000..3775cfc --- /dev/null +++ b/wolverine/getting-started/IssueCretaedHandler.cs @@ -0,0 +1,25 @@ +using System.Net.Mail; + +namespace WolverineTutorial; + +public static class IssueCreatedHandler +{ + public static async Task Handle(IssueCreated created, IssueRepository repository) + { + var issue = repository.Get(created.Id); + var message = await BuildEmailMessage(issue); + using var client = new SmtpClient(); + client.Send(message); + } + + // This is a little helper method I made public + // Wolverine will not expose this as a message handler + private static Task BuildEmailMessage(Issue issue) + { + // Build up a templated email message, with + // some sort of async method to look up additional + // data just so we can show off an async + // Wolverine Handler + return Task.FromResult(new MailMessage()); + } +} \ No newline at end of file diff --git a/wolverine/getting-started/IssueRepository.cs b/wolverine/getting-started/IssueRepository.cs new file mode 100644 index 0000000..630e211 --- /dev/null +++ b/wolverine/getting-started/IssueRepository.cs @@ -0,0 +1,14 @@ +namespace WolverineTutorial; + +public class IssueRepository +{ + public void Store(Issue issue) + { + throw new NotImplementedException(); + } + + public Issue Get(Guid createdId) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/wolverine/getting-started/Program.cs b/wolverine/getting-started/Program.cs new file mode 100644 index 0000000..8174e35 --- /dev/null +++ b/wolverine/getting-started/Program.cs @@ -0,0 +1,29 @@ +using JasperFx; +using Microsoft.AspNetCore.Http.HttpResults; +using Microsoft.AspNetCore.Mvc; +using Scalar.AspNetCore; +using Wolverine; +using WolverineTutorial; + +var builder = WebApplication.CreateBuilder(args); + +builder.Services.AddOpenApi(); + +builder.Host.UseWolverine(options => { options.UseRuntimeCompilation(); }); + +builder.Services.AddSingleton(); +builder.Services.AddSingleton(); + +var app = builder.Build(); + +app.MapPost("/issues/create", (CreateIssue body, IMessageBus bus) => bus.InvokeAsync(body)); +//app.MapPost("/issues/assign", (AssignIssue body, IMessageBus bus) => bus.InvokeAsync(body)); + +app.MapOpenApi(); + +app.MapScalarApiReference(); + +app.MapGet("/", () => Results.Redirect("/scalar")); + +app.UseHttpsRedirection(); +return await app.RunJasperFxCommands(args); \ No newline at end of file diff --git a/wolverine/getting-started/Properties/launchSettings.json b/wolverine/getting-started/Properties/launchSettings.json new file mode 100644 index 0000000..3025f39 --- /dev/null +++ b/wolverine/getting-started/Properties/launchSettings.json @@ -0,0 +1,23 @@ +{ + "$schema": "https://json.schemastore.org/launchsettings.json", + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": false, + "applicationUrl": "http://localhost:5043", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": false, + "applicationUrl": "https://localhost:7161;http://localhost:5043", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/wolverine/getting-started/UserRepository.cs b/wolverine/getting-started/UserRepository.cs new file mode 100644 index 0000000..ada74bc --- /dev/null +++ b/wolverine/getting-started/UserRepository.cs @@ -0,0 +1,5 @@ +namespace WolverineTutorial; + +public class UserRepository +{ +} \ No newline at end of file diff --git a/wolverine/getting-started/appsettings.Development.json b/wolverine/getting-started/appsettings.Development.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/wolverine/getting-started/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/wolverine/getting-started/appsettings.json b/wolverine/getting-started/appsettings.json new file mode 100644 index 0000000..10f68b8 --- /dev/null +++ b/wolverine/getting-started/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} diff --git a/wolverine/getting-started/getting-started.csproj b/wolverine/getting-started/getting-started.csproj new file mode 100644 index 0000000..c6ea9c9 --- /dev/null +++ b/wolverine/getting-started/getting-started.csproj @@ -0,0 +1,17 @@ + + + + net10.0 + enable + enable + WolverineTutorial + + + + + + + + + + diff --git a/wolverine/getting-started/getting-started.http b/wolverine/getting-started/getting-started.http new file mode 100644 index 0000000..2c29e7d --- /dev/null +++ b/wolverine/getting-started/getting-started.http @@ -0,0 +1,12 @@ +@getting_started_HostAddress = https://localhost:7161 + +POST {{getting_started_HostAddress}}/issues/create +Content-Type: application/json + +{ + "originatorId": "e731cf74-0e57-4c91-8fda-6ae5214a9fa4", + "title": "Test Title", + "description": "Test Description" +} + +###