Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
version: 2
updates:
- package-ecosystem: nuget
directory: /src
schedule:
interval: weekly
groups:
nuget-dependencies:
patterns:
- "*"

- package-ecosystem: github-actions
directory: /
schedule:
interval: weekly
16 changes: 13 additions & 3 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ jobs:
- name: Set up .NET
uses: actions/setup-dotnet@v5
with:
dotnet-version: 10.0.x
dotnet-version: |
8.0.x
10.0.x

- name: Restore dependencies
run: dotnet restore src/core.slnx
Expand All @@ -49,15 +51,23 @@ jobs:
--configuration Release
--no-build
--output artifacts
-p:PackageVersion=1.0.0-ci.${{ github.run_number }}
-p:Version=2.0.0-ci.${{ github.run_number }}

- name: Pack ASP.NET Core integration
run: >-
dotnet pack src/Core.AspNetCore/Core.AspNetCore.csproj
--configuration Release
--no-build
--output artifacts
-p:Version=2.0.0-ci.${{ github.run_number }}

- name: Pack DB
run: >-
dotnet pack src/DB/DB.csproj
--configuration Release
--no-build
--output artifacts
-p:PackageVersion=1.0.0-ci.${{ github.run_number }}
-p:Version=2.0.0-ci.${{ github.run_number }}

- name: Upload packages
uses: actions/upload-artifact@v7
Expand Down
26 changes: 22 additions & 4 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ env:

jobs:
publish:
name: Publish Core and DB
name: Publish KitchenPC packages
runs-on: ubuntu-latest
environment: nuget

Expand All @@ -37,7 +37,9 @@ jobs:
- name: Set up .NET
uses: actions/setup-dotnet@v5
with:
dotnet-version: 10.0.x
dotnet-version: |
8.0.x
10.0.x

- name: Restore dependencies
run: dotnet restore src/core.slnx
Expand All @@ -58,15 +60,23 @@ jobs:
--configuration Release
--no-build
--output artifacts
-p:PackageVersion=${{ steps.version.outputs.value }}
-p:Version=${{ steps.version.outputs.value }}

- name: Pack DB
run: >-
dotnet pack src/DB/DB.csproj
--configuration Release
--no-build
--output artifacts
-p:PackageVersion=${{ steps.version.outputs.value }}
-p:Version=${{ steps.version.outputs.value }}

- name: Pack ASP.NET Core integration
run: >-
dotnet pack src/Core.AspNetCore/Core.AspNetCore.csproj
--configuration Release
--no-build
--output artifacts
-p:Version=${{ steps.version.outputs.value }}

- name: Upload release packages
uses: actions/upload-artifact@v7
Expand Down Expand Up @@ -96,3 +106,11 @@ jobs:
--api-key ${{ steps.nuget-login.outputs.NUGET_API_KEY }}
--source https://api.nuget.org/v3/index.json
--skip-duplicate

- name: Publish ASP.NET Core integration to NuGet
run: >-
dotnet nuget push
artifacts/KitchenPC.Core.AspNetCore.${{ steps.version.outputs.value }}.nupkg
--api-key ${{ steps.nuget-login.outputs.NUGET_API_KEY }}
--source https://api.nuget.org/v3/index.json
--skip-duplicate
7 changes: 7 additions & 0 deletions Directory.Build.props
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<Project>
<PropertyGroup>
<NuGetAudit>true</NuGetAudit>
<NuGetAuditMode>all</NuGetAuditMode>
<WarningsAsErrors>$(WarningsAsErrors);NU1901;NU1902;NU1903;NU1904</WarningsAsErrors>
</PropertyGroup>
</Project>
25 changes: 20 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,28 @@ Example applications and a small static data snapshot are available in the
Building and Testing
====

Install the .NET 10 SDK, then restore, build, and test from the repository root:
Install the .NET 8 and .NET 10 SDKs, then restore, build, and test from the repository root:

```bash
dotnet restore src/core.slnx
dotnet build src/core.slnx --configuration Release --no-restore
dotnet test src/UnitTests/UnitTests.csproj --configuration Release --no-build --no-restore
```

The build includes `KitchenPC.Core`, `KitchenPC.DB`, and the unit tests.
The build includes `KitchenPC.Core`, `KitchenPC.DB`, `KitchenPC.Core.AspNetCore`, and the unit tests.

`KitchenPC.Core` contains the engine and static context. Add `KitchenPC.DB` when using PostgreSQL,
and add `KitchenPC.Core.AspNetCore` only when registering a context with ASP.NET Core dependency
injection. Applications can connect KitchenPC to standard Microsoft logging through either context
builder:

```csharp
var context = DBContext.Configure
.Logging(loggerFactory)
.Adapter(/* database adapter configuration */)
.Identity(() => AuthIdentity.Anonymous)
.Create();
```

Database Schema Naming
====
Expand Down Expand Up @@ -80,11 +93,13 @@ sample-data startup and memory measurements.
Packages and Releases
====

Every push and pull request builds and tests the solution, then creates matching prerelease packages for CI validation. Version tags publish `KitchenPC.Core` and `KitchenPC.DB` to NuGet with the same version. For example:
Every push and pull request builds and tests the solution, then creates matching prerelease packages
for CI validation. Version tags publish `KitchenPC.Core`, `KitchenPC.DB`, and
`KitchenPC.Core.AspNetCore` to NuGet with the same version. For example:

```bash
git tag -a v1.0.0 -m "KitchenPC 1.0.0"
git push origin v1.0.0
git tag -a v2.0.0 -m "KitchenPC 2.0.0"
git push origin v2.0.0
```

NuGet package versions are immutable. Always increment the version for a subsequent release.
32 changes: 32 additions & 0 deletions src/Core.AspNetCore/Core.AspNetCore.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net8.0;net10.0</TargetFrameworks>
<AssemblyName>KitchenPC.Core.AspNetCore</AssemblyName>
<RootNamespace>KitchenPC.Core</RootNamespace>
<Description>ASP.NET Core integration for the KitchenPC recipe engine</Description>
<Authors>Mike Christensen</Authors>
<Company>KitchenPC</Company>
<PackageId>KitchenPC.Core.AspNetCore</PackageId>
<Version>2.0.0</Version>
<PackageProjectUrl>https://github.com/KitchenPC/core</PackageProjectUrl>
<RepositoryUrl>https://github.com/KitchenPC/core.git</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageReadmeFile>README.md</PackageReadmeFile>
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
<PackageTags>recipes;aspnetcore;dependency-injection</PackageTags>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<NoWarn>$(NoWarn);1591</NoWarn>
</PropertyGroup>

<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
<ProjectReference Include="..\Core\Core.csproj" />
<None Include="..\..\LICENSE" Pack="true" PackagePath="/" />
<None Include="..\..\README.md" Pack="true" PackagePath="/" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Security.Claims;
using KitchenPC.Core.Context;
using Microsoft.AspNetCore.Http;
Expand All @@ -8,33 +8,31 @@ namespace KitchenPC.Core.Middleware;

public static class KPCMiddleware
{
/// <summary>
/// Adds KitchenPC OWIN Middleware components into Service Collection
/// </summary>
/// <param name="services"></param>
/// <param name="configuration"></param>
/// <summary>Adds a configured KitchenPC context to an ASP.NET Core service collection.</summary>
public static void AddKPCContext<T>(
this IServiceCollection services,
IConfiguration<T> configuration
)
where T : class, IKPCContext
{
ArgumentNullException.ThrowIfNull(services);
ArgumentNullException.ThrowIfNull(configuration);

var kpcContext = configuration.InitializeContext();

services.AddHttpContextAccessor();
services.AddScoped(ctx =>
{
IHttpContextAccessor contextAccessor = ctx.GetService<IHttpContextAccessor>();
var contextAccessor = ctx.GetService<IHttpContextAccessor>();

if (contextAccessor?.HttpContext?.User?.Identity?.IsAuthenticated == true)
{
string id = contextAccessor.HttpContext.User.FindFirst(ClaimTypes.Sid)?.Value;
string alias = contextAccessor.HttpContext.User.FindFirst(ClaimTypes.Name)?.Value;
var id = contextAccessor.HttpContext.User.FindFirst(ClaimTypes.Sid)?.Value;
var alias = contextAccessor.HttpContext.User.FindFirst(ClaimTypes.Name)?.Value;

if (Guid.TryParse(id, out Guid guidId) && !string.IsNullOrWhiteSpace(alias))
if (Guid.TryParse(id, out var guidId) && !string.IsNullOrWhiteSpace(alias))
{
var identity = new AuthIdentity(guidId, alias);
return kpcContext.AsUserContext(identity) as T;
return kpcContext.AsUserContext(new AuthIdentity(guidId, alias)) as T;
}
}

Expand Down
11 changes: 9 additions & 2 deletions src/Core/Context/DBContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
using KitchenPC.Core.Provisioning;
using KitchenPC.Core.Recipes;
using KitchenPC.Core.ShoppingLists;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using IngredientUsage = KitchenPC.Core.Ingredients.IngredientUsage;

namespace KitchenPC.Core.Context;
Expand All @@ -31,7 +33,8 @@ private AsUser(
Parser parser,
IDBAdapter adapter,
AuthIdentity identity,
DBContextCapabilities capabilities
DBContextCapabilities capabilities,
ILoggerFactory loggerFactory
)
{
this.ingParser = ingParser;
Expand All @@ -41,6 +44,7 @@ DBContextCapabilities capabilities
this.Identity = identity;
this.GetIdentity = () => identity;
this.Capabilities = capabilities;
this.LoggerFactory = loggerFactory;
}

public static AsUser Clone(DBContext context, AuthIdentity identity) =>
Expand All @@ -50,7 +54,8 @@ public static AsUser Clone(DBContext context, AuthIdentity identity) =>
context.parser,
context.Adapter,
identity,
context.Capabilities
context.Capabilities,
context.LoggerFactory
);
}

Expand All @@ -63,6 +68,7 @@ public static AsUser Clone(DBContext context, AuthIdentity identity) =>

/// <summary>Gets the optional in-memory capabilities configured for this context.</summary>
public DBContextCapabilities Capabilities { get; internal set; } = DBContextCapabilities.All;
public ILoggerFactory LoggerFactory { get; internal set; } = NullLoggerFactory.Instance;

/// <summary>Gets or sets the IDBAdapter used to directly talk with the database.</summary>
public IDBAdapter Adapter { get; set; }
Expand Down Expand Up @@ -166,6 +172,7 @@ public virtual void Initialize()

if (HasCapability(DBContextCapabilities.IngredientParsing))
{
NlpTracer.SetTracer(new DefaultTracer(LoggerFactory));
IngredientSynonyms.InitIndex(Adapter.IngredientLoader);
UnitSynonyms.InitIndex(Adapter.UnitLoader);
FormSynonyms.InitIndex(Adapter.FormLoader);
Expand Down
7 changes: 7 additions & 0 deletions src/Core/Context/DBContextBuilder.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using Microsoft.Extensions.Logging;

namespace KitchenPC.Core.Context;

Expand All @@ -24,6 +25,12 @@ public DBContextBuilder Identity(Func<AuthIdentity> getIdentity)
return this;
}

public DBContextBuilder Logging(ILoggerFactory loggerFactory)
{
context.LoggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory));
return this;
}

/// <summary>
/// Selects the optional in-memory indexes initialized by this context. All capabilities are
/// enabled by default for backward compatibility.
Expand Down
2 changes: 2 additions & 0 deletions src/Core/Context/IKPCContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using KitchenPC.Core.NLP;
using KitchenPC.Core.Recipes;
using KitchenPC.Core.ShoppingLists;
using Microsoft.Extensions.Logging;
using IngredientUsage = KitchenPC.Core.Ingredients.IngredientUsage;

namespace KitchenPC.Core.Context;
Expand All @@ -18,6 +19,7 @@ public interface IKPCContext
{
void Initialize();
AuthIdentity Identity { get; }
ILoggerFactory LoggerFactory { get; }

// Autocomplete support
IEnumerable<IngredientNode> AutocompleteIngredient(string query);
Expand Down
4 changes: 4 additions & 0 deletions src/Core/Context/StaticContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
using KitchenPC.Core.Provisioning.DTO;
using KitchenPC.Core.Recipes;
using KitchenPC.Core.ShoppingLists;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using IngredientUsage = KitchenPC.Core.Ingredients.IngredientUsage;

namespace KitchenPC.Core.Context;
Expand All @@ -27,6 +29,7 @@ public class StaticContext : IKPCContext, IProvisionTarget, IProvisionSource
public Func<AuthIdentity> GetIdentity { get; set; }
public Parser Parser { get; private set; }
public ModelerProxy ModelerProxy { get; private set; }
public ILoggerFactory LoggerFactory { get; internal set; } = NullLoggerFactory.Instance;

private DataStore store;
private IngredientParser ingParser;
Expand All @@ -51,6 +54,7 @@ private StaticContext()
/// </summary>
public void Initialize()
{
NlpTracer.SetTracer(new DefaultTracer(LoggerFactory));
var file = CompressedStore ? "KPCData.gz" : "KPCData.xml";
var path = Path.Combine(DataDirectory, file);
// TODO Fix logging
Expand Down
7 changes: 7 additions & 0 deletions src/Core/Context/StaticContextBuilder.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using Microsoft.Extensions.Logging;

namespace KitchenPC.Core.Context;

Expand Down Expand Up @@ -34,5 +35,11 @@ public StaticContextBuilder Identity(Func<AuthIdentity> getIdentity)
return this;
}

public StaticContextBuilder Logging(ILoggerFactory loggerFactory)
{
context.LoggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory));
return this;
}

public StaticContext Create() => context;
}
2 changes: 1 addition & 1 deletion src/Core/Context/StaticIngredientLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ public StaticIngredientLoader(DataStore store)

if (nodes.ContainsKey(ingId))
{
Parser.Log.ErrorFormat(
NlpTracer.Trace(TraceLevel.Error,
"[NLP Loader] Duplicate ingredient key due to bad DB data: {0} ({1})",
name,
ingId
Expand Down
Loading