diff --git a/packages/org.gamecult.eve.surface/GameCult.Eve.Surface.csproj b/packages/org.gamecult.eve.surface/GameCult.Eve.Surface.csproj index 442ae1a..72b5b3f 100644 --- a/packages/org.gamecult.eve.surface/GameCult.Eve.Surface.csproj +++ b/packages/org.gamecult.eve.surface/GameCult.Eve.Surface.csproj @@ -5,6 +5,14 @@ latest enable Portable Eve surface and provider contracts. + GameCult.Eve.Surface + 0.3.2 + GameCult + MPL-2.0 + https://github.com/GameCult/Eve + https://github.com/GameCult/Eve + README.md + eve;cultui;cultmesh;multiplayer;ui $(MSBuildThisFileDirectory)..\..\..\CultLib @@ -12,6 +20,9 @@ + + + + - diff --git a/packages/org.gamecult.eve.surface/README.md b/packages/org.gamecult.eve.surface/README.md index bd31b4d..b0e6dd5 100644 --- a/packages/org.gamecult.eve.surface/README.md +++ b/packages/org.gamecult.eve.surface/README.md @@ -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` diff --git a/scripts/pack-dotnet-surface.ps1 b/scripts/pack-dotnet-surface.ps1 new file mode 100644 index 0000000..963c843 --- /dev/null +++ b/scripts/pack-dotnet-surface.ps1 @@ -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 = @" + + + net10.0 + Exe + enable + $outputRoot;https://api.nuget.org/v3/index.json + + + + + +"@ + $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)"