Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
60ffad2ea9 | ||
|
|
14fe8f2897 |
9
.cursor/maksit-skills.json
Normal file
9
.cursor/maksit-skills.json
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"$schema": "homelab-maksit-skills-manifest-v1",
|
||||
"skillsRoot": "E:\\Users\\maksym\\source\\repos\\private\\homelab\\ai\\skills",
|
||||
"skills": [
|
||||
"common/csharp",
|
||||
"common/maksit-repo-maintenance",
|
||||
"local-ollama"
|
||||
]
|
||||
}
|
||||
15
.cursor/rules/maksit-skills.mdc
Normal file
15
.cursor/rules/maksit-skills.mdc
Normal file
@ -0,0 +1,15 @@
|
||||
---
|
||||
description: Load MaksIT agent skills from homelab (deterministic)
|
||||
globs: "**/*.{cs,csproj,slnx,md}"
|
||||
alwaysApply: true
|
||||
---
|
||||
|
||||
# MaksIT skills (maksit-results)
|
||||
|
||||
Complementary skills (no precedence). Read each `SKILL.md` when relevant:
|
||||
|
||||
1. `E:\Users\maksym\source\repos\private\homelab\ai\skills\common\csharp\SKILL.md`
|
||||
2. `E:\Users\maksym\source\repos\private\homelab\ai\skills\common\maksit-repo-maintenance\SKILL.md`
|
||||
3. `E:\Users\maksym\source\repos\private\homelab\ai\skills\local-ollama\SKILL.md` — local Ollama offload (`@local-ollama`)
|
||||
|
||||
Manifest: `.cursor/maksit-skills.json`.
|
||||
11
AGENTS.md
Normal file
11
AGENTS.md
Normal file
@ -0,0 +1,11 @@
|
||||
# Agent instructions (maksit-results)
|
||||
|
||||
Complementary skills (no precedence):
|
||||
|
||||
| Skill | Path |
|
||||
|-------|------|
|
||||
| csharp | [SKILL.md](E:\Users\maksym\source\repos\private\homelab\ai\skills\common\csharp\SKILL.md) |
|
||||
| maksit-repo-maintenance | [SKILL.md](E:\Users\maksym\source\repos\private\homelab\ai\skills\common\maksit-repo-maintenance\SKILL.md) |
|
||||
| local-ollama | [SKILL.md](E:\Users\maksym\source\repos\private\homelab\ai\skills\local-ollama\SKILL.md) |
|
||||
|
||||
Manifest: `.cursor/maksit-skills.json`.
|
||||
@ -5,6 +5,15 @@ All notable changes to this project will be documented in this file.
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [2.0.3] - 2026-06-28
|
||||
|
||||
### Added
|
||||
- `Result<T>.ToActionResult()` now returns `RedirectResult` when the status code is a redirection (300–303, 307–308) and `Value` is a non-empty URL string.
|
||||
- Added `MaksIT.Results.Mvc.RedirectResult` for HTTP redirect responses.
|
||||
|
||||
### Changed
|
||||
- Updated ASP.NET Core and Microsoft.Extensions package references.
|
||||
|
||||
## [2.0.2] - 2026-06-02
|
||||
|
||||
### Changed
|
||||
|
||||
@ -82,6 +82,7 @@ public sealed record UserDto(Guid Id, string Name);
|
||||
|
||||
- `Result` success: returns status-code-only response.
|
||||
- `Result<T>` success with non-null `Value`: returns JSON body + status code.
|
||||
- `Result<T>` success with a redirection status code (300–303, 307–308) and a non-empty string `Value`: returns an HTTP redirect to that URL.
|
||||
- Any failure: returns RFC 7807-style `ProblemDetails` JSON with:
|
||||
- `status` = result status code
|
||||
- `title` = `"An error occurred"`
|
||||
|
||||
@ -1,21 +1,21 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="150" height="20" role="img" aria-label="Branch Coverage: 65.4%">
|
||||
<title>Branch Coverage: 65.4%</title>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="147.5" height="20" role="img" aria-label="Branch Coverage: 75%">
|
||||
<title>Branch Coverage: 75%</title>
|
||||
<linearGradient id="s" x2="0" y2="100%">
|
||||
<stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
|
||||
<stop offset="1" stop-opacity=".1"/>
|
||||
</linearGradient>
|
||||
<clipPath id="r">
|
||||
<rect width="150" height="20" rx="3" fill="#fff"/>
|
||||
<rect width="147.5" height="20" rx="3" fill="#fff"/>
|
||||
</clipPath>
|
||||
<g clip-path="url(#r)">
|
||||
<rect width="107.5" height="20" fill="#555"/>
|
||||
<rect x="107.5" width="42.5" height="20" fill="#97ca00"/>
|
||||
<rect width="150" height="20" fill="url(#s)"/>
|
||||
<rect x="107.5" width="40" height="20" fill="#97ca00"/>
|
||||
<rect width="147.5" height="20" fill="url(#s)"/>
|
||||
</g>
|
||||
<g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="11">
|
||||
<text aria-hidden="true" x="53.75" y="15" fill="#010101" fill-opacity=".3">Branch Coverage</text>
|
||||
<text x="53.75" y="14" fill="#fff">Branch Coverage</text>
|
||||
<text aria-hidden="true" x="128.75" y="15" fill="#010101" fill-opacity=".3">65.4%</text>
|
||||
<text x="128.75" y="14" fill="#fff">65.4%</text>
|
||||
<text aria-hidden="true" x="127.5" y="15" fill="#010101" fill-opacity=".3">75%</text>
|
||||
<text x="127.5" y="14" fill="#fff">75%</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
@ -1,5 +1,5 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="137" height="20" role="img" aria-label="Line Coverage: 17.6%">
|
||||
<title>Line Coverage: 17.6%</title>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="137" height="20" role="img" aria-label="Line Coverage: 19.8%">
|
||||
<title>Line Coverage: 19.8%</title>
|
||||
<linearGradient id="s" x2="0" y2="100%">
|
||||
<stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
|
||||
<stop offset="1" stop-opacity=".1"/>
|
||||
@ -15,7 +15,7 @@
|
||||
<g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="11">
|
||||
<text aria-hidden="true" x="47.25" y="15" fill="#010101" fill-opacity=".3">Line Coverage</text>
|
||||
<text x="47.25" y="14" fill="#fff">Line Coverage</text>
|
||||
<text aria-hidden="true" x="115.75" y="15" fill="#010101" fill-opacity=".3">17.6%</text>
|
||||
<text x="115.75" y="14" fill="#fff">17.6%</text>
|
||||
<text aria-hidden="true" x="115.75" y="15" fill="#010101" fill-opacity=".3">19.8%</text>
|
||||
<text x="115.75" y="14" fill="#fff">19.8%</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
@ -1,5 +1,5 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="150" height="20" role="img" aria-label="Method Coverage: 17.8%">
|
||||
<title>Method Coverage: 17.8%</title>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="150" height="20" role="img" aria-label="Method Coverage: 19.9%">
|
||||
<title>Method Coverage: 19.9%</title>
|
||||
<linearGradient id="s" x2="0" y2="100%">
|
||||
<stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
|
||||
<stop offset="1" stop-opacity=".1"/>
|
||||
@ -15,7 +15,7 @@
|
||||
<g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="11">
|
||||
<text aria-hidden="true" x="53.75" y="15" fill="#010101" fill-opacity=".3">Method Coverage</text>
|
||||
<text x="53.75" y="14" fill="#fff">Method Coverage</text>
|
||||
<text aria-hidden="true" x="128.75" y="15" fill="#010101" fill-opacity=".3">17.8%</text>
|
||||
<text x="128.75" y="14" fill="#fff">17.8%</text>
|
||||
<text aria-hidden="true" x="128.75" y="15" fill="#010101" fill-opacity=".3">19.9%</text>
|
||||
<text x="128.75" y="14" fill="#fff">19.9%</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
@ -14,10 +14,10 @@
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Http" Version="2.3.10" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="10.0.8" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options" Version="10.0.8" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.6.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Http" Version="2.3.11" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="10.0.9" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options" Version="10.0.9" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.7.0" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.5">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
|
||||
@ -45,4 +45,15 @@ public class ResultToActionResultTests {
|
||||
Assert.Equal((int)HttpStatusCode.OK, objectResult.StatusCode);
|
||||
Assert.Equal(value, objectResult.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ToActionResult_WhenGenericSuccessWithRedirect_ReturnsRedirectResult() {
|
||||
var result = Result<string>.Found("https://example.com/continue");
|
||||
|
||||
var actionResult = result.ToActionResult();
|
||||
|
||||
Assert.IsType<RedirectResult>(actionResult);
|
||||
var redirectResult = (RedirectResult)actionResult;
|
||||
Assert.Equal("https://example.com/continue", redirectResult.Location);
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
<!-- NuGet package metadata -->
|
||||
<PackageId>MaksIT.Results</PackageId>
|
||||
<Version>2.0.2</Version>
|
||||
<Version>2.0.3</Version>
|
||||
<Authors>Maksym Sadovnychyy</Authors>
|
||||
<Company>MAKS-IT</Company>
|
||||
<Product>MaksIT.Results</Product>
|
||||
@ -22,9 +22,9 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Abstractions" Version="2.3.10" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="10.0.8" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options" Version="10.0.8" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Abstractions" Version="2.3.11" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="10.0.9" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options" Version="10.0.9" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
12
src/MaksIT.Results/Mvc/RedirectResult.cs
Normal file
12
src/MaksIT.Results/Mvc/RedirectResult.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace MaksIT.Results.Mvc;
|
||||
|
||||
public class RedirectResult(string location) : IActionResult {
|
||||
public string Location { get; } = location;
|
||||
|
||||
public Task ExecuteResultAsync(ActionContext context) {
|
||||
context.HttpContext.Response.Redirect(Location);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
@ -78,13 +78,24 @@ public partial class Result<T> : Result {
|
||||
/// <returns>IActionResult that represents the HTTP response.</returns>
|
||||
public override IActionResult ToActionResult() {
|
||||
if (IsSuccess) {
|
||||
if (Value is not null) {
|
||||
if (IsRedirectionStatusCode(StatusCode) && Value is string location && !string.IsNullOrWhiteSpace(location))
|
||||
return new RedirectResult(location);
|
||||
|
||||
if (Value is not null)
|
||||
return new ObjectResult(Value) { StatusCode = (int)StatusCode };
|
||||
}
|
||||
|
||||
return base.ToActionResult();
|
||||
}
|
||||
else {
|
||||
return base.ToActionResult();
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsRedirectionStatusCode(HttpStatusCode statusCode) =>
|
||||
statusCode is HttpStatusCode.MultipleChoices
|
||||
or HttpStatusCode.MovedPermanently
|
||||
or HttpStatusCode.Found
|
||||
or HttpStatusCode.SeeOther
|
||||
or HttpStatusCode.TemporaryRedirect
|
||||
or HttpStatusCode.PermanentRedirect;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user