This commit is contained in:
john 2025-05-03 15:38:57 +02:00
commit ab2e20f7e1
72 changed files with 2000 additions and 0 deletions

View file

@ -0,0 +1,28 @@
using Femto.Api.Controllers.Authors.Dto;
using Femto.Modules.Blog.Domain.Posts.Commands.GetAuthorPosts;
using MediatR;
using Microsoft.AspNetCore.Mvc;
namespace Femto.Api.Controllers.Authors;
[ApiController]
[Route("authors")]
public class AuthorsController(IMediator mediator) : ControllerBase
{
[HttpGet("{authorId}/posts")]
public async Task<ActionResult<GetAuthorPostsResponse>> GetAuthorPosts(
Guid authorId,
[FromQuery] GetAuthorPostsSearchParams searchParams,
CancellationToken cancellationToken
)
{
var posts = await mediator.Send(
new GetAuthorPostsQuery(authorId, searchParams.Cursor, searchParams.Count),
cancellationToken
);
return new GetAuthorPostsResponse(
posts.Select(p => new AuthorPostDto(p.PostId, p.Text, p.Media.Select(m => m.Url)))
);
}
}

View file

@ -0,0 +1,9 @@
using JetBrains.Annotations;
namespace Femto.Api.Controllers.Authors.Dto;
[PublicAPI]
public record GetAuthorPostsResponse(IEnumerable<AuthorPostDto> Posts);
[PublicAPI]
public record AuthorPostDto(Guid PostId, string Content, IEnumerable<Uri> Media);

View file

@ -0,0 +1,3 @@
namespace Femto.Api.Controllers.Authors;
public record GetAuthorPostsSearchParams(Guid? Cursor, int? Count);

View file

@ -0,0 +1,3 @@
namespace Femto.Api.Controllers.Posts.Dto;
public record CreatePostRequest(Guid AuthorId, string Content, IEnumerable<Uri> Media);

View file

@ -0,0 +1,3 @@
namespace Femto.Api.Controllers.Posts.Dto;
public record CreatePostResponse(Guid PostId);

View file

@ -0,0 +1,6 @@
namespace Femto.Api.Controllers.Posts.Dto;
public record GetPostResponse
{
}

View file

@ -0,0 +1,25 @@
using Femto.Api.Controllers.Posts.Dto;
using Femto.Modules.Blog.Domain.Posts.Commands.CreatePost;
using MediatR;
using Microsoft.AspNetCore.Mvc;
namespace Femto.Api.Controllers.Posts;
[ApiController]
[Route("posts")]
public class PostsController(IMediator mediator) : ControllerBase
{
[HttpPost]
public async Task<ActionResult<CreatePostResponse>> Post(
[FromBody] CreatePostRequest req,
CancellationToken cancellationToken
)
{
var guid = await mediator.Send(
new CreatePostCommand(req.AuthorId, req.Content, req.Media),
cancellationToken
);
return new CreatePostResponse(guid);
}
}

View file

@ -0,0 +1,28 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
<LangVersion>13</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="MediatR" Version="12.5.0" />
<PackageReference Include="Microsoft.AspNetCore" Version="2.3.0" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.3"/>
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.4" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Femto.Modules.Blog\Femto.Modules.Blog.csproj" />
</ItemGroup>
<ItemGroup>
<Reference Include="Microsoft.Data.SqlClient">
<HintPath>..\..\..\..\.nuget\packages\microsoft.data.sqlclient\6.0.1\ref\net9.0\Microsoft.Data.SqlClient.dll</HintPath>
</Reference>
</ItemGroup>
</Project>

39
Femto.Api/Program.cs Normal file
View file

@ -0,0 +1,39 @@
using System.Text.Json;
using System.Text.Json.Serialization;
using Femto.Modules.Blog;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddOpenApi();
var databaseConnectionString = builder.Configuration.GetConnectionString("Database");
if (databaseConnectionString is null)
throw new Exception("no database connection string found");
builder.Services.UseBlogModule(databaseConnectionString);
builder.Services.AddControllers();
builder
.Services.AddControllers()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.PropertyNameCaseInsensitive = true;
options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
options.JsonSerializerOptions.DictionaryKeyPolicy = JsonNamingPolicy.CamelCase;
options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
options.JsonSerializerOptions.NumberHandling = JsonNumberHandling.AllowReadingFromString;
});
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.MapOpenApi();
}
app.MapControllers();
app.UseHttpsRedirection();
app.Run();

View file

@ -0,0 +1,23 @@
{
"$schema": "https://json.schemastore.org/launchsettings.json",
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": false,
"applicationUrl": "http://localhost:5181",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": false,
"applicationUrl": "https://localhost:7269;http://localhost:5181",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

View file

@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}