Package the portable Eve surface for .NET

This commit is contained in:
Meta Vens 2026-08-18 06:33:29 +02:00
commit e7b09f755d
3 changed files with 119 additions and 5 deletions

View file

@ -5,6 +5,14 @@
<LangVersion>latest</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Description>Portable Eve surface and provider contracts.</Description>
<PackageId>GameCult.Eve.Surface</PackageId>
<Version>0.3.2</Version>
<Authors>GameCult</Authors>
<PackageLicenseExpression>MPL-2.0</PackageLicenseExpression>
<PackageProjectUrl>https://github.com/GameCult/Eve</PackageProjectUrl>
<RepositoryUrl>https://github.com/GameCult/Eve</RepositoryUrl>
<PackageReadmeFile>README.md</PackageReadmeFile>
<PackageTags>eve;cultui;cultmesh;multiplayer;ui</PackageTags>
<CultLibRoot Condition="'$(CultLibRoot)' == ''">$(MSBuildThisFileDirectory)..\..\..\CultLib</CultLibRoot>
</PropertyGroup>
@ -12,6 +20,9 @@
<ProjectReference Include="$(CultLibRoot)\src\GameCult.Caching\GameCult.Caching.csproj" />
<ProjectReference Include="$(CultLibRoot)\src\GameCult.Mesh\GameCult.Mesh.csproj" />
</ItemGroup>
<ItemGroup>
<None Include="README.md" Pack="true" PackagePath="\" />
</ItemGroup>
</Project>

View file

@ -16,15 +16,19 @@ bindings through `StateBindings`, and nested synced document regions through
schema, presentation kind, and route hint; renderers resolve that child through
CultMesh instead of rebuilding it with runtime-local projection code.
See `../../docs/surface-contract-v1.md` for the full contract and
`../../web/fixtures/cultui-embedded-surface.json` for the parity fixture.
Runtime discovery and required feature coverage live in
`../../tools/parity/parity-manifest.json`; active GUI runtimes must list
See the
[surface contract](https://github.com/GameCult/Eve/blob/main/docs/surface-contract-v1.md)
for the full contract and the
[embedded-surface fixture](https://github.com/GameCult/Eve/blob/main/web/fixtures/cultui-embedded-surface.json)
for parity evidence. Runtime discovery and required feature coverage live in
the [parity manifest](https://github.com/GameCult/Eve/blob/main/tools/parity/parity-manifest.json);
active GUI runtimes must list
`embeddedDocuments` as a supported feature and require the `embedded-surface`
fixture.
Verification entrypoints:
- clean .NET package consumer: `powershell -ExecutionPolicy Bypass -File .\scripts\pack-dotnet-surface.ps1`
- C# serialization: `dotnet test tests/GameCult.Eve.Surface.Serialization.Tests/GameCult.Eve.Surface.Serialization.Tests.csproj`
- Browser/TypeScript: `node --test web\eve-dsl.test.mjs`
- Semantic runtime matrix: `powershell -ExecutionPolicy Bypass -File .\scripts\run-parity-harness.ps1`

View file

@ -0,0 +1,99 @@
param(
[string] $CultLibRoot = "",
[string] $Configuration = "Release",
[string] $OutputDirectory = "artifacts\nuget",
[switch] $SkipConsumerSmoke
)
$ErrorActionPreference = "Stop"
$repoRoot = Split-Path -Parent $PSScriptRoot
if ([string]::IsNullOrWhiteSpace($CultLibRoot)) {
$CultLibRoot = Join-Path (Split-Path -Parent $repoRoot) "CultLib"
}
$cultLibPath = [IO.Path]::GetFullPath($CultLibRoot)
$cultLibPack = Join-Path $cultLibPath "scripts\pack-nuget.ps1"
if (-not (Test-Path -LiteralPath $cultLibPack)) {
throw "CultLib NuGet packer was not found at '$cultLibPack'."
}
$outputRoot = if ([IO.Path]::IsPathRooted($OutputDirectory)) {
[IO.Path]::GetFullPath($OutputDirectory)
} else {
[IO.Path]::GetFullPath((Join-Path $repoRoot $OutputDirectory))
}
& $cultLibPack -Configuration $Configuration -OutputDirectory $outputRoot -SkipConsumerSmoke
if ($LASTEXITCODE -ne 0) {
throw "CultLib NuGet dependency pack failed with exit code $LASTEXITCODE."
}
$surfaceProject = Join-Path $repoRoot "packages\org.gamecult.eve.surface\GameCult.Eve.Surface.csproj"
dotnet pack $surfaceProject -c $Configuration -o $outputRoot `
-p:CultLibRoot=$cultLibPath -p:NoWarn=1591%3BCS8632 `
--nologo --verbosity quiet
if ($LASTEXITCODE -ne 0) {
throw "Eve surface NuGet pack failed with exit code $LASTEXITCODE."
}
$surfacePackage = Get-ChildItem -LiteralPath $outputRoot -Filter "GameCult.Eve.Surface.*.nupkg" |
Where-Object { $_.Name -notlike "*.snupkg" } |
Sort-Object LastWriteTimeUtc -Descending |
Select-Object -First 1
if (-not $surfacePackage) {
throw "GameCult.Eve.Surface package was not produced."
}
$version = [regex]::Match(
$surfacePackage.Name,
'^GameCult\.Eve\.Surface\.(.+)\.nupkg$').Groups[1].Value
if (-not $SkipConsumerSmoke) {
$smokeRoot = Join-Path ([IO.Path]::GetTempPath()) ("eve-surface-consumer-" + [guid]::NewGuid().ToString("N"))
New-Item -ItemType Directory -Force -Path $smokeRoot | Out-Null
try {
$projectDocument = @"
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<OutputType>Exe</OutputType>
<ImplicitUsings>enable</ImplicitUsings>
<RestoreSources>$outputRoot;https://api.nuget.org/v3/index.json</RestoreSources>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="GameCult.Eve.Surface" Version="$version" />
</ItemGroup>
</Project>
"@
$program = @"
using GameCult.Eve.Surface;
var surface = EveSurface.Create("sample.counter")
.Provider("sample.counter-provider", "sample.daemon")
.Title("Clean package consumer")
.RootColumn("root", root => root.Title("title", "Portable Eve"))
.Build();
if (surface.Schema != EveSurfaceDocument.SchemaId)
throw new InvalidOperationException("The packed surface contract returned the wrong schema.");
Console.WriteLine(surface.Schema);
"@
[IO.File]::WriteAllText(
(Join-Path $smokeRoot "Consumer.csproj"),
$projectDocument,
[Text.UTF8Encoding]::new($false))
[IO.File]::WriteAllText(
(Join-Path $smokeRoot "Program.cs"),
$program,
[Text.UTF8Encoding]::new($false))
dotnet run --project (Join-Path $smokeRoot "Consumer.csproj") -c $Configuration `
--nologo --verbosity quiet
if ($LASTEXITCODE -ne 0) {
throw "Eve surface clean NuGet consumer failed with exit code $LASTEXITCODE."
}
} finally {
if (Test-Path -LiteralPath $smokeRoot) {
Remove-Item -LiteralPath $smokeRoot -Recurse -Force
}
}
}
Write-Host "Eve .NET package feed: $outputRoot"
Write-Host "GameCult.Eve.Surface: $version"
Write-Host "Clean PackageReference consumer: $(-not $SkipConsumerSmoke)"