From 0c24dd9a2f20db7e184f185c2c30df6a602448b0 Mon Sep 17 00:00:00 2001
From: tobias-tengler <45513122+tobias-tengler@users.noreply.github.com>
Date: Thu, 30 Jul 2026 10:22:08 +0200
Subject: [PATCH 01/11] Add Nitro Fusion publishing to Aspire
---
src/All.slnx | 4 +
.../Fusion.Aspire/AspireCompositionHelper.cs | 60 +
.../CommandLineSchemaExporter.cs | 458 +
.../GraphQLResourceBuilderExtensions.cs | 47 +
.../src/Fusion.Aspire/GraphQLResourceModel.cs | 115 +
.../GraphQLSourceSchemaAnnotation.cs | 10 +
.../GraphQLSourceSchemaValidator.cs | 45 +
.../HotChocolate.Fusion.Aspire.csproj | 2 +
.../src/Fusion.Aspire/SchemaComposition.cs | 262 +-
.../Fusion.Aspire/SourceSchemaLocationType.cs | 3 +-
.../CommandLineSchemaExporterTests.cs | 337 +
.../GraphQLResourceBuilderExtensionsTests.cs | 56 +
.../GraphQLResourceModelTests.cs | 121 +
.../ChilliCream.Nitro.Aspire.csproj | 32 +
.../FusionDeploymentResource.cs | 32 +
.../FusionPipeline.cs | 283 +
.../FusionPipelineExecutor.cs | 930 ++
.../FusionPipelineResource.cs | 5 +
.../IFusionPipelineExecutor.cs | 18 +
.../ChilliCream.Nitro.Aspire/NitroResource.cs | 15 +
.../NitroResourceBuilderExtensions.cs | 238 +
.../src/ChilliCream.Nitro.Aspire/README.md | 29 +
.../FUSION_ASPIRE_PUBLISH_DEPLOY.md | 386 +
.../ChilliCream.Nitro.Fusion/.graphqlrc.json | 25 +
.../ChilliCream.Nitro.Fusion.csproj | 33 +
.../FusionArchiveContent.cs | 140 +
.../FusionDeploymentException.cs | 17 +
.../FusionDeploymentWorkflow.cs | 593 +
.../FusionIdentityCollisionException.cs | 12 +
.../FusionIndeterminateStateException.cs | 27 +
.../FusionPublicationRequest.cs | 14 +
.../FusionSourceSchemaUpload.cs | 10 +
.../FusionSourceSchemaVersion.cs | 6 +
.../ChilliCream.Nitro.Fusion/FusionTarget.cs | 10 +
.../Generated/FusionApiClient.Client.cs | 11092 ++++++++++++++++
.../IFusionDeploymentWorkflow.cs | 23 +
.../NitroFusionServiceCollectionExtensions.cs | 27 +
.../Operations/Fragments.graphql | 3 +
.../Operations/FusionDeployment.graphql | 65 +
.../Operations/FusionSourceSchema.graphql | 11 +
.../src/ChilliCream.Nitro.Fusion/README.md | 14 +
.../Transport/FusionApiTransportFactory.cs | 323 +
.../Transport/IFusionDeploymentTransport.cs | 78 +
.../ChilliCream.Nitro.Aspire.Tests.csproj | 15 +
.../FusionPipelineTests.cs | 230 +
.../ChilliCream.Nitro.Fusion.Tests.csproj | 15 +
.../FusionDeploymentWorkflowTests.cs | 454 +
47 files changed, 16623 insertions(+), 102 deletions(-)
create mode 100644 src/HotChocolate/Fusion/src/Fusion.Aspire/CommandLineSchemaExporter.cs
create mode 100644 src/HotChocolate/Fusion/src/Fusion.Aspire/GraphQLResourceModel.cs
create mode 100644 src/HotChocolate/Fusion/src/Fusion.Aspire/GraphQLSourceSchemaValidator.cs
create mode 100644 src/HotChocolate/Fusion/test/Fusion.Aspire.Tests/CommandLineSchemaExporterTests.cs
create mode 100644 src/HotChocolate/Fusion/test/Fusion.Aspire.Tests/GraphQLResourceModelTests.cs
create mode 100644 src/Nitro/Common/src/ChilliCream.Nitro.Aspire/ChilliCream.Nitro.Aspire.csproj
create mode 100644 src/Nitro/Common/src/ChilliCream.Nitro.Aspire/FusionDeploymentResource.cs
create mode 100644 src/Nitro/Common/src/ChilliCream.Nitro.Aspire/FusionPipeline.cs
create mode 100644 src/Nitro/Common/src/ChilliCream.Nitro.Aspire/FusionPipelineExecutor.cs
create mode 100644 src/Nitro/Common/src/ChilliCream.Nitro.Aspire/FusionPipelineResource.cs
create mode 100644 src/Nitro/Common/src/ChilliCream.Nitro.Aspire/IFusionPipelineExecutor.cs
create mode 100644 src/Nitro/Common/src/ChilliCream.Nitro.Aspire/NitroResource.cs
create mode 100644 src/Nitro/Common/src/ChilliCream.Nitro.Aspire/NitroResourceBuilderExtensions.cs
create mode 100644 src/Nitro/Common/src/ChilliCream.Nitro.Aspire/README.md
create mode 100644 src/Nitro/Common/src/ChilliCream.Nitro.Client/FUSION_ASPIRE_PUBLISH_DEPLOY.md
create mode 100644 src/Nitro/Common/src/ChilliCream.Nitro.Fusion/.graphqlrc.json
create mode 100644 src/Nitro/Common/src/ChilliCream.Nitro.Fusion/ChilliCream.Nitro.Fusion.csproj
create mode 100644 src/Nitro/Common/src/ChilliCream.Nitro.Fusion/FusionArchiveContent.cs
create mode 100644 src/Nitro/Common/src/ChilliCream.Nitro.Fusion/FusionDeploymentException.cs
create mode 100644 src/Nitro/Common/src/ChilliCream.Nitro.Fusion/FusionDeploymentWorkflow.cs
create mode 100644 src/Nitro/Common/src/ChilliCream.Nitro.Fusion/FusionIdentityCollisionException.cs
create mode 100644 src/Nitro/Common/src/ChilliCream.Nitro.Fusion/FusionIndeterminateStateException.cs
create mode 100644 src/Nitro/Common/src/ChilliCream.Nitro.Fusion/FusionPublicationRequest.cs
create mode 100644 src/Nitro/Common/src/ChilliCream.Nitro.Fusion/FusionSourceSchemaUpload.cs
create mode 100644 src/Nitro/Common/src/ChilliCream.Nitro.Fusion/FusionSourceSchemaVersion.cs
create mode 100644 src/Nitro/Common/src/ChilliCream.Nitro.Fusion/FusionTarget.cs
create mode 100644 src/Nitro/Common/src/ChilliCream.Nitro.Fusion/Generated/FusionApiClient.Client.cs
create mode 100644 src/Nitro/Common/src/ChilliCream.Nitro.Fusion/IFusionDeploymentWorkflow.cs
create mode 100644 src/Nitro/Common/src/ChilliCream.Nitro.Fusion/NitroFusionServiceCollectionExtensions.cs
create mode 100644 src/Nitro/Common/src/ChilliCream.Nitro.Fusion/Operations/Fragments.graphql
create mode 100644 src/Nitro/Common/src/ChilliCream.Nitro.Fusion/Operations/FusionDeployment.graphql
create mode 100644 src/Nitro/Common/src/ChilliCream.Nitro.Fusion/Operations/FusionSourceSchema.graphql
create mode 100644 src/Nitro/Common/src/ChilliCream.Nitro.Fusion/README.md
create mode 100644 src/Nitro/Common/src/ChilliCream.Nitro.Fusion/Transport/FusionApiTransportFactory.cs
create mode 100644 src/Nitro/Common/src/ChilliCream.Nitro.Fusion/Transport/IFusionDeploymentTransport.cs
create mode 100644 src/Nitro/Common/test/ChilliCream.Nitro.Aspire.Tests/ChilliCream.Nitro.Aspire.Tests.csproj
create mode 100644 src/Nitro/Common/test/ChilliCream.Nitro.Aspire.Tests/FusionPipelineTests.cs
create mode 100644 src/Nitro/Common/test/ChilliCream.Nitro.Fusion.Tests/ChilliCream.Nitro.Fusion.Tests.csproj
create mode 100644 src/Nitro/Common/test/ChilliCream.Nitro.Fusion.Tests/FusionDeploymentWorkflowTests.cs
diff --git a/src/All.slnx b/src/All.slnx
index a4dad5e1730..408c384dc68 100644
--- a/src/All.slnx
+++ b/src/All.slnx
@@ -410,13 +410,17 @@
+
+
+
+
diff --git a/src/HotChocolate/Fusion/src/Fusion.Aspire/AspireCompositionHelper.cs b/src/HotChocolate/Fusion/src/Fusion.Aspire/AspireCompositionHelper.cs
index b23717b0cb9..b354272996e 100644
--- a/src/HotChocolate/Fusion/src/Fusion.Aspire/AspireCompositionHelper.cs
+++ b/src/HotChocolate/Fusion/src/Fusion.Aspire/AspireCompositionHelper.cs
@@ -2,12 +2,68 @@
using System.Text;
using HotChocolate.Fusion.Logging;
using HotChocolate.Fusion.Packaging;
+using HotChocolate.Fusion.SourceSchema.Packaging;
using Microsoft.Extensions.Logging;
namespace HotChocolate.Fusion.Aspire;
internal static class AspireCompositionHelper
{
+ public static async Task TryComposeArchivesAsync(
+ string fusionArchivePath,
+ IReadOnlyList archives,
+ GraphQLCompositionSettings settings,
+ ILogger logger,
+ CancellationToken cancellationToken)
+ {
+ var sourceSchemas = new List(archives.Count);
+
+ try
+ {
+ foreach (var archiveInfo in archives)
+ {
+ using var archive = FusionSourceSchemaArchive.Open(
+ archiveInfo.ArchivePath);
+ var schema = await archive.TryGetSchemaAsync(cancellationToken)
+ ?? throw new InvalidOperationException(
+ $"Fusion source archive '{archiveInfo.Name}' has no schema.");
+ var sourceSettings =
+ await archive.TryGetSettingsAsync(cancellationToken)
+ ?? throw new InvalidOperationException(
+ $"Fusion source archive '{archiveInfo.Name}' has no settings.");
+ var extensions =
+ await archive.TryGetSchemaExtensionsAsync(cancellationToken);
+
+ sourceSchemas.Add(
+ new SourceSchemaInfo
+ {
+ Name = archiveInfo.Name,
+ Schema = new SourceSchemaText(
+ archiveInfo.Name,
+ Encoding.UTF8.GetString(schema.Span),
+ extensions is null
+ ? null
+ : Encoding.UTF8.GetString(extensions.Value.Span)),
+ SchemaSettings = sourceSettings
+ });
+ }
+
+ return await TryComposeAsync(
+ fusionArchivePath,
+ [.. sourceSchemas],
+ settings,
+ logger,
+ cancellationToken);
+ }
+ finally
+ {
+ foreach (var sourceSchema in sourceSchemas)
+ {
+ sourceSchema.SchemaSettings.Dispose();
+ }
+ }
+ }
+
public static async Task TryComposeAsync(
string fusionArchivePath,
ImmutableArray newSourceSchemas,
@@ -100,3 +156,7 @@ private static string FormatMultilineMessage(string message)
return string.Join(Environment.NewLine + " ", lines);
}
}
+
+internal readonly record struct SourceSchemaArchiveInfo(
+ string Name,
+ string ArchivePath);
diff --git a/src/HotChocolate/Fusion/src/Fusion.Aspire/CommandLineSchemaExporter.cs b/src/HotChocolate/Fusion/src/Fusion.Aspire/CommandLineSchemaExporter.cs
new file mode 100644
index 00000000000..f38db0480be
--- /dev/null
+++ b/src/HotChocolate/Fusion/src/Fusion.Aspire/CommandLineSchemaExporter.cs
@@ -0,0 +1,458 @@
+using System.ComponentModel;
+using System.Diagnostics;
+using System.Text;
+using System.Text.Json;
+using Aspire.Hosting.ApplicationModel;
+using IOPath = System.IO.Path;
+
+namespace HotChocolate.Fusion.Aspire;
+
+internal static class CommandLineSchemaExporter
+{
+ private const int MaxCapturedOutputLength = 32 * 1024;
+ private static readonly TimeSpan s_processTerminationTimeout = TimeSpan.FromSeconds(10);
+
+ public static async Task ExportAsync(
+ IResource resource,
+ GraphQLSourceSchemaAnnotation declaration,
+ string outputDirectory,
+ CancellationToken cancellationToken)
+ {
+ ArgumentNullException.ThrowIfNull(resource);
+ ArgumentNullException.ThrowIfNull(declaration);
+ ArgumentException.ThrowIfNullOrWhiteSpace(outputDirectory);
+
+ if (declaration is not
+ {
+ Location: SourceSchemaLocationType.CommandLineExport,
+ ExportSchemaName: { } schemaName,
+ ExportConfiguration: { } configuration,
+ ExportTargetFramework: { } targetFramework,
+ ExportTimeout: { } timeout
+ }
+ || string.IsNullOrWhiteSpace(schemaName)
+ || string.IsNullOrWhiteSpace(configuration)
+ || string.IsNullOrWhiteSpace(targetFramework)
+ || timeout <= TimeSpan.Zero
+ || declaration.ExportRuntimeIdentifier is { } runtimeIdentifier
+ && string.IsNullOrWhiteSpace(runtimeIdentifier))
+ {
+ throw new InvalidOperationException(
+ $"Resource '{resource.Name}' does not have a complete command-line export declaration.");
+ }
+
+ cancellationToken.ThrowIfCancellationRequested();
+
+ var projectPath = IOPath.GetFullPath(GraphQLResourceModel.GetProjectPath(resource));
+ outputDirectory = IOPath.GetFullPath(outputDirectory);
+ Directory.CreateDirectory(outputDirectory);
+
+ var schemaPath = IOPath.Combine(outputDirectory, "schema.graphqls");
+ var settingsPath = IOPath.Combine(outputDirectory, "schema-settings.json");
+
+ DeleteExistingArtifact(schemaPath);
+ DeleteExistingArtifact(settingsPath);
+
+ var startInfo = CreateStartInfo(
+ projectPath,
+ schemaPath,
+ schemaName,
+ configuration,
+ targetFramework,
+ declaration.ExportRuntimeIdentifier);
+ var processResult = await RunProcessAsync(
+ startInfo,
+ timeout,
+ resource.Name,
+ cancellationToken);
+
+ if (processResult.ExitCode != 0)
+ {
+ throw new InvalidOperationException(
+ $"Schema export for resource '{resource.Name}' exited with code "
+ + $"{processResult.ExitCode}. Child-process output was suppressed because it may "
+ + "contain sensitive data.");
+ }
+
+ await ValidateArtifactsAsync(
+ resource.Name,
+ schemaName,
+ schemaPath,
+ settingsPath,
+ cancellationToken);
+
+ return new(
+ schemaPath,
+ settingsPath,
+ projectPath,
+ configuration,
+ targetFramework,
+ declaration.ExportRuntimeIdentifier);
+ }
+
+ internal static ProcessStartInfo CreateStartInfo(
+ string projectPath,
+ string schemaPath,
+ string schemaName,
+ string configuration,
+ string targetFramework,
+ string? runtimeIdentifier)
+ {
+ ArgumentException.ThrowIfNullOrWhiteSpace(projectPath);
+ ArgumentException.ThrowIfNullOrWhiteSpace(schemaPath);
+ ArgumentException.ThrowIfNullOrWhiteSpace(schemaName);
+ ArgumentException.ThrowIfNullOrWhiteSpace(configuration);
+ ArgumentException.ThrowIfNullOrWhiteSpace(targetFramework);
+
+ if (runtimeIdentifier is not null)
+ {
+ ArgumentException.ThrowIfNullOrWhiteSpace(runtimeIdentifier);
+ }
+
+ projectPath = IOPath.GetFullPath(projectPath);
+ schemaPath = IOPath.GetFullPath(schemaPath);
+
+ var startInfo = new ProcessStartInfo
+ {
+ FileName = "dotnet",
+ WorkingDirectory = IOPath.GetDirectoryName(projectPath)!,
+ RedirectStandardOutput = true,
+ RedirectStandardError = true,
+ UseShellExecute = false,
+ CreateNoWindow = true
+ };
+
+ startInfo.ArgumentList.Add("run");
+ startInfo.ArgumentList.Add("--project");
+ startInfo.ArgumentList.Add(projectPath);
+ startInfo.ArgumentList.Add("--configuration");
+ startInfo.ArgumentList.Add(configuration);
+ startInfo.ArgumentList.Add("--framework");
+ startInfo.ArgumentList.Add(targetFramework);
+
+ if (runtimeIdentifier is not null)
+ {
+ startInfo.ArgumentList.Add("--runtime");
+ startInfo.ArgumentList.Add(runtimeIdentifier);
+ }
+
+ startInfo.ArgumentList.Add("--no-launch-profile");
+ startInfo.ArgumentList.Add("--");
+ startInfo.ArgumentList.Add("schema");
+ startInfo.ArgumentList.Add("export");
+ startInfo.ArgumentList.Add("--output");
+ startInfo.ArgumentList.Add(schemaPath);
+ startInfo.ArgumentList.Add("--schema-name");
+ startInfo.ArgumentList.Add(schemaName);
+
+ ApplyEnvironmentAllowList(startInfo);
+ return startInfo;
+ }
+
+ internal static async Task RunProcessAsync(
+ ProcessStartInfo startInfo,
+ TimeSpan timeout,
+ string resourceName,
+ CancellationToken cancellationToken)
+ {
+ ArgumentNullException.ThrowIfNull(startInfo);
+ ArgumentOutOfRangeException.ThrowIfLessThanOrEqual(timeout, TimeSpan.Zero);
+ ArgumentException.ThrowIfNullOrWhiteSpace(resourceName);
+ cancellationToken.ThrowIfCancellationRequested();
+
+ using var process = new Process { StartInfo = startInfo };
+ using var timeoutSource = new CancellationTokenSource(timeout);
+ using var linkedSource = CancellationTokenSource.CreateLinkedTokenSource(
+ cancellationToken,
+ timeoutSource.Token);
+ using var outputSource = new CancellationTokenSource();
+
+ if (!process.Start())
+ {
+ throw new InvalidOperationException(
+ $"Could not start schema export for resource '{resourceName}'.");
+ }
+
+ var stdout = CaptureAsync(
+ process.StandardOutput,
+ retainOutput: true,
+ outputSource.Token);
+ var stderr = CaptureAsync(
+ process.StandardError,
+ retainOutput: false,
+ outputSource.Token);
+
+ try
+ {
+ try
+ {
+ await process.WaitForExitAsync(linkedSource.Token);
+ }
+ catch (OperationCanceledException)
+ when (cancellationToken.IsCancellationRequested
+ || timeoutSource.IsCancellationRequested)
+ {
+ await TerminateProcessAsync(
+ process,
+ stdout,
+ stderr,
+ outputSource);
+
+ if (cancellationToken.IsCancellationRequested)
+ {
+ throw new OperationCanceledException(cancellationToken);
+ }
+
+ throw new TimeoutException(
+ $"Schema export for resource '{resourceName}' exceeded {timeout}.");
+ }
+ catch
+ {
+ await TerminateProcessAsync(
+ process,
+ stdout,
+ stderr,
+ outputSource);
+ throw;
+ }
+
+ var captured = await Task.WhenAll(stdout, stderr);
+ return new(
+ process.ExitCode,
+ captured[0].Output,
+ captured[0].WasTruncated,
+ captured[1].CharacterCount);
+ }
+ finally
+ {
+ if (!HasExited(process))
+ {
+ await TerminateProcessAsync(
+ process,
+ stdout,
+ stderr,
+ outputSource);
+ }
+ }
+ }
+
+ internal static void ApplyEnvironmentAllowList(ProcessStartInfo startInfo)
+ {
+ ArgumentNullException.ThrowIfNull(startInfo);
+
+ var inheritedEnvironment = startInfo.Environment.ToArray();
+ var comparison = OperatingSystem.IsWindows()
+ ? StringComparison.OrdinalIgnoreCase
+ : StringComparison.Ordinal;
+
+ startInfo.Environment.Clear();
+
+ CopyIfPresent("PATH");
+ CopyIfPresent("DOTNET_ROOT");
+ CopyIfPresent("DOTNET_ROOT_X64");
+ CopyIfPresent("DOTNET_ROOT_X86");
+ CopyIfPresent("DOTNET_ROOT_ARM64");
+ CopyIfPresent("DOTNET_CLI_HOME");
+ CopyIfPresent("NUGET_PACKAGES");
+
+ if (OperatingSystem.IsWindows())
+ {
+ CopyIfPresent("SystemRoot");
+ CopyIfPresent("SystemDrive");
+ CopyIfPresent("USERPROFILE");
+ CopyIfPresent("LOCALAPPDATA");
+ }
+ else
+ {
+ CopyIfPresent("HOME");
+ }
+
+ CopyIfPresent("TMPDIR");
+ CopyIfPresent("TMP");
+ CopyIfPresent("TEMP");
+
+ startInfo.Environment["DOTNET_NOLOGO"] = "1";
+ startInfo.Environment["DOTNET_CLI_TELEMETRY_OPTOUT"] = "1";
+
+ void CopyIfPresent(string name)
+ {
+ foreach (var pair in inheritedEnvironment)
+ {
+ if (pair.Key.Equals(name, comparison)
+ && !string.IsNullOrEmpty(pair.Value))
+ {
+ startInfo.Environment[name] = pair.Value;
+ return;
+ }
+ }
+ }
+ }
+
+ internal static async Task ValidateArtifactsAsync(
+ string resourceName,
+ string schemaName,
+ string schemaPath,
+ string settingsPath,
+ CancellationToken cancellationToken)
+ {
+ ArgumentException.ThrowIfNullOrWhiteSpace(resourceName);
+ ArgumentException.ThrowIfNullOrWhiteSpace(schemaName);
+ ArgumentException.ThrowIfNullOrWhiteSpace(schemaPath);
+ ArgumentException.ThrowIfNullOrWhiteSpace(settingsPath);
+
+ if (!File.Exists(schemaPath) || !File.Exists(settingsPath))
+ {
+ throw new InvalidOperationException(
+ $"Schema export for resource '{resourceName}' did not produce both "
+ + "schema.graphqls and schema-settings.json.");
+ }
+
+ var schemaText = await File.ReadAllTextAsync(schemaPath, cancellationToken);
+ var settingsText = await File.ReadAllTextAsync(settingsPath, cancellationToken);
+
+ if (string.IsNullOrWhiteSpace(settingsText))
+ {
+ throw new InvalidOperationException(
+ $"Schema export for resource '{resourceName}' produced empty schema-settings.json.");
+ }
+
+ using var settings = JsonDocument.Parse(settingsText);
+ var configuration = SchemaComposition.ReadEndpointConfiguration(
+ resourceName,
+ schemaName,
+ settings);
+ GraphQLSourceSchemaValidator.Validate(
+ resourceName,
+ configuration,
+ schemaText);
+ }
+
+ private static async Task CaptureAsync(
+ StreamReader reader,
+ bool retainOutput,
+ CancellationToken cancellationToken)
+ {
+ StringBuilder? output = retainOutput
+ ? new StringBuilder(MaxCapturedOutputLength)
+ : null;
+ var buffer = new char[4096];
+ var characterCount = 0L;
+
+ while (true)
+ {
+ var count = await reader.ReadAsync(buffer.AsMemory(), cancellationToken);
+ if (count == 0)
+ {
+ break;
+ }
+
+ characterCount += count;
+
+ if (output?.Length is < MaxCapturedOutputLength)
+ {
+ output.Append(
+ buffer,
+ 0,
+ Math.Min(count, MaxCapturedOutputLength - output.Length));
+ }
+ }
+
+ return new(
+ output?.ToString() ?? string.Empty,
+ characterCount,
+ characterCount > MaxCapturedOutputLength);
+ }
+
+ private static async Task TerminateProcessAsync(
+ Process process,
+ Task stdout,
+ Task stderr,
+ CancellationTokenSource outputSource)
+ {
+ TryKillProcess(process, entireProcessTree: true);
+
+ if (!HasExited(process))
+ {
+ TryKillProcess(process, entireProcessTree: false);
+ }
+
+ using var cleanupSource = new CancellationTokenSource(s_processTerminationTimeout);
+
+ try
+ {
+ await process.WaitForExitAsync(cleanupSource.Token);
+ await Task.WhenAll(stdout, stderr).WaitAsync(cleanupSource.Token);
+ }
+ catch (OperationCanceledException) when (cleanupSource.IsCancellationRequested)
+ {
+ outputSource.Cancel();
+ }
+ catch (IOException)
+ {
+ outputSource.Cancel();
+ }
+ catch (ObjectDisposedException)
+ {
+ outputSource.Cancel();
+ }
+ }
+
+ private static bool HasExited(Process process)
+ {
+ try
+ {
+ return process.HasExited;
+ }
+ catch (InvalidOperationException)
+ {
+ return true;
+ }
+ }
+
+ private static void TryKillProcess(Process process, bool entireProcessTree)
+ {
+ try
+ {
+ if (!process.HasExited)
+ {
+ process.Kill(entireProcessTree);
+ }
+ }
+ catch (InvalidOperationException)
+ {
+ }
+ catch (NotSupportedException)
+ {
+ }
+ catch (Win32Exception)
+ {
+ }
+ }
+
+ private static void DeleteExistingArtifact(string path)
+ {
+ if (File.Exists(path))
+ {
+ File.Delete(path);
+ }
+ }
+
+ private readonly record struct CapturedOutput(
+ string Output,
+ long CharacterCount,
+ bool WasTruncated);
+}
+
+internal sealed record CommandLineSchemaExportResult(
+ string SchemaPath,
+ string SettingsPath,
+ string ProjectPath,
+ string Configuration,
+ string TargetFramework,
+ string? RuntimeIdentifier);
+
+internal sealed record CommandLineProcessResult(
+ int ExitCode,
+ string StandardOutput,
+ bool StandardOutputWasTruncated,
+ long StandardErrorCharacterCount);
diff --git a/src/HotChocolate/Fusion/src/Fusion.Aspire/GraphQLResourceBuilderExtensions.cs b/src/HotChocolate/Fusion/src/Fusion.Aspire/GraphQLResourceBuilderExtensions.cs
index cb38240d4c0..79e340c3bbb 100644
--- a/src/HotChocolate/Fusion/src/Fusion.Aspire/GraphQLResourceBuilderExtensions.cs
+++ b/src/HotChocolate/Fusion/src/Fusion.Aspire/GraphQLResourceBuilderExtensions.cs
@@ -72,6 +72,53 @@ public static IResourceBuilder WithGraphQLSchemaFile(
return builder;
}
+ ///
+ /// Marks a project resource as exporting a GraphQL schema through the Hot Chocolate
+ /// command-line schema exporter during publishing.
+ ///
+ /// The project resource builder.
+ /// The exact registered schema name to export.
+ /// The build configuration used by dotnet run.
+ /// The exact target framework used by dotnet run.
+ ///
+ /// The runtime identifier used by dotnet run, or for an
+ /// explicitly portable export.
+ ///
+ /// The maximum time allowed for the child process.
+ /// The resource builder for chaining.
+ public static IResourceBuilder WithGraphQLSchemaExport(
+ this IResourceBuilder builder,
+ string schemaName,
+ string configuration,
+ string targetFramework,
+ string? runtimeIdentifier,
+ TimeSpan timeout)
+ {
+ ArgumentException.ThrowIfNullOrWhiteSpace(schemaName);
+ ArgumentException.ThrowIfNullOrWhiteSpace(configuration);
+ ArgumentException.ThrowIfNullOrWhiteSpace(targetFramework);
+ ArgumentOutOfRangeException.ThrowIfLessThanOrEqual(timeout, TimeSpan.Zero);
+
+ if (runtimeIdentifier is not null)
+ {
+ ArgumentException.ThrowIfNullOrWhiteSpace(runtimeIdentifier);
+ }
+
+ builder.WithAnnotation(
+ new GraphQLSourceSchemaAnnotation
+ {
+ SourceSchemaName = schemaName,
+ ExportSchemaName = schemaName,
+ ExportConfiguration = configuration,
+ ExportTargetFramework = targetFramework,
+ ExportRuntimeIdentifier = runtimeIdentifier,
+ ExportTimeout = timeout,
+ Location = SourceSchemaLocationType.CommandLineExport
+ });
+
+ return builder;
+ }
+
///
/// Marks a resource as needing GraphQL schema composition from its referenced subgraphs.
///
diff --git a/src/HotChocolate/Fusion/src/Fusion.Aspire/GraphQLResourceModel.cs b/src/HotChocolate/Fusion/src/Fusion.Aspire/GraphQLResourceModel.cs
new file mode 100644
index 00000000000..652df83481e
--- /dev/null
+++ b/src/HotChocolate/Fusion/src/Fusion.Aspire/GraphQLResourceModel.cs
@@ -0,0 +1,115 @@
+using System.Diagnostics.CodeAnalysis;
+using Aspire.Hosting.ApplicationModel;
+using IOPath = System.IO.Path;
+
+namespace HotChocolate.Fusion.Aspire;
+
+internal static class GraphQLResourceModel
+{
+ [SuppressMessage(
+ "Trimming",
+ "IL2075:'this' argument does not satisfy 'DynamicallyAccessedMembersAttribute' "
+ + "in call to target method.")]
+ public static IReadOnlyList GetReferencedSourceSchemas(
+ IResourceWithEndpoints compositionResource,
+ DistributedApplicationModel model)
+ {
+ ArgumentNullException.ThrowIfNull(compositionResource);
+ ArgumentNullException.ThrowIfNull(model);
+
+ var referencedResources = new HashSet(
+ ReferenceEqualityComparer.Instance);
+
+ foreach (var annotation in compositionResource.Annotations)
+ {
+ switch (annotation)
+ {
+ case ResourceRelationshipAnnotation relationship:
+ referencedResources.Add(relationship.Resource);
+ break;
+
+ case var endpointReference
+ when endpointReference.GetType().FullName
+ == "Aspire.Hosting.ApplicationModel.EndpointReferenceAnnotation":
+ var resourceProperty = endpointReference.GetType().GetProperty("Resource");
+ if (resourceProperty?.GetValue(endpointReference) is IResource resource)
+ {
+ referencedResources.Add(resource);
+ }
+ break;
+ }
+ }
+
+ return model.Resources
+ .OfType()
+ .Where(resource => referencedResources.Contains(resource))
+ .Where(resource => resource.HasGraphQLSchema())
+ .Select(resource => new GraphQLSourceSchemaResource(
+ resource,
+ GetSourceSchema(resource)))
+ .ToArray();
+ }
+
+ public static GraphQLSourceSchemaAnnotation GetSourceSchema(
+ IResource resource)
+ => resource.Annotations.OfType().Single();
+
+ public static GraphQLSchemaCompositionAnnotation GetComposition(
+ IResource resource)
+ => resource.Annotations.OfType().Single();
+
+ public static GraphQLProjectSchemaPaths GetProjectSchemaPaths(
+ IResource resource,
+ GraphQLSourceSchemaAnnotation declaration)
+ {
+ ArgumentNullException.ThrowIfNull(resource);
+ ArgumentNullException.ThrowIfNull(declaration);
+
+ if (declaration.Location is not SourceSchemaLocationType.ProjectDirectory)
+ {
+ throw new InvalidOperationException(
+ $"GraphQL source resource '{resource.Name}' does not use a project schema file.");
+ }
+
+ var projectPath = IOPath.GetFullPath(GetProjectPath(resource));
+ var projectDirectory = IOPath.GetDirectoryName(projectPath)!;
+ var schemaPath = IOPath.GetFullPath(
+ IOPath.Combine(
+ projectDirectory,
+ declaration.SchemaPath ?? "schema.graphqls"));
+ var schemaDirectory = IOPath.GetDirectoryName(schemaPath)!;
+ var schemaFileName = IOPath.GetFileNameWithoutExtension(schemaPath);
+
+ return new(
+ projectPath,
+ schemaPath,
+ IOPath.Combine(schemaDirectory, $"{schemaFileName}-settings.json"),
+ IOPath.Combine(
+ schemaDirectory,
+ schemaFileName + "-extensions" + IOPath.GetExtension(schemaPath)));
+ }
+
+ [SuppressMessage(
+ "Trimming",
+ "IL2026:Members attributed with RequiresUnreferencedCodeAttribute require dynamic access otherwise.")]
+ public static string GetProjectPath(IResource resource)
+ {
+ if (resource is not ProjectResource projectResource)
+ {
+ throw new InvalidOperationException(
+ $"GraphQL source resource '{resource.Name}' must be a project resource.");
+ }
+
+ return projectResource.GetProjectMetadata().ProjectPath;
+ }
+}
+
+internal readonly record struct GraphQLSourceSchemaResource(
+ IResourceWithEndpoints Resource,
+ GraphQLSourceSchemaAnnotation Declaration);
+
+internal readonly record struct GraphQLProjectSchemaPaths(
+ string ProjectPath,
+ string SchemaPath,
+ string SettingsPath,
+ string ExtensionsPath);
diff --git a/src/HotChocolate/Fusion/src/Fusion.Aspire/GraphQLSourceSchemaAnnotation.cs b/src/HotChocolate/Fusion/src/Fusion.Aspire/GraphQLSourceSchemaAnnotation.cs
index 1a42dd711ed..46be67d7a82 100644
--- a/src/HotChocolate/Fusion/src/Fusion.Aspire/GraphQLSourceSchemaAnnotation.cs
+++ b/src/HotChocolate/Fusion/src/Fusion.Aspire/GraphQLSourceSchemaAnnotation.cs
@@ -13,5 +13,15 @@ internal sealed class GraphQLSourceSchemaAnnotation : IResourceAnnotation
///
public string? SchemaPath { get; init; }
+ public string? ExportSchemaName { get; init; }
+
+ public string? ExportConfiguration { get; init; }
+
+ public string? ExportTargetFramework { get; init; }
+
+ public string? ExportRuntimeIdentifier { get; init; }
+
+ public TimeSpan? ExportTimeout { get; init; }
+
public required SourceSchemaLocationType Location { get; init; }
}
diff --git a/src/HotChocolate/Fusion/src/Fusion.Aspire/GraphQLSourceSchemaValidator.cs b/src/HotChocolate/Fusion/src/Fusion.Aspire/GraphQLSourceSchemaValidator.cs
new file mode 100644
index 00000000000..acb8f77cdc2
--- /dev/null
+++ b/src/HotChocolate/Fusion/src/Fusion.Aspire/GraphQLSourceSchemaValidator.cs
@@ -0,0 +1,45 @@
+using HotChocolate.Fusion.Logging;
+
+namespace HotChocolate.Fusion.Aspire;
+
+internal static class GraphQLSourceSchemaValidator
+{
+ public static void Validate(
+ string resourceName,
+ SchemaEndpointConfiguration configuration,
+ string sourceText,
+ string? extensionsSourceText = null)
+ {
+ ArgumentException.ThrowIfNullOrWhiteSpace(resourceName);
+
+ if (string.IsNullOrWhiteSpace(sourceText))
+ {
+ throw new InvalidOperationException(
+ $"Schema export for resource '{resourceName}' produced empty GraphQL SDL.");
+ }
+
+ if (extensionsSourceText is not null
+ && string.IsNullOrWhiteSpace(extensionsSourceText))
+ {
+ throw new InvalidOperationException(
+ $"Schema extensions for resource '{resourceName}' contain empty GraphQL SDL.");
+ }
+
+ var log = new CompositionLog();
+ var result = new SourceSchemaParser(
+ new SourceSchemaText(
+ configuration.SourceSchemaName,
+ sourceText,
+ extensionsSourceText),
+ log,
+ isApolloFederationV1:
+ configuration.ApolloFederationVersion is ApolloFederationVersion.Version1)
+ .Parse();
+
+ if (result.IsFailure)
+ {
+ throw new InvalidOperationException(
+ $"Schema for resource '{resourceName}' is not valid GraphQL SDL.");
+ }
+ }
+}
diff --git a/src/HotChocolate/Fusion/src/Fusion.Aspire/HotChocolate.Fusion.Aspire.csproj b/src/HotChocolate/Fusion/src/Fusion.Aspire/HotChocolate.Fusion.Aspire.csproj
index dad78802960..aa3681f56d8 100644
--- a/src/HotChocolate/Fusion/src/Fusion.Aspire/HotChocolate.Fusion.Aspire.csproj
+++ b/src/HotChocolate/Fusion/src/Fusion.Aspire/HotChocolate.Fusion.Aspire.csproj
@@ -9,6 +9,7 @@
+
@@ -20,6 +21,7 @@
+
diff --git a/src/HotChocolate/Fusion/src/Fusion.Aspire/SchemaComposition.cs b/src/HotChocolate/Fusion/src/Fusion.Aspire/SchemaComposition.cs
index 9f17fbfe569..8ba8a5f32a1 100644
--- a/src/HotChocolate/Fusion/src/Fusion.Aspire/SchemaComposition.cs
+++ b/src/HotChocolate/Fusion/src/Fusion.Aspire/SchemaComposition.cs
@@ -1,4 +1,3 @@
-using System.Diagnostics.CodeAnalysis;
using System.Text.Json;
using Aspire.Hosting;
using Aspire.Hosting.ApplicationModel;
@@ -133,8 +132,8 @@ private async Task> DiscoverReferencedSourceSchemasAsync(
{
var sourceSchemas = new List();
- // Get all resources referenced by the composition resource
- var referencedResources = GetReferencedResources(compositionResource, appModel);
+ var referencedResources =
+ GraphQLResourceModel.GetReferencedSourceSchemas(compositionResource, appModel);
logger.LogInformation(
"Found {Count} referenced resources for {ResourceName}",
@@ -142,17 +141,12 @@ private async Task> DiscoverReferencedSourceSchemasAsync(
try
{
- foreach (var referencedResource in referencedResources)
+ foreach (var referencedSource in referencedResources)
{
- if (!referencedResource.HasGraphQLSchema())
- {
- logger.LogDebug(
- "Resource {ResourceName} does not have a GraphQL schema, skipping",
- referencedResource.Name);
- continue;
- }
-
- var schemaInfo = await GetSourceSchemaInfoAsync(referencedResource, cancellationToken);
+ var schemaInfo = await GetSourceSchemaInfoAsync(
+ referencedSource.Resource,
+ referencedSource.Declaration,
+ cancellationToken);
if (schemaInfo is null)
{
continue;
@@ -179,51 +173,11 @@ private async Task> DiscoverReferencedSourceSchemasAsync(
return sourceSchemas;
}
- [SuppressMessage(
- "Trimming",
- "IL2075:\'this\' argument does not satisfy \'DynamicallyAccessedMembersAttribute\' "
- + "in call to target method. The return value of the source method does not have matching annotations.")]
- [SuppressMessage("ReSharper", "UnusedVariable")]
- private List GetReferencedResources(
- IResourceWithEndpoints compositionResource,
- DistributedApplicationModel appModel)
- {
- var referencedResourceNames = new HashSet();
-
- foreach (var annotation in compositionResource.Annotations)
- {
- switch (annotation)
- {
- case ResourceRelationshipAnnotation rel:
- referencedResourceNames.Add(rel.Resource.Name);
- break;
-
- case var endpointRef when annotation.GetType().Name == "EndpointReferenceAnnotation":
- var targetResourceProp = annotation.GetType().GetProperty("Resource");
- if (targetResourceProp?.GetValue(annotation) is IResource targetResource)
- {
- referencedResourceNames.Add(targetResource.Name);
- }
- break;
- }
- }
-
- return appModel.Resources
- .OfType()
- .Where(r => referencedResourceNames.Contains(r.Name))
- .ToList();
- }
-
private async Task GetSourceSchemaInfoAsync(
IResourceWithEndpoints resource,
+ GraphQLSourceSchemaAnnotation sourceSchemaSettings,
CancellationToken cancellationToken)
{
- var sourceSchemaSettings = resource.Annotations.OfType().FirstOrDefault();
- if (sourceSchemaSettings is null)
- {
- return null;
- }
-
switch (sourceSchemaSettings.Location)
{
case SourceSchemaLocationType.SchemaEndpoint:
@@ -235,6 +189,12 @@ private List GetReferencedResources(
case SourceSchemaLocationType.ProjectDirectory:
return await GetSourceSchemaFromFileAsync(resource, sourceSchemaSettings, cancellationToken);
+ case SourceSchemaLocationType.CommandLineExport:
+ return await GetSourceSchemaFromCommandLineAsync(
+ resource,
+ sourceSchemaSettings,
+ cancellationToken);
+
default:
logger.LogWarning(
"Unknown schema location type {LocationType} for {ResourceName}",
@@ -244,6 +204,86 @@ private List GetReferencedResources(
}
}
+ private async Task GetSourceSchemaFromCommandLineAsync(
+ IResourceWithEndpoints resource,
+ GraphQLSourceSchemaAnnotation annotation,
+ CancellationToken cancellationToken)
+ {
+ var outputDirectory = IOPath.Combine(
+ IOPath.GetTempPath(),
+ "hotchocolate-fusion-aspire",
+ Guid.NewGuid().ToString("N"));
+
+ try
+ {
+ var result = await CommandLineSchemaExporter.ExportAsync(
+ resource,
+ annotation,
+ outputDirectory,
+ cancellationToken);
+ var schemaText = await File.ReadAllTextAsync(
+ result.SchemaPath,
+ cancellationToken);
+ var settings = JsonDocument.Parse(
+ await File.ReadAllTextAsync(result.SettingsPath, cancellationToken));
+ var ownershipTransferred = false;
+
+ try
+ {
+ var configuration = ReadEndpointConfiguration(
+ resource.Name,
+ annotation.SourceSchemaName,
+ settings);
+ GraphQLSourceSchemaValidator.Validate(
+ resource.Name,
+ configuration,
+ schemaText);
+
+ var sourceSchema = new SourceSchemaInfo
+ {
+ Name = configuration.SourceSchemaName,
+ ResourceName = resource.Name,
+ Schema = new SourceSchemaText(configuration.SourceSchemaName, schemaText),
+ SchemaSettings = settings
+ };
+
+ ownershipTransferred = true;
+ return sourceSchema;
+ }
+ finally
+ {
+ if (!ownershipTransferred)
+ {
+ settings.Dispose();
+ }
+ }
+ }
+ finally
+ {
+ try
+ {
+ if (Directory.Exists(outputDirectory))
+ {
+ Directory.Delete(outputDirectory, recursive: true);
+ }
+ }
+ catch (IOException exception)
+ {
+ logger.LogWarning(
+ exception,
+ "Could not remove schema export directory for {ResourceName}.",
+ resource.Name);
+ }
+ catch (UnauthorizedAccessException exception)
+ {
+ logger.LogWarning(
+ exception,
+ "Could not remove schema export directory for {ResourceName}.",
+ resource.Name);
+ }
+ }
+ }
+
private async Task GetSourceSchemaFromEndpointAsync(
IResourceWithEndpoints resource,
GraphQLSourceSchemaAnnotation annotation,
@@ -286,6 +326,11 @@ private List GetReferencedResources(
return null;
}
+ GraphQLSourceSchemaValidator.Validate(
+ resource.Name,
+ endpointConfiguration,
+ schemaText);
+
var sourceSchema = new SourceSchemaInfo
{
Name = endpointConfiguration.SourceSchemaName,
@@ -363,9 +408,12 @@ internal static SchemaEndpointConfiguration ReadEndpointConfiguration(
GraphQLSourceSchemaAnnotation annotation,
CancellationToken cancellationToken)
{
- var sourceSchemaName = resource.GetGraphQLSourceSchemaName() ?? resource.Name;
+ var sourceSchemaName = annotation.SourceSchemaName ?? resource.Name;
- var schemaPath = annotation.SchemaPath ?? "schema.graphql";
+ var schemaPaths = GraphQLResourceModel.GetProjectSchemaPaths(
+ resource,
+ annotation);
+ var schemaPath = schemaPaths.SchemaPath;
if (IsExtensionsSchemaPath(schemaPath))
{
@@ -375,30 +423,60 @@ internal static SchemaEndpointConfiguration ReadEndpointConfiguration(
return null;
}
- var schemaFromFile = await ReadSchemaFromProjectDirectoryAsync(resource, schemaPath, cancellationToken);
+ var schemaFromFile = await ReadSchemaFromProjectDirectoryAsync(
+ resource,
+ schemaPath,
+ cancellationToken);
if (schemaFromFile is not { } schemaFiles)
{
return null;
}
- // For file schemas, settings file is named after the schema file
- // e.g., "foo.graphql" -> "foo-settings.json"
- var settingsFileName = $"{IOPath.GetFileNameWithoutExtension(schemaPath)}-settings.json";
-
- var schemaSettings = await GetSourceSchemaSettingsAsync(resource, settingsFileName, cancellationToken);
+ var schemaSettings = await GetSourceSchemaSettingsAsync(
+ resource,
+ schemaPaths.SettingsPath,
+ cancellationToken);
if (schemaSettings == null)
{
return null;
}
- return new SourceSchemaInfo
+ var ownershipTransferred = false;
+
+ try
{
- Name = sourceSchemaName,
- ResourceName = resource.Name,
- HttpEndpointUrl = null, // No HTTP endpoint for file-based schemas
- Schema = new SourceSchemaText(sourceSchemaName, schemaFiles.Schema, schemaFiles.Extensions),
- SchemaSettings = schemaSettings
- };
+ var configuration = ReadEndpointConfiguration(
+ resource.Name,
+ sourceSchemaName,
+ schemaSettings);
+ GraphQLSourceSchemaValidator.Validate(
+ resource.Name,
+ configuration,
+ schemaFiles.Schema,
+ schemaFiles.Extensions);
+
+ var sourceSchema = new SourceSchemaInfo
+ {
+ Name = configuration.SourceSchemaName,
+ ResourceName = resource.Name,
+ HttpEndpointUrl = null,
+ Schema = new SourceSchemaText(
+ configuration.SourceSchemaName,
+ schemaFiles.Schema,
+ schemaFiles.Extensions),
+ SchemaSettings = schemaSettings
+ };
+
+ ownershipTransferred = true;
+ return sourceSchema;
+ }
+ finally
+ {
+ if (!ownershipTransferred)
+ {
+ schemaSettings.Dispose();
+ }
+ }
}
private async Task GetSourceSchemaSettingsAsync(
@@ -416,7 +494,9 @@ internal static SchemaEndpointConfiguration ReadEndpointConfiguration(
}
var projectDirectory = IOPath.GetDirectoryName(projectPath);
- var settingsFile = IOPath.Combine(projectDirectory!, settingsFileName);
+ var settingsFile = IOPath.IsPathRooted(settingsFileName)
+ ? settingsFileName
+ : IOPath.Combine(projectDirectory!, settingsFileName);
if (!File.Exists(settingsFile))
{
@@ -556,7 +636,10 @@ internal static SchemaEndpointConfiguration ReadEndpointConfiguration(
}
var projectDirectory = IOPath.GetDirectoryName(projectPath);
- var schemaFile = IOPath.Combine(projectDirectory!, fileName ?? "schema.graphql");
+ var schemaPath = fileName ?? "schema.graphqls";
+ var schemaFile = IOPath.IsPathRooted(schemaPath)
+ ? schemaPath
+ : IOPath.Combine(projectDirectory!, schemaPath);
if (!File.Exists(schemaFile))
{
@@ -591,42 +674,19 @@ internal static SchemaEndpointConfiguration ReadEndpointConfiguration(
}
}
- [SuppressMessage(
- "Trimming",
- "IL2075:\'this\' argument does not satisfy \'DynamicallyAccessedMembersAttribute\' "
- + "in call to target method. The return value of the source method does not have matching annotations.")]
private string? GetProjectPath(IResourceWithEndpoints resource)
{
- // Check if this is a ProjectResource
- if (resource is not ProjectResource projectResource)
+ try
{
- return null;
+ return GraphQLResourceModel.GetProjectPath(resource);
}
-
- // Get the project metadata from the ProjectResource
- // The metadata is typically stored as an annotation or property
- var metadataAnnotation = projectResource.Annotations
- .FirstOrDefault(a => a.GetType().GetInterfaces().Contains(typeof(IProjectMetadata)));
-
- if (metadataAnnotation is IProjectMetadata projectMetadata)
+ catch (InvalidOperationException)
{
- return projectMetadata.ProjectPath;
- }
-
- // Alternative approach: look for the metadata in the resource's type or properties
- // Sometimes the metadata might be accessible through reflection on the resource itself
- var metadataProperty = projectResource.GetType()
- .GetProperties()
- .FirstOrDefault(p => p.PropertyType.GetInterfaces().Contains(typeof(IProjectMetadata)));
-
- if (metadataProperty != null)
- {
- var metadata = metadataProperty.GetValue(projectResource) as IProjectMetadata;
- return metadata?.ProjectPath;
+ logger.LogWarning(
+ "Could not find project metadata for resource {ResourceName}",
+ resource.Name);
+ return null;
}
-
- logger.LogWarning("Could not find project metadata for resource {ResourceName}", resource.Name);
- return null;
}
private async Task ComposeSchemaAsync(
diff --git a/src/HotChocolate/Fusion/src/Fusion.Aspire/SourceSchemaLocationType.cs b/src/HotChocolate/Fusion/src/Fusion.Aspire/SourceSchemaLocationType.cs
index 2a2ba82cdf0..3251baff00e 100644
--- a/src/HotChocolate/Fusion/src/Fusion.Aspire/SourceSchemaLocationType.cs
+++ b/src/HotChocolate/Fusion/src/Fusion.Aspire/SourceSchemaLocationType.cs
@@ -3,5 +3,6 @@ namespace HotChocolate.Fusion.Aspire;
internal enum SourceSchemaLocationType
{
ProjectDirectory,
- SchemaEndpoint
+ SchemaEndpoint,
+ CommandLineExport
}
diff --git a/src/HotChocolate/Fusion/test/Fusion.Aspire.Tests/CommandLineSchemaExporterTests.cs b/src/HotChocolate/Fusion/test/Fusion.Aspire.Tests/CommandLineSchemaExporterTests.cs
new file mode 100644
index 00000000000..b3f90857b69
--- /dev/null
+++ b/src/HotChocolate/Fusion/test/Fusion.Aspire.Tests/CommandLineSchemaExporterTests.cs
@@ -0,0 +1,337 @@
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
+
+namespace HotChocolate.Fusion.Aspire;
+
+public sealed class CommandLineSchemaExporterTests
+{
+ [Fact]
+ public void CreateStartInfo_Should_UseExplicitArgumentSafeBuildInputs()
+ {
+ var projectPath = GetTestProjectFile();
+ var schemaPath = System.IO.Path.Combine(
+ System.IO.Path.GetTempPath(),
+ "schema export",
+ "schema.graphqls");
+
+ var startInfo = CommandLineSchemaExporter.CreateStartInfo(
+ projectPath,
+ schemaPath,
+ "Products Schema",
+ "Release",
+ "net9.0",
+ "linux-x64");
+
+ string.Join(Environment.NewLine, startInfo.ArgumentList).MatchInlineSnapshot(
+ $$"""
+ run
+ --project
+ {{projectPath}}
+ --configuration
+ Release
+ --framework
+ net9.0
+ --runtime
+ linux-x64
+ --no-launch-profile
+ --
+ schema
+ export
+ --output
+ {{schemaPath}}
+ --schema-name
+ Products Schema
+ """);
+ }
+
+ [Fact]
+ public void CreateStartInfo_Should_OmitRuntimeArgument_When_ExportIsExplicitlyPortable()
+ {
+ var startInfo = CommandLineSchemaExporter.CreateStartInfo(
+ GetTestProjectFile(),
+ System.IO.Path.Combine(System.IO.Path.GetTempPath(), "schema.graphqls"),
+ "Products",
+ "Release",
+ "net9.0",
+ runtimeIdentifier: null);
+
+ Assert.Equal(
+ [
+ "run",
+ "--project",
+ GetTestProjectFile(),
+ "--configuration",
+ "Release",
+ "--framework",
+ "net9.0",
+ "--no-launch-profile",
+ "--",
+ "schema",
+ "export",
+ "--output",
+ System.IO.Path.Combine(System.IO.Path.GetTempPath(), "schema.graphqls"),
+ "--schema-name",
+ "Products"
+ ],
+ startInfo.ArgumentList);
+ }
+
+ [Fact]
+ public void ApplyEnvironmentAllowList_Should_RemoveSecretsAndKeepOsBootstrapVariables()
+ {
+ var startInfo = new ProcessStartInfo();
+ startInfo.Environment.Clear();
+ startInfo.Environment["PATH"] = "dotnet-path";
+ startInfo.Environment["DOTNET_ROOT"] = "dotnet-root";
+ startInfo.Environment["NUGET_PACKAGES"] = "packages";
+ startInfo.Environment["NITRO_API_KEY"] = "secret";
+
+ if (OperatingSystem.IsWindows())
+ {
+ startInfo.Environment["SystemRoot"] = "system-root";
+ startInfo.Environment["USERPROFILE"] = "user-profile";
+ }
+ else
+ {
+ startInfo.Environment["HOME"] = "user-home";
+ startInfo.Environment["path"] = "wrong-case-path";
+ }
+
+ CommandLineSchemaExporter.ApplyEnvironmentAllowList(startInfo);
+
+ var expected = OperatingSystem.IsWindows()
+ ? new Dictionary
+ {
+ ["DOTNET_CLI_TELEMETRY_OPTOUT"] = "1",
+ ["DOTNET_NOLOGO"] = "1",
+ ["DOTNET_ROOT"] = "dotnet-root",
+ ["NUGET_PACKAGES"] = "packages",
+ ["PATH"] = "dotnet-path",
+ ["SystemRoot"] = "system-root",
+ ["USERPROFILE"] = "user-profile"
+ }
+ : new Dictionary
+ {
+ ["DOTNET_CLI_TELEMETRY_OPTOUT"] = "1",
+ ["DOTNET_NOLOGO"] = "1",
+ ["DOTNET_ROOT"] = "dotnet-root",
+ ["HOME"] = "user-home",
+ ["NUGET_PACKAGES"] = "packages",
+ ["PATH"] = "dotnet-path"
+ };
+
+ Assert.Equal(
+ expected.OrderBy(t => t.Key),
+ startInfo.Environment.OrderBy(t => t.Key));
+ }
+
+ [Fact]
+ public async Task RunProcessAsync_Should_DrainPipesAndBoundRetainedOutput_When_OutputIsLarge()
+ {
+ var startInfo = CreateLargeOutputProcess();
+
+ var result = await CommandLineSchemaExporter.RunProcessAsync(
+ startInfo,
+ TimeSpan.FromSeconds(30),
+ "products",
+ TestContext.Current.CancellationToken);
+
+ $$"""
+ Exit code: {{result.ExitCode}}
+ Standard output length: {{result.StandardOutput.Length}}
+ Standard output truncated: {{result.StandardOutputWasTruncated}}
+ Standard error characters: {{result.StandardErrorCharacterCount > 32 * 1024}}
+ Secret retained: {{result.ToString().Contains("stderr-secret", StringComparison.Ordinal)}}
+ """.MatchInlineSnapshot(
+ """
+ Exit code: 7
+ Standard output length: 32768
+ Standard output truncated: True
+ Standard error characters: True
+ Secret retained: False
+ """);
+ }
+
+ [Fact]
+ public async Task RunProcessAsync_Should_KillProcessTreeAndPreserveToken_When_Canceled()
+ {
+ var startInfo = CreateLongRunningProcess();
+ using var cancellation = new CancellationTokenSource(TimeSpan.FromMilliseconds(500));
+ var timer = Stopwatch.StartNew();
+
+ var exception = await Assert.ThrowsAnyAsync(
+ () => CommandLineSchemaExporter.RunProcessAsync(
+ startInfo,
+ TimeSpan.FromMinutes(1),
+ "products",
+ cancellation.Token));
+
+ Assert.Equal(cancellation.Token, exception.CancellationToken);
+ Assert.True(
+ timer.Elapsed < TimeSpan.FromSeconds(10),
+ $"Cancellation cleanup took {timer.Elapsed}.");
+ }
+
+ [Fact]
+ public async Task ValidateArtifactsAsync_Should_AcceptExactNameAndValidSchema()
+ {
+ using var directory = new TemporaryDirectory();
+ var schemaPath = directory.WriteFile(
+ "schema.graphqls",
+ "type Query { product: String }");
+ var settingsPath = directory.WriteFile(
+ "schema-settings.json",
+ """{ "name": "Products" }""");
+
+ await CommandLineSchemaExporter.ValidateArtifactsAsync(
+ "products",
+ "Products",
+ schemaPath,
+ settingsPath,
+ TestContext.Current.CancellationToken);
+ }
+
+ [Fact]
+ public async Task ValidateArtifactsAsync_Should_RejectNameMismatch()
+ {
+ using var directory = new TemporaryDirectory();
+ var schemaPath = directory.WriteFile(
+ "schema.graphqls",
+ "type Query { product: String }");
+ var settingsPath = directory.WriteFile(
+ "schema-settings.json",
+ """{ "name": "Inventory" }""");
+
+ var exception = await Assert.ThrowsAsync(
+ () => CommandLineSchemaExporter.ValidateArtifactsAsync(
+ "products",
+ "Products",
+ schemaPath,
+ settingsPath,
+ TestContext.Current.CancellationToken));
+
+ Assert.Equal(
+ "The configured source schema name 'Products' for resource 'products' "
+ + "does not match schema-settings.json name 'Inventory'.",
+ exception.Message);
+ }
+
+ [Theory]
+ [InlineData(" ", "Schema export for resource 'products' produced empty GraphQL SDL.")]
+ [InlineData(
+ "type Query {",
+ "Schema for resource 'products' is not valid GraphQL SDL.")]
+ public async Task ValidateArtifactsAsync_Should_RejectInvalidSchema(
+ string schema,
+ string expectedMessage)
+ {
+ using var directory = new TemporaryDirectory();
+ var schemaPath = directory.WriteFile("schema.graphqls", schema);
+ var settingsPath = directory.WriteFile(
+ "schema-settings.json",
+ """{ "name": "Products" }""");
+
+ var exception = await Assert.ThrowsAsync(
+ () => CommandLineSchemaExporter.ValidateArtifactsAsync(
+ "products",
+ "Products",
+ schemaPath,
+ settingsPath,
+ TestContext.Current.CancellationToken));
+
+ Assert.Equal(expectedMessage, exception.Message);
+ }
+
+ private static ProcessStartInfo CreateLargeOutputProcess()
+ {
+ if (OperatingSystem.IsWindows())
+ {
+ return CreateProcess(
+ "cmd.exe",
+ "/D",
+ "/S",
+ "/C",
+ "(for /L %i in (1,1,4000) do @echo 01234567890123456789)"
+ + "&(for /L %i in (1,1,4000) do @echo stderr-secret-0123456789 1>&2)"
+ + "&exit /b 7");
+ }
+
+ return CreateProcess(
+ "/bin/sh",
+ "-c",
+ "i=0; while [ $i -lt 4000 ]; do "
+ + "printf '01234567890123456789\\n'; "
+ + "printf 'stderr-secret-0123456789\\n' >&2; "
+ + "i=$((i + 1)); done; exit 7");
+ }
+
+ private static ProcessStartInfo CreateLongRunningProcess()
+ {
+ if (OperatingSystem.IsWindows())
+ {
+ return CreateProcess(
+ "cmd.exe",
+ "/D",
+ "/S",
+ "/C",
+ "ping -t 127.0.0.1 >nul");
+ }
+
+ return CreateProcess(
+ "/bin/sh",
+ "-c",
+ "while true; do sleep 1; done");
+ }
+
+ private static ProcessStartInfo CreateProcess(
+ string fileName,
+ params string[] arguments)
+ {
+ var startInfo = new ProcessStartInfo
+ {
+ FileName = fileName,
+ RedirectStandardOutput = true,
+ RedirectStandardError = true,
+ UseShellExecute = false,
+ CreateNoWindow = true
+ };
+
+ foreach (var argument in arguments)
+ {
+ startInfo.ArgumentList.Add(argument);
+ }
+
+ return startInfo;
+ }
+
+ private static string GetTestProjectFile([CallerFilePath] string sourceFile = "")
+ => System.IO.Path.GetFullPath(
+ System.IO.Path.Combine(
+ System.IO.Path.GetDirectoryName(sourceFile)!,
+ "HotChocolate.Fusion.Aspire.Tests.csproj"));
+
+ private sealed class TemporaryDirectory : IDisposable
+ {
+ private readonly string _path = System.IO.Path.Combine(
+ System.IO.Path.GetTempPath(),
+ "fusion-aspire-tests",
+ Guid.NewGuid().ToString("N"));
+
+ public TemporaryDirectory()
+ {
+ Directory.CreateDirectory(_path);
+ }
+
+ public string WriteFile(string fileName, string content)
+ {
+ var path = System.IO.Path.Combine(_path, fileName);
+ File.WriteAllText(path, content);
+ return path;
+ }
+
+ public void Dispose()
+ {
+ Directory.Delete(_path, recursive: true);
+ }
+ }
+}
diff --git a/src/HotChocolate/Fusion/test/Fusion.Aspire.Tests/GraphQLResourceBuilderExtensionsTests.cs b/src/HotChocolate/Fusion/test/Fusion.Aspire.Tests/GraphQLResourceBuilderExtensionsTests.cs
index 34896663e9a..de243372373 100644
--- a/src/HotChocolate/Fusion/test/Fusion.Aspire.Tests/GraphQLResourceBuilderExtensionsTests.cs
+++ b/src/HotChocolate/Fusion/test/Fusion.Aspire.Tests/GraphQLResourceBuilderExtensionsTests.cs
@@ -50,6 +50,62 @@ public void WithGraphQLSchemaEndpoint_Should_RejectPath_When_PathIsNotRooted()
exception.Message);
}
+ [Fact]
+ public void WithGraphQLSchemaExport_Should_PreserveExplicitBuildInputs()
+ {
+ var builder = DistributedApplication.CreateBuilder();
+ var resource = builder
+ .AddProject("products", GetTestProjectFile())
+ .WithGraphQLSchemaExport(
+ "Products",
+ "Release",
+ "net9.0",
+ "linux-x64",
+ TimeSpan.FromMinutes(2));
+
+ var annotation = Assert.Single(
+ resource.Resource.Annotations.OfType());
+
+ $$"""
+ Source schema name: {{annotation.SourceSchemaName}}
+ Export schema name: {{annotation.ExportSchemaName}}
+ Configuration: {{annotation.ExportConfiguration}}
+ Target framework: {{annotation.ExportTargetFramework}}
+ Runtime identifier: {{annotation.ExportRuntimeIdentifier}}
+ Timeout: {{annotation.ExportTimeout}}
+ Location: {{annotation.Location}}
+ """.MatchInlineSnapshot(
+ """
+ Source schema name: Products
+ Export schema name: Products
+ Configuration: Release
+ Target framework: net9.0
+ Runtime identifier: linux-x64
+ Timeout: 00:02:00
+ Location: CommandLineExport
+ """);
+ }
+
+ [Fact]
+ public void WithGraphQLSchemaExport_Should_RejectWhitespaceRuntimeIdentifier()
+ {
+ var builder = DistributedApplication.CreateBuilder();
+ var resource = builder.AddProject("products", GetTestProjectFile());
+
+ var exception = Assert.Throws(
+ () => resource.WithGraphQLSchemaExport(
+ "Products",
+ "Release",
+ "net9.0",
+ " ",
+ TimeSpan.FromMinutes(2)));
+
+ Assert.Equal(
+ "The value cannot be an empty string or composed entirely of whitespace. "
+ + "(Parameter 'runtimeIdentifier')",
+ exception.Message);
+ }
+
[Theory]
[InlineData(
null,
diff --git a/src/HotChocolate/Fusion/test/Fusion.Aspire.Tests/GraphQLResourceModelTests.cs b/src/HotChocolate/Fusion/test/Fusion.Aspire.Tests/GraphQLResourceModelTests.cs
new file mode 100644
index 00000000000..baf66123cad
--- /dev/null
+++ b/src/HotChocolate/Fusion/test/Fusion.Aspire.Tests/GraphQLResourceModelTests.cs
@@ -0,0 +1,121 @@
+using System.Runtime.CompilerServices;
+using Aspire.Hosting;
+using Aspire.Hosting.ApplicationModel;
+
+namespace HotChocolate.Fusion.Aspire;
+
+public sealed class GraphQLResourceModelTests
+{
+ [Fact]
+ public void GetReferencedSourceSchemas_Should_ReturnSharedResourceAndDeclaration()
+ {
+ var builder = DistributedApplication.CreateBuilder();
+ var products = builder
+ .AddProject("products", GetTestProjectFile())
+ .WithGraphQLSchemaExport(
+ "Products",
+ "Release",
+ "net9.0",
+ runtimeIdentifier: null,
+ TimeSpan.FromMinutes(1));
+ var unrelated = builder
+ .AddProject("unrelated", GetTestProjectFile())
+ .WithGraphQLSchemaFile();
+ var unreferenced = builder
+ .AddProject("unreferenced", GetTestProjectFile())
+ .WithGraphQLSchemaFile();
+ var gateway = builder
+ .AddProject("gateway", GetTestProjectFile())
+ .WithReference(products)
+ .WithReference(unrelated)
+ .WithGraphQLSchemaComposition();
+ var model = new DistributedApplicationModel(
+ [
+ products.Resource,
+ unrelated.Resource,
+ unreferenced.Resource,
+ gateway.Resource
+ ]);
+
+ var sources = GraphQLResourceModel.GetReferencedSourceSchemas(
+ gateway.Resource,
+ model);
+
+ Assert.Collection(
+ sources,
+ source =>
+ {
+ Assert.Same(products.Resource, source.Resource);
+ Assert.Same(
+ GraphQLResourceModel.GetSourceSchema(products.Resource),
+ source.Declaration);
+ },
+ source =>
+ {
+ Assert.Same(unrelated.Resource, source.Resource);
+ Assert.Same(
+ GraphQLResourceModel.GetSourceSchema(unrelated.Resource),
+ source.Declaration);
+ });
+ }
+
+ [Fact]
+ public void GetReferencedSourceSchemas_Should_FailClosed_When_DeclarationIsAmbiguous()
+ {
+ var builder = DistributedApplication.CreateBuilder();
+ var products = builder
+ .AddProject("products", GetTestProjectFile())
+ .WithGraphQLSchemaFile();
+ products.Resource.Annotations.Add(
+ new GraphQLSourceSchemaAnnotation
+ {
+ Location = SourceSchemaLocationType.SchemaEndpoint
+ });
+ var gateway = builder
+ .AddProject("gateway", GetTestProjectFile())
+ .WithReference(products)
+ .WithGraphQLSchemaComposition();
+ var model = new DistributedApplicationModel(
+ [products.Resource, gateway.Resource]);
+
+ Assert.Throws(
+ () => GraphQLResourceModel.GetReferencedSourceSchemas(
+ gateway.Resource,
+ model));
+ }
+
+ [Fact]
+ public void GetProjectSchemaPaths_Should_ResolveSettingsBesideNestedSchema()
+ {
+ var builder = DistributedApplication.CreateBuilder();
+ var products = builder
+ .AddProject("products", GetTestProjectFile())
+ .WithGraphQLSchemaFile(
+ System.IO.Path.Combine("schemas", "products.graphqls"),
+ "Products");
+ var declaration = GraphQLResourceModel.GetSourceSchema(products.Resource);
+
+ var paths = GraphQLResourceModel.GetProjectSchemaPaths(
+ products.Resource,
+ declaration);
+
+ var projectDirectory = System.IO.Path.GetDirectoryName(GetTestProjectFile())!;
+ $$"""
+ Project: {{System.IO.Path.GetRelativePath(projectDirectory, paths.ProjectPath)}}
+ Schema: {{System.IO.Path.GetRelativePath(projectDirectory, paths.SchemaPath)}}
+ Settings: {{System.IO.Path.GetRelativePath(projectDirectory, paths.SettingsPath)}}
+ Extensions: {{System.IO.Path.GetRelativePath(projectDirectory, paths.ExtensionsPath)}}
+ """.MatchInlineSnapshot(
+ """
+ Project: HotChocolate.Fusion.Aspire.Tests.csproj
+ Schema: schemas/products.graphqls
+ Settings: schemas/products-settings.json
+ Extensions: schemas/products-extensions.graphqls
+ """);
+ }
+
+ private static string GetTestProjectFile([CallerFilePath] string sourceFile = "")
+ => System.IO.Path.Combine(
+ System.IO.Path.GetDirectoryName(sourceFile)!,
+ "HotChocolate.Fusion.Aspire.Tests.csproj");
+}
diff --git a/src/Nitro/Common/src/ChilliCream.Nitro.Aspire/ChilliCream.Nitro.Aspire.csproj b/src/Nitro/Common/src/ChilliCream.Nitro.Aspire/ChilliCream.Nitro.Aspire.csproj
new file mode 100644
index 00000000000..c0b287ddcc2
--- /dev/null
+++ b/src/Nitro/Common/src/ChilliCream.Nitro.Aspire/ChilliCream.Nitro.Aspire.csproj
@@ -0,0 +1,32 @@
+
+
+
+ ChilliCream.Nitro.Aspire
+ ChilliCream.Nitro.Aspire
+ net11.0;net10.0;net9.0
+ false
+ Integrates deterministic Hot Chocolate Fusion publication workflows with .NET Aspire deployment pipelines.
+ README.md
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Nitro/Common/src/ChilliCream.Nitro.Aspire/FusionDeploymentResource.cs b/src/Nitro/Common/src/ChilliCream.Nitro.Aspire/FusionDeploymentResource.cs
new file mode 100644
index 00000000000..8527f9d0b37
--- /dev/null
+++ b/src/Nitro/Common/src/ChilliCream.Nitro.Aspire/FusionDeploymentResource.cs
@@ -0,0 +1,32 @@
+using Aspire.Hosting.ApplicationModel;
+
+namespace ChilliCream.Nitro.Aspire;
+
+///
+/// Represents an environment-specific Fusion deployment to Nitro.
+///
+public sealed class FusionDeploymentResource(
+ string name,
+ NitroResource nitro)
+ : Resource(name)
+{
+ internal NitroResource Nitro { get; } = nitro;
+
+ internal string? EnvironmentName { get; set; }
+
+ internal string? StageName { get; set; }
+
+ internal string? ConfigurationTag { get; set; }
+
+ internal ParameterResource? ConfigurationTagParameter { get; set; }
+
+ internal bool UseGitCommitAsSourceVersion { get; set; }
+
+ internal bool WaitForApproval { get; set; }
+
+ internal bool Force { get; set; }
+
+ internal TimeSpan OperationTimeout { get; set; } = TimeSpan.FromMinutes(15);
+
+ internal TimeSpan ApprovalTimeout { get; set; } = TimeSpan.FromHours(2);
+}
diff --git a/src/Nitro/Common/src/ChilliCream.Nitro.Aspire/FusionPipeline.cs b/src/Nitro/Common/src/ChilliCream.Nitro.Aspire/FusionPipeline.cs
new file mode 100644
index 00000000000..028d46d681b
--- /dev/null
+++ b/src/Nitro/Common/src/ChilliCream.Nitro.Aspire/FusionPipeline.cs
@@ -0,0 +1,283 @@
+using Aspire.Hosting;
+using Aspire.Hosting.ApplicationModel;
+using Aspire.Hosting.Pipelines;
+using HotChocolate.Fusion.Aspire;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+
+namespace ChilliCream.Nitro.Aspire;
+
+#pragma warning disable ASPIREPIPELINES001
+
+internal static class FusionPipeline
+{
+ internal const string ArtifactsStepName = "fusion-artifacts";
+ internal const string ReadinessStepName = "fusion-readiness";
+ internal const string UploadStepName = "fusion-upload";
+ internal const string PublishStepName = "fusion-publish";
+
+ public static void Configure(
+ IResourceBuilder pipeline)
+ {
+ var topology = new FusionPipelineTopology();
+
+ pipeline.WithPipelineStepFactory(
+ context => CreateSteps(context, topology));
+ pipeline.WithPipelineConfiguration(
+ context => ConfigureSteps(context, topology));
+ }
+
+ internal static IReadOnlyList SelectDeployments(
+ DistributedApplicationModel model,
+ string environmentName)
+ {
+ var deployments = model.Resources
+ .OfType()
+ .Where(deployment =>
+ string.Equals(
+ deployment.EnvironmentName,
+ environmentName,
+ StringComparison.Ordinal))
+ .ToArray();
+
+ foreach (var deployment in deployments)
+ {
+ ValidateDeclaration(deployment);
+ }
+
+ var duplicate = deployments
+ .GroupBy(
+ deployment => (
+ deployment.Nitro.CloudUrl,
+ deployment.Nitro.ApiId,
+ deployment.StageName),
+ FusionDeploymentKeyComparer.Instance)
+ .FirstOrDefault(group => group.Count() > 1);
+
+ if (duplicate is not null)
+ {
+ throw new InvalidOperationException(
+ $"Multiple Fusion deployments map environment '{environmentName}' to Nitro "
+ + $"API '{duplicate.Key.ApiId}' stage '{duplicate.Key.StageName}'.");
+ }
+
+ return deployments;
+ }
+
+ internal static IResourceWithEndpoints GetCompositionResource(
+ DistributedApplicationModel model)
+ {
+ var compositions = model.GetGraphQLCompositionResources().ToArray();
+ return compositions.Length switch
+ {
+ 1 => compositions[0],
+ 0 => throw new InvalidOperationException(
+ "A Fusion deployment requires one resource with GraphQL schema composition."),
+ _ => throw new InvalidOperationException(
+ "A Fusion deployment requires exactly one resource with GraphQL schema composition.")
+ };
+ }
+
+ private static IEnumerable CreateSteps(
+ PipelineStepFactoryContext context,
+ FusionPipelineTopology topology)
+ {
+ var environment = context.PipelineContext.Services
+ .GetRequiredService()
+ .EnvironmentName;
+ var deployments = SelectDeployments(
+ context.PipelineContext.Model,
+ environment);
+
+ topology.EnvironmentName = environment;
+ topology.HasDeployments = deployments.Count > 0;
+
+ return CreateStepDefinitions(context.Resource, topology);
+ }
+
+ internal static PipelineStep[] CreateStepDefinitionsForTest(
+ IResource resource)
+ => CreateStepDefinitions(resource, new FusionPipelineTopology());
+
+ private static PipelineStep[] CreateStepDefinitions(
+ IResource resource,
+ FusionPipelineTopology topology)
+ =>
+ [
+ new PipelineStep
+ {
+ Name = ArtifactsStepName,
+ Description = "Produce portable Fusion deployment artifacts.",
+ Resource = resource,
+ RequiredBySteps = [WellKnownPipelineSteps.Publish],
+ Action = ExecuteArtifactsAsync
+ },
+ new PipelineStep
+ {
+ Name = ReadinessStepName,
+ Description = "Verify deployed Fusion source services are ready.",
+ Resource = resource,
+ DependsOnSteps = [ArtifactsStepName],
+ Action = stepContext => ExecuteReadinessAsync(stepContext, topology)
+ },
+ new PipelineStep
+ {
+ Name = UploadStepName,
+ Description = "Reconcile immutable Fusion source schema versions.",
+ Resource = resource,
+ DependsOnSteps = [ArtifactsStepName],
+ Action = ExecuteUploadAsync
+ },
+ new PipelineStep
+ {
+ Name = PublishStepName,
+ Description = "Compose and publish the Fusion configuration to Nitro.",
+ Resource = resource,
+ DependsOnSteps = [UploadStepName, ReadinessStepName],
+ RequiredBySteps = [WellKnownPipelineSteps.Deploy],
+ Action = ExecutePublishAsync
+ }
+ ];
+
+ private static void ConfigureSteps(
+ PipelineConfigurationContext context,
+ FusionPipelineTopology topology)
+ {
+ if (!topology.HasDeployments)
+ {
+ return;
+ }
+
+ var composition = GetCompositionResource(context.Model);
+ var sources = GraphQLResourceModel.GetReferencedSourceSchemas(
+ composition,
+ context.Model);
+ var readiness = context.Steps.Single(
+ step => step.Name == ReadinessStepName);
+
+ topology.SourcesWithoutCompute.Clear();
+
+ foreach (var source in sources)
+ {
+ var computeSteps = context
+ .GetSteps(source.Resource, WellKnownPipelineTags.DeployCompute)
+ .ToArray();
+
+ if (computeSteps.Length == 0)
+ {
+ topology.SourcesWithoutCompute.Add(source.Resource.Name);
+ continue;
+ }
+
+ foreach (var computeStep in computeSteps)
+ {
+ readiness.DependsOn(computeStep);
+ }
+ }
+ }
+
+ private static Task ExecuteArtifactsAsync(PipelineStepContext context)
+ => GetExecutor(context).CreateArtifactsAsync(context);
+
+ private static Task ExecuteReadinessAsync(
+ PipelineStepContext context,
+ FusionPipelineTopology topology)
+ {
+ if (topology.SourcesWithoutCompute.Count > 0)
+ {
+ throw new InvalidOperationException(
+ "Fusion publication cannot prove compute deployment ordering for resources: "
+ + string.Join(", ", topology.SourcesWithoutCompute.Order()));
+ }
+
+ return GetExecutor(context).VerifyReadinessAsync(context);
+ }
+
+ private static Task ExecuteUploadAsync(PipelineStepContext context)
+ => GetExecutor(context).UploadAsync(context);
+
+ private static Task ExecutePublishAsync(PipelineStepContext context)
+ => GetExecutor(context).PublishAsync(context);
+
+ private static IFusionPipelineExecutor GetExecutor(
+ PipelineStepContext context)
+ => context.Services.GetService()
+ ?? FusionPipelineExecutor.Instance;
+
+ private static void ValidateDeclaration(
+ FusionDeploymentResource deployment)
+ {
+ if (string.IsNullOrWhiteSpace(deployment.EnvironmentName))
+ {
+ throw new InvalidOperationException(
+ $"Fusion deployment '{deployment.Name}' must select an Aspire environment.");
+ }
+
+ if (string.IsNullOrWhiteSpace(deployment.StageName))
+ {
+ throw new InvalidOperationException(
+ $"Fusion deployment '{deployment.Name}' must select a Nitro stage.");
+ }
+
+ if (string.IsNullOrWhiteSpace(deployment.Nitro.CloudUrl))
+ {
+ throw new InvalidOperationException(
+ $"Nitro target '{deployment.Nitro.Name}' must specify a cloud URL.");
+ }
+
+ if (!Uri.TryCreate(
+ deployment.Nitro.CloudUrl,
+ UriKind.Absolute,
+ out var cloudUri)
+ || cloudUri.Scheme is not "https")
+ {
+ throw new InvalidOperationException(
+ $"Nitro target '{deployment.Nitro.Name}' cloud URL must use HTTPS.");
+ }
+
+ if (string.IsNullOrWhiteSpace(deployment.Nitro.ApiId))
+ {
+ throw new InvalidOperationException(
+ $"Nitro target '{deployment.Nitro.Name}' must specify an API ID.");
+ }
+
+ if (deployment.ConfigurationTagParameter is null
+ && string.IsNullOrWhiteSpace(deployment.ConfigurationTag))
+ {
+ throw new InvalidOperationException(
+ $"Fusion deployment '{deployment.Name}' must specify a configuration tag.");
+ }
+ }
+
+ private sealed class FusionPipelineTopology
+ {
+ public string? EnvironmentName { get; set; }
+
+ public bool HasDeployments { get; set; }
+
+ public HashSet SourcesWithoutCompute { get; } =
+ new(StringComparer.Ordinal);
+ }
+
+ private sealed class FusionDeploymentKeyComparer
+ : IEqualityComparer<(string? CloudUrl, string? ApiId, string? StageName)>
+ {
+ public static FusionDeploymentKeyComparer Instance { get; } = new();
+
+ public bool Equals(
+ (string? CloudUrl, string? ApiId, string? StageName) x,
+ (string? CloudUrl, string? ApiId, string? StageName) y)
+ => string.Equals(x.CloudUrl, y.CloudUrl, StringComparison.OrdinalIgnoreCase)
+ && string.Equals(x.ApiId, y.ApiId, StringComparison.Ordinal)
+ && string.Equals(x.StageName, y.StageName, StringComparison.Ordinal);
+
+ public int GetHashCode(
+ (string? CloudUrl, string? ApiId, string? StageName) obj)
+ => HashCode.Combine(
+ StringComparer.OrdinalIgnoreCase.GetHashCode(obj.CloudUrl ?? ""),
+ StringComparer.Ordinal.GetHashCode(obj.ApiId ?? ""),
+ StringComparer.Ordinal.GetHashCode(obj.StageName ?? ""));
+ }
+}
+
+#pragma warning restore ASPIREPIPELINES001
diff --git a/src/Nitro/Common/src/ChilliCream.Nitro.Aspire/FusionPipelineExecutor.cs b/src/Nitro/Common/src/ChilliCream.Nitro.Aspire/FusionPipelineExecutor.cs
new file mode 100644
index 00000000000..759015a5160
--- /dev/null
+++ b/src/Nitro/Common/src/ChilliCream.Nitro.Aspire/FusionPipelineExecutor.cs
@@ -0,0 +1,930 @@
+using System.Diagnostics;
+using System.Net;
+using System.Security.Cryptography;
+using System.Text.Json;
+using Aspire.Hosting.ApplicationModel;
+using Aspire.Hosting.Pipelines;
+using ChilliCream.Nitro.Fusion;
+using HotChocolate.Fusion.Aspire;
+using HotChocolate.Fusion.SourceSchema.Packaging;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.Hosting;
+using Microsoft.Extensions.Logging;
+
+namespace ChilliCream.Nitro.Aspire;
+
+#pragma warning disable ASPIREPIPELINES001
+#pragma warning disable ASPIREPIPELINES004
+
+internal sealed class FusionPipelineExecutor : IFusionPipelineExecutor
+{
+ public static FusionPipelineExecutor Instance { get; } = new();
+
+ public async Task CreateArtifactsAsync(PipelineStepContext context)
+ {
+ var environment = context.Services
+ .GetRequiredService()
+ .EnvironmentName;
+ var deployments = FusionPipeline.SelectDeployments(
+ context.Model,
+ environment);
+
+ if (deployments.Count == 0)
+ {
+ return;
+ }
+
+ var composition = FusionPipeline.GetCompositionResource(context.Model);
+ var sources = GraphQLResourceModel.GetReferencedSourceSchemas(
+ composition,
+ context.Model);
+
+ if (sources.Count == 0)
+ {
+ throw new InvalidOperationException(
+ $"Fusion composition resource '{composition.Name}' has no declared source schemas.");
+ }
+
+ var output = context.Services
+ .GetRequiredService()
+ .GetOutputDirectory();
+
+ foreach (var deployment in deployments)
+ {
+ await CreateDeploymentArtifactsAsync(
+ deployment,
+ sources,
+ output,
+ context.CancellationToken);
+ }
+ }
+
+ public async Task VerifyReadinessAsync(PipelineStepContext context)
+ {
+ var environment = context.Services
+ .GetRequiredService()
+ .EnvironmentName;
+ var deployments = FusionPipeline.SelectDeployments(
+ context.Model,
+ environment);
+
+ if (deployments.Count == 0)
+ {
+ return;
+ }
+
+ var output = context.Services
+ .GetRequiredService()
+ .GetOutputDirectory();
+ using var httpClient = new HttpClient
+ {
+ Timeout = TimeSpan.FromSeconds(10)
+ };
+
+ foreach (var deployment in deployments)
+ {
+ var deploymentDirectory = GetDeploymentDirectory(output, deployment);
+
+ foreach (var sourceDirectory in Directory.EnumerateDirectories(
+ Path.Combine(deploymentDirectory, "sources")))
+ {
+ var settingsPath = Path.Combine(
+ sourceDirectory,
+ "schema-settings.template.json");
+ using var settings = JsonDocument.Parse(
+ await File.ReadAllTextAsync(
+ settingsPath,
+ context.CancellationToken));
+ var endpoint = GetTransportEndpoint(settings);
+ RejectLoopbackEndpoint(endpoint);
+
+ using var response = await httpClient.GetAsync(
+ endpoint,
+ context.CancellationToken);
+ if ((int)response.StatusCode >= (int)HttpStatusCode.InternalServerError)
+ {
+ throw new InvalidOperationException(
+ $"Fusion source '{Path.GetFileName(sourceDirectory)}' did not pass "
+ + "its production readiness check.");
+ }
+ }
+ }
+ }
+
+ public async Task UploadAsync(PipelineStepContext context)
+ {
+ var artifacts = await MaterializeArchivesAsync(context);
+ if (artifacts.Count == 0)
+ {
+ return;
+ }
+
+ var workflow = context.Services.GetRequiredService();
+
+ foreach (var group in artifacts.GroupBy(artifact => artifact.Deployment))
+ {
+ var target = await ResolveTargetAsync(
+ group.Key,
+ context,
+ context.CancellationToken);
+
+ foreach (var artifact in group)
+ {
+ await workflow.ReconcileSourceSchemaAsync(
+ target,
+ new FusionSourceSchemaUpload(
+ artifact.Name,
+ artifact.Version,
+ artifact.ArchivePath,
+ artifact.Sha256),
+ context.CancellationToken);
+ }
+ }
+ }
+
+ public async Task PublishAsync(PipelineStepContext context)
+ {
+ var artifacts = await MaterializeArchivesAsync(context);
+ if (artifacts.Count == 0)
+ {
+ return;
+ }
+
+ var workflow = context.Services.GetRequiredService();
+ var compositionResource = FusionPipeline.GetCompositionResource(context.Model);
+ var composition = GraphQLResourceModel.GetComposition(compositionResource);
+
+ foreach (var group in artifacts.GroupBy(artifact => artifact.Deployment))
+ {
+ var deployment = group.Key;
+ var target = await ResolveTargetAsync(
+ deployment,
+ context,
+ context.CancellationToken);
+ var releaseId = await ResolveConfigurationTagAsync(
+ deployment,
+ context.CancellationToken);
+ var farPath = Path.Combine(
+ Path.GetDirectoryName(group.First().ArchivePath)!,
+ $"{releaseId}.far");
+
+ await ComposeAsync(
+ farPath,
+ group.ToArray(),
+ composition.Settings,
+ context,
+ context.CancellationToken);
+
+ await workflow.PublishAsync(
+ new FusionPublicationRequest(
+ target,
+ deployment.StageName!,
+ releaseId,
+ group
+ .Select(artifact =>
+ new FusionSourceSchemaVersion(
+ artifact.Name,
+ artifact.Version))
+ .ToArray(),
+ deployment.WaitForApproval,
+ deployment.Force,
+ deployment.OperationTimeout,
+ deployment.ApprovalTimeout),
+ farPath,
+ context.CancellationToken);
+
+ await WriteDeploymentManifestAsync(
+ deployment,
+ releaseId,
+ group.ToArray(),
+ context,
+ context.CancellationToken);
+ }
+ }
+
+ internal async Task> MaterializeArchivesAsync(
+ PipelineStepContext context)
+ {
+ var environment = context.Services
+ .GetRequiredService()
+ .EnvironmentName;
+ var deployments = FusionPipeline.SelectDeployments(
+ context.Model,
+ environment);
+
+ if (deployments.Count == 0)
+ {
+ return [];
+ }
+
+ var output = context.Services
+ .GetRequiredService()
+ .GetOutputDirectory();
+ var artifacts = new List();
+
+ foreach (var deployment in deployments)
+ {
+ var releaseId = await ResolveConfigurationTagAsync(
+ deployment,
+ context.CancellationToken);
+ var deploymentDirectory = GetDeploymentDirectory(output, deployment);
+ var materializedDirectory = Path.Combine(
+ deploymentDirectory,
+ "materialized");
+ Directory.CreateDirectory(materializedDirectory);
+
+ foreach (var sourceDirectory in Directory.EnumerateDirectories(
+ Path.Combine(deploymentDirectory, "sources")))
+ {
+ var name = Path.GetFileName(sourceDirectory);
+ var sourceVersion = deployment.UseGitCommitAsSourceVersion
+ ? await ReadGitCommitAsync(
+ sourceDirectory,
+ context.CancellationToken)
+ : releaseId;
+ ValidatePathSegment(sourceVersion, "source version");
+ var schema = await File.ReadAllBytesAsync(
+ Path.Combine(sourceDirectory, "schema.graphqls"),
+ context.CancellationToken);
+ var settingsPath = Path.Combine(
+ sourceDirectory,
+ "schema-settings.template.json");
+ using var settings = JsonDocument.Parse(
+ await File.ReadAllTextAsync(
+ settingsPath,
+ context.CancellationToken));
+
+ ValidateSettingsName(name, settings);
+
+ var endpoint = GetTransportEndpoint(settings);
+ RejectLoopbackEndpoint(endpoint);
+
+ var archivePath = Path.Combine(
+ materializedDirectory,
+ $"{name}-{sourceVersion}.zip");
+ await CreateArchiveAsync(
+ archivePath,
+ schema,
+ settings,
+ GetExtensionsPath(sourceDirectory),
+ context.CancellationToken);
+ var digest = await ComputeFileDigestAsync(
+ archivePath,
+ context.CancellationToken);
+
+ artifacts.Add(
+ new(
+ deployment,
+ name,
+ sourceVersion,
+ archivePath,
+ digest));
+ }
+ }
+
+ return artifacts;
+ }
+
+ private static async Task CreateDeploymentArtifactsAsync(
+ FusionDeploymentResource deployment,
+ IReadOnlyList sources,
+ string output,
+ CancellationToken cancellationToken)
+ {
+ var deploymentDirectory = GetDeploymentDirectory(output, deployment);
+ var fusionDirectory = Path.GetDirectoryName(deploymentDirectory)!;
+ Directory.CreateDirectory(fusionDirectory);
+ var temporaryDirectory = Path.Combine(
+ fusionDirectory,
+ $".{deployment.Name}.{Guid.NewGuid():N}.tmp");
+
+ try
+ {
+ var sourcesDirectory = Path.Combine(temporaryDirectory, "sources");
+ Directory.CreateDirectory(sourcesDirectory);
+ var sourceNames = new List(sources.Count);
+
+ foreach (var source in sources)
+ {
+ sourceNames.Add(
+ await CreateSourceArtifactsAsync(
+ source,
+ sourcesDirectory,
+ cancellationToken));
+ }
+
+ var template = new FusionDeploymentTemplate(
+ FormatVersion: 1,
+ CloudUrl: deployment.Nitro.CloudUrl!,
+ ApiId: deployment.Nitro.ApiId!,
+ Environment: deployment.EnvironmentName!,
+ Stage: deployment.StageName!,
+ ConfigurationTag: deployment.ConfigurationTag
+ ?? $"{{{{{deployment.ConfigurationTagParameter!.Name}}}}}",
+ StageOwnership: "authoritative",
+ Sources: sourceNames.Order().ToArray());
+
+ await WriteJsonAtomicallyAsync(
+ Path.Combine(temporaryDirectory, "nitro-deployment-template.json"),
+ template,
+ cancellationToken);
+
+ ReplaceDirectoryAtomically(
+ temporaryDirectory,
+ deploymentDirectory);
+ }
+ finally
+ {
+ DeleteDirectoryBestEffort(temporaryDirectory);
+ }
+ }
+
+ internal static void ReplaceDirectoryAtomically(
+ string sourceDirectory,
+ string destinationDirectory)
+ {
+ if (!Directory.Exists(sourceDirectory))
+ {
+ throw new DirectoryNotFoundException(
+ $"Replacement directory '{sourceDirectory}' does not exist.");
+ }
+
+ var destinationParent = Path.GetDirectoryName(destinationDirectory)
+ ?? throw new InvalidOperationException(
+ $"Replacement destination '{destinationDirectory}' has no parent directory.");
+ Directory.CreateDirectory(destinationParent);
+ var backupDirectory = Path.Combine(
+ destinationParent,
+ $".{Path.GetFileName(destinationDirectory)}.{Guid.NewGuid():N}.bak");
+ var movedDestination = false;
+
+ try
+ {
+ if (Directory.Exists(destinationDirectory))
+ {
+ Directory.Move(destinationDirectory, backupDirectory);
+ movedDestination = true;
+ }
+
+ try
+ {
+ Directory.Move(sourceDirectory, destinationDirectory);
+ }
+ catch
+ {
+ if (movedDestination
+ && !Directory.Exists(destinationDirectory)
+ && Directory.Exists(backupDirectory))
+ {
+ Directory.Move(backupDirectory, destinationDirectory);
+ movedDestination = false;
+ }
+
+ throw;
+ }
+ }
+ finally
+ {
+ if (movedDestination)
+ {
+ DeleteDirectoryBestEffort(backupDirectory);
+ }
+ }
+ }
+
+ private static async Task CreateSourceArtifactsAsync(
+ GraphQLSourceSchemaResource sourceSchema,
+ string sourcesDirectory,
+ CancellationToken cancellationToken)
+ {
+ var source = sourceSchema.Resource;
+ var declaration = sourceSchema.Declaration;
+
+ string schemaPath;
+ string settingsPath;
+ string? extensionsPath = null;
+ string projectPath;
+ string configuration;
+ string? targetFramework;
+ string? runtimeIdentifier;
+ using var temporaryExportDirectory = new TemporaryDirectoryScope();
+
+ switch (declaration.Location)
+ {
+ case SourceSchemaLocationType.ProjectDirectory:
+ var schemaPaths = GraphQLResourceModel.GetProjectSchemaPaths(
+ source,
+ declaration);
+ projectPath = schemaPaths.ProjectPath;
+ schemaPath = schemaPaths.SchemaPath;
+ settingsPath = schemaPaths.SettingsPath;
+ extensionsPath = schemaPaths.ExtensionsPath;
+ configuration = "prebuilt";
+ targetFramework = null;
+ runtimeIdentifier = null;
+ break;
+
+ case SourceSchemaLocationType.CommandLineExport:
+ var exportDirectory =
+ temporaryExportDirectory.Create(source.Name);
+ var export = await CommandLineSchemaExporter.ExportAsync(
+ source,
+ declaration,
+ exportDirectory,
+ cancellationToken);
+ schemaPath = export.SchemaPath;
+ settingsPath = export.SettingsPath;
+ projectPath = export.ProjectPath;
+ configuration = export.Configuration;
+ targetFramework = export.TargetFramework;
+ runtimeIdentifier = export.RuntimeIdentifier;
+ break;
+
+ case SourceSchemaLocationType.SchemaEndpoint:
+ throw new InvalidOperationException(
+ $"GraphQL source '{source.Name}' uses runtime endpoint acquisition, which "
+ + "is unavailable during Aspire publish. Declare a schema file or an "
+ + "explicit command-line export.");
+
+ default:
+ throw new InvalidOperationException(
+ $"GraphQL source '{source.Name}' has an unsupported acquisition mode.");
+ }
+
+ if (!File.Exists(schemaPath) || !File.Exists(settingsPath))
+ {
+ throw new InvalidOperationException(
+ $"GraphQL source '{source.Name}' did not provide both schema and settings files.");
+ }
+
+ var schema = await File.ReadAllTextAsync(schemaPath, cancellationToken);
+ if (string.IsNullOrWhiteSpace(schema))
+ {
+ throw new InvalidOperationException(
+ $"GraphQL source '{source.Name}' has an empty schema.");
+ }
+
+ string? extensions = null;
+ if (extensionsPath is not null && File.Exists(extensionsPath))
+ {
+ extensions = await File.ReadAllTextAsync(
+ extensionsPath,
+ cancellationToken);
+ }
+
+ using var settings = JsonDocument.Parse(
+ await File.ReadAllTextAsync(settingsPath, cancellationToken));
+ var endpointConfiguration = SchemaComposition.ReadEndpointConfiguration(
+ source.Name,
+ declaration.SourceSchemaName ?? source.Name,
+ settings);
+ var name = endpointConfiguration.SourceSchemaName;
+ ValidatePathSegment(name, "source schema name");
+ GraphQLSourceSchemaValidator.Validate(
+ source.Name,
+ endpointConfiguration,
+ schema,
+ extensions);
+
+ var sourceDirectory = Path.Combine(sourcesDirectory, name);
+ Directory.CreateDirectory(sourceDirectory);
+ var destinationSchema = Path.Combine(sourceDirectory, "schema.graphqls");
+ var destinationSettings = Path.Combine(
+ sourceDirectory,
+ "schema-settings.template.json");
+ await File.WriteAllTextAsync(
+ destinationSchema,
+ schema,
+ cancellationToken);
+ await File.WriteAllTextAsync(
+ destinationSettings,
+ settings.RootElement.GetRawText(),
+ cancellationToken);
+
+ if (extensions is not null)
+ {
+ await File.WriteAllTextAsync(
+ Path.Combine(sourceDirectory, "schema-extensions.graphqls"),
+ extensions,
+ cancellationToken);
+ }
+
+ var projectDigest = await ComputeFileDigestAsync(
+ projectPath,
+ cancellationToken);
+ var schemaDigest = await ComputeFileDigestAsync(
+ destinationSchema,
+ cancellationToken);
+ var provenance = new FusionSourceProvenance(
+ ProjectPath: projectPath,
+ ProjectSha256: projectDigest,
+ SchemaSha256: schemaDigest,
+ Configuration: configuration,
+ TargetFramework: targetFramework,
+ RuntimeIdentifier: runtimeIdentifier,
+ LaunchProfile: false,
+ WorkingDirectory: Path.GetDirectoryName(projectPath)!);
+
+ await WriteJsonAtomicallyAsync(
+ Path.Combine(sourceDirectory, "provenance.json"),
+ provenance,
+ cancellationToken);
+
+ return name;
+ }
+
+ private static async Task CreateArchiveAsync(
+ string archivePath,
+ byte[] schema,
+ JsonDocument settings,
+ string? extensionsPath,
+ CancellationToken cancellationToken)
+ {
+ var temporaryPath = archivePath + "." + Guid.NewGuid().ToString("N") + ".tmp";
+
+ try
+ {
+ using (var archive = FusionSourceSchemaArchive.Create(temporaryPath))
+ {
+ await archive.SetArchiveMetadataAsync(
+ new HotChocolate.Fusion.SourceSchema.Packaging.ArchiveMetadata(),
+ cancellationToken);
+ await archive.SetSchemaAsync(schema, cancellationToken);
+ await archive.SetSettingsAsync(settings, cancellationToken);
+
+ if (extensionsPath is not null)
+ {
+ await archive.SetSchemaExtensionsAsync(
+ await File.ReadAllBytesAsync(
+ extensionsPath,
+ cancellationToken),
+ cancellationToken);
+ }
+
+ await archive.CommitAsync(cancellationToken);
+ }
+
+ File.Move(temporaryPath, archivePath, overwrite: true);
+ }
+ finally
+ {
+ if (File.Exists(temporaryPath))
+ {
+ File.Delete(temporaryPath);
+ }
+ }
+ }
+
+ private static async Task ComposeAsync(
+ string farPath,
+ IReadOnlyList artifacts,
+ GraphQLCompositionSettings settings,
+ PipelineStepContext context,
+ CancellationToken cancellationToken)
+ {
+ if (File.Exists(farPath))
+ {
+ File.Delete(farPath);
+ }
+
+ var logger = context.Services
+ .GetRequiredService>();
+ if (!await AspireCompositionHelper.TryComposeArchivesAsync(
+ farPath,
+ artifacts.Select(
+ artifact => new SourceSchemaArchiveInfo(
+ artifact.Name,
+ artifact.ArchivePath))
+ .ToArray(),
+ settings,
+ logger,
+ cancellationToken))
+ {
+ throw new InvalidOperationException(
+ "Fusion configuration composition failed.");
+ }
+ }
+
+ private static async Task ResolveTargetAsync(
+ FusionDeploymentResource deployment,
+ PipelineStepContext context,
+ CancellationToken cancellationToken)
+ {
+ var apiKey = deployment.Nitro.ApiKey is null
+ ? context.Services.GetRequiredService()["Nitro:ApiKey"]
+ ?? context.Services.GetRequiredService()["NITRO_API_KEY"]
+ : await deployment.Nitro.ApiKey.GetValueAsync(cancellationToken);
+
+ if (string.IsNullOrWhiteSpace(apiKey))
+ {
+ throw new InvalidOperationException(
+ $"Nitro target '{deployment.Nitro.Name}' requires an API key.");
+ }
+
+ return new(
+ new Uri(deployment.Nitro.CloudUrl!, UriKind.Absolute),
+ deployment.Nitro.ApiId!,
+ apiKey);
+ }
+
+ private static async Task WriteDeploymentManifestAsync(
+ FusionDeploymentResource deployment,
+ string releaseId,
+ IReadOnlyList artifacts,
+ PipelineStepContext context,
+ CancellationToken cancellationToken)
+ {
+ var output = context.Services
+ .GetRequiredService()
+ .GetOutputDirectory();
+ var manifest = new FusionDeploymentManifest(
+ FormatVersion: 1,
+ CloudUrl: deployment.Nitro.CloudUrl!,
+ ApiId: deployment.Nitro.ApiId!,
+ Environment: deployment.EnvironmentName!,
+ Stage: deployment.StageName!,
+ ConfigurationTag: releaseId,
+ StageOwnership: "authoritative",
+ Sources: artifacts.Select(
+ artifact => new FusionDeploymentManifestSource(
+ artifact.Name,
+ artifact.Version,
+ Path.GetRelativePath(
+ GetDeploymentDirectory(output, deployment),
+ artifact.ArchivePath),
+ artifact.Sha256))
+ .ToArray());
+
+ await WriteJsonAtomicallyAsync(
+ Path.Combine(
+ GetDeploymentDirectory(output, deployment),
+ "nitro-deployment.json"),
+ manifest,
+ cancellationToken);
+ }
+
+ internal static Uri GetTransportEndpoint(JsonDocument settings)
+ {
+ var root = settings.RootElement;
+ if (!root.TryGetProperty("transports", out var transports)
+ || !transports.TryGetProperty("http", out var http)
+ || !http.TryGetProperty("url", out var url)
+ || url.ValueKind is not JsonValueKind.String
+ || !Uri.TryCreate(url.GetString(), UriKind.Absolute, out var endpoint))
+ {
+ throw new InvalidOperationException(
+ "Fusion deployment settings must specify an absolute production "
+ + "transports.http.url.");
+ }
+
+ return endpoint;
+ }
+
+ private static void RejectLoopbackEndpoint(Uri endpoint)
+ {
+ if (endpoint.IsLoopback
+ || endpoint.Host.Equals("localhost", StringComparison.OrdinalIgnoreCase))
+ {
+ throw new InvalidOperationException(
+ "Fusion deployment settings must not contain a loopback production endpoint.");
+ }
+ }
+
+ private static void ValidateSettingsName(
+ string expectedName,
+ JsonDocument settings)
+ {
+ if (!settings.RootElement.TryGetProperty("name", out var name)
+ || name.ValueKind is not JsonValueKind.String
+ || !string.Equals(
+ name.GetString(),
+ expectedName,
+ StringComparison.Ordinal))
+ {
+ throw new InvalidOperationException(
+ $"Fusion source settings name must exactly match '{expectedName}'.");
+ }
+ }
+
+ private static string? GetExtensionsPath(string sourceDirectory)
+ {
+ var path = Path.Combine(
+ sourceDirectory,
+ "schema-extensions.graphqls");
+ return File.Exists(path) ? path : null;
+ }
+
+ private static async Task ResolveConfigurationTagAsync(
+ FusionDeploymentResource deployment,
+ CancellationToken cancellationToken)
+ {
+ var value = deployment.ConfigurationTag;
+ if (deployment.ConfigurationTagParameter is not null)
+ {
+ value = await deployment.ConfigurationTagParameter.GetValueAsync(
+ cancellationToken);
+ }
+
+ if (string.IsNullOrWhiteSpace(value))
+ {
+ throw new InvalidOperationException(
+ $"Fusion deployment '{deployment.Name}' configuration tag resolved to an empty value.");
+ }
+
+ ValidatePathSegment(value, "configuration tag");
+ return value;
+ }
+
+ private static async Task ReadGitCommitAsync(
+ string sourceDirectory,
+ CancellationToken cancellationToken)
+ {
+ using var provenance = JsonDocument.Parse(
+ await File.ReadAllTextAsync(
+ Path.Combine(sourceDirectory, "provenance.json"),
+ cancellationToken));
+ var workingDirectory = provenance.RootElement
+ .GetProperty("workingDirectory")
+ .GetString()!;
+ var startInfo = new ProcessStartInfo
+ {
+ FileName = "git",
+ RedirectStandardOutput = true,
+ RedirectStandardError = true,
+ UseShellExecute = false,
+ CreateNoWindow = true
+ };
+ startInfo.ArgumentList.Add("-C");
+ startInfo.ArgumentList.Add(workingDirectory);
+ startInfo.ArgumentList.Add("rev-parse");
+ startInfo.ArgumentList.Add("HEAD");
+
+ using var process = Process.Start(startInfo)
+ ?? throw new InvalidOperationException("Could not start Git.");
+ var output = await process.StandardOutput.ReadToEndAsync(cancellationToken);
+ await process.WaitForExitAsync(cancellationToken);
+
+ if (process.ExitCode != 0 || string.IsNullOrWhiteSpace(output))
+ {
+ throw new InvalidOperationException(
+ "Could not resolve the Git commit for a Fusion source version.");
+ }
+
+ return output.Trim();
+ }
+
+ internal static void ValidatePathSegment(
+ string value,
+ string description)
+ {
+ if (value is "." or ".."
+ || value.Any(character =>
+ !char.IsAsciiLetterOrDigit(character)
+ && character is not '.' and not '_' and not '-'))
+ {
+ throw new InvalidOperationException(
+ $"Fusion {description} '{value}' cannot be used as a portable path segment.");
+ }
+ }
+
+ private static async Task ComputeFileDigestAsync(
+ string path,
+ CancellationToken cancellationToken)
+ {
+ await using var stream = File.OpenRead(path);
+ var digest = await SHA256.HashDataAsync(stream, cancellationToken);
+ return Convert.ToHexStringLower(digest);
+ }
+
+ private static async Task WriteJsonAtomicallyAsync(
+ string path,
+ T value,
+ CancellationToken cancellationToken)
+ {
+ Directory.CreateDirectory(Path.GetDirectoryName(path)!);
+ var temporaryPath = path + "." + Guid.NewGuid().ToString("N") + ".tmp";
+
+ try
+ {
+ await using (var stream = File.Create(temporaryPath))
+ {
+ await JsonSerializer.SerializeAsync(
+ stream,
+ value,
+ new JsonSerializerOptions
+ {
+ PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
+ WriteIndented = true
+ },
+ cancellationToken);
+ }
+
+ File.Move(temporaryPath, path, overwrite: true);
+ }
+ finally
+ {
+ if (File.Exists(temporaryPath))
+ {
+ File.Delete(temporaryPath);
+ }
+ }
+ }
+
+ private static string GetDeploymentDirectory(
+ string output,
+ FusionDeploymentResource deployment)
+ => Path.Combine(output, "fusion", deployment.Name);
+
+ private static void DeleteDirectoryBestEffort(string path)
+ {
+ try
+ {
+ if (Directory.Exists(path))
+ {
+ Directory.Delete(path, recursive: true);
+ }
+ }
+ catch (IOException)
+ {
+ }
+ catch (UnauthorizedAccessException)
+ {
+ }
+ }
+
+ private sealed class TemporaryDirectoryScope : IDisposable
+ {
+ private string? _path;
+
+ public string Create(string resourceName)
+ {
+ _path = Path.Combine(
+ Path.GetTempPath(),
+ "chilicream-nitro-aspire",
+ Guid.NewGuid().ToString("N"),
+ resourceName);
+ return _path;
+ }
+
+ public void Dispose()
+ {
+ try
+ {
+ if (_path is not null && Directory.Exists(_path))
+ {
+ Directory.Delete(_path, recursive: true);
+ }
+ }
+ catch (IOException)
+ {
+ }
+ }
+ }
+}
+
+internal sealed record FusionSourceArtifact(
+ FusionDeploymentResource Deployment,
+ string Name,
+ string Version,
+ string ArchivePath,
+ string Sha256);
+
+internal sealed record FusionDeploymentTemplate(
+ int FormatVersion,
+ string CloudUrl,
+ string ApiId,
+ string Environment,
+ string Stage,
+ string ConfigurationTag,
+ string StageOwnership,
+ IReadOnlyList Sources);
+
+internal sealed record FusionSourceProvenance(
+ string ProjectPath,
+ string ProjectSha256,
+ string SchemaSha256,
+ string Configuration,
+ string? TargetFramework,
+ string? RuntimeIdentifier,
+ bool LaunchProfile,
+ string WorkingDirectory);
+
+internal sealed record FusionDeploymentManifest(
+ int FormatVersion,
+ string CloudUrl,
+ string ApiId,
+ string Environment,
+ string Stage,
+ string ConfigurationTag,
+ string StageOwnership,
+ IReadOnlyList Sources);
+
+internal sealed record FusionDeploymentManifestSource(
+ string Name,
+ string SourceVersion,
+ string Archive,
+ string Sha256);
+
+#pragma warning restore ASPIREPIPELINES004
+#pragma warning restore ASPIREPIPELINES001
diff --git a/src/Nitro/Common/src/ChilliCream.Nitro.Aspire/FusionPipelineResource.cs b/src/Nitro/Common/src/ChilliCream.Nitro.Aspire/FusionPipelineResource.cs
new file mode 100644
index 00000000000..fac5c024f31
--- /dev/null
+++ b/src/Nitro/Common/src/ChilliCream.Nitro.Aspire/FusionPipelineResource.cs
@@ -0,0 +1,5 @@
+using Aspire.Hosting.ApplicationModel;
+
+namespace ChilliCream.Nitro.Aspire;
+
+internal sealed class FusionPipelineResource(string name) : Resource(name);
diff --git a/src/Nitro/Common/src/ChilliCream.Nitro.Aspire/IFusionPipelineExecutor.cs b/src/Nitro/Common/src/ChilliCream.Nitro.Aspire/IFusionPipelineExecutor.cs
new file mode 100644
index 00000000000..3b3cf938912
--- /dev/null
+++ b/src/Nitro/Common/src/ChilliCream.Nitro.Aspire/IFusionPipelineExecutor.cs
@@ -0,0 +1,18 @@
+using Aspire.Hosting.Pipelines;
+
+namespace ChilliCream.Nitro.Aspire;
+
+#pragma warning disable ASPIREPIPELINES001
+
+internal interface IFusionPipelineExecutor
+{
+ Task CreateArtifactsAsync(PipelineStepContext context);
+
+ Task VerifyReadinessAsync(PipelineStepContext context);
+
+ Task UploadAsync(PipelineStepContext context);
+
+ Task PublishAsync(PipelineStepContext context);
+}
+
+#pragma warning restore ASPIREPIPELINES001
diff --git a/src/Nitro/Common/src/ChilliCream.Nitro.Aspire/NitroResource.cs b/src/Nitro/Common/src/ChilliCream.Nitro.Aspire/NitroResource.cs
new file mode 100644
index 00000000000..b3b8a59722a
--- /dev/null
+++ b/src/Nitro/Common/src/ChilliCream.Nitro.Aspire/NitroResource.cs
@@ -0,0 +1,15 @@
+using Aspire.Hosting.ApplicationModel;
+
+namespace ChilliCream.Nitro.Aspire;
+
+///
+/// Represents a Nitro target in an Aspire application model.
+///
+public sealed class NitroResource(string name) : Resource(name)
+{
+ internal string? CloudUrl { get; set; }
+
+ internal string? ApiId { get; set; }
+
+ internal ParameterResource? ApiKey { get; set; }
+}
diff --git a/src/Nitro/Common/src/ChilliCream.Nitro.Aspire/NitroResourceBuilderExtensions.cs b/src/Nitro/Common/src/ChilliCream.Nitro.Aspire/NitroResourceBuilderExtensions.cs
new file mode 100644
index 00000000000..5a59ce81f6e
--- /dev/null
+++ b/src/Nitro/Common/src/ChilliCream.Nitro.Aspire/NitroResourceBuilderExtensions.cs
@@ -0,0 +1,238 @@
+using Aspire.Hosting;
+using Aspire.Hosting.ApplicationModel;
+using ChilliCream.Nitro.Fusion;
+
+namespace ChilliCream.Nitro.Aspire;
+
+///
+/// Provides extensions for declaring Nitro Fusion deployments.
+///
+public static class NitroResourceBuilderExtensions
+{
+ ///
+ /// Adds a Nitro target.
+ ///
+ public static IResourceBuilder AddNitro(
+ this IDistributedApplicationBuilder builder,
+ string name)
+ {
+ ArgumentNullException.ThrowIfNull(builder);
+ ArgumentException.ThrowIfNullOrWhiteSpace(name);
+
+ EnsureFusionPipeline(builder);
+ builder.Services.AddNitroFusionDeploymentWorkflow();
+
+ var configuredCloudUrl =
+ builder.Configuration["Nitro:CloudUrl"]
+ ?? builder.Configuration["NITRO_CLOUD_URL"];
+ var resource = new NitroResource(name)
+ {
+ CloudUrl = string.IsNullOrWhiteSpace(configuredCloudUrl)
+ ? null
+ : NormalizeCloudUrl(configuredCloudUrl),
+ ApiId =
+ builder.Configuration["Nitro:ApiId"]
+ ?? builder.Configuration["NITRO_API_ID"]
+ };
+
+ return builder.AddResource(resource);
+ }
+
+ ///
+ /// Sets the Nitro GraphQL API URL.
+ ///
+ public static IResourceBuilder WithCloudUrl(
+ this IResourceBuilder builder,
+ string cloudUrl)
+ {
+ ArgumentNullException.ThrowIfNull(builder);
+
+ builder.Resource.CloudUrl = NormalizeCloudUrl(cloudUrl);
+ return builder;
+ }
+
+ ///
+ /// Sets the Nitro API identifier.
+ ///
+ public static IResourceBuilder WithApiId(
+ this IResourceBuilder builder,
+ string apiId)
+ {
+ ArgumentNullException.ThrowIfNull(builder);
+ ArgumentException.ThrowIfNullOrWhiteSpace(apiId);
+
+ builder.Resource.ApiId = apiId;
+ return builder;
+ }
+
+ ///
+ /// Sets the secret parameter used as the Nitro API key.
+ ///
+ public static IResourceBuilder WithApiKey(
+ this IResourceBuilder builder,
+ IResourceBuilder apiKey)
+ {
+ ArgumentNullException.ThrowIfNull(builder);
+ ArgumentNullException.ThrowIfNull(apiKey);
+
+ if (!apiKey.Resource.Secret)
+ {
+ throw new ArgumentException(
+ "The Nitro API key parameter must be declared as a secret.",
+ nameof(apiKey));
+ }
+
+ builder.Resource.ApiKey = apiKey.Resource;
+ return builder;
+ }
+
+ ///
+ /// Adds an environment-specific Fusion deployment.
+ ///
+ public static IResourceBuilder AddFusionDeployment(
+ this IResourceBuilder builder,
+ string name)
+ {
+ ArgumentNullException.ThrowIfNull(builder);
+ ArgumentException.ThrowIfNullOrWhiteSpace(name);
+
+ var resource = new FusionDeploymentResource(name, builder.Resource);
+ return builder.ApplicationBuilder.AddResource(resource);
+ }
+
+ ///
+ /// Maps the deployment to an exact Aspire environment.
+ ///
+ public static IResourceBuilder ForEnvironment(
+ this IResourceBuilder builder,
+ string environmentName)
+ {
+ ArgumentNullException.ThrowIfNull(builder);
+ ArgumentException.ThrowIfNullOrWhiteSpace(environmentName);
+
+ builder.Resource.EnvironmentName = environmentName;
+ return builder;
+ }
+
+ ///
+ /// Maps the deployment to an exact Nitro stage.
+ ///
+ public static IResourceBuilder ToStage(
+ this IResourceBuilder builder,
+ string stageName)
+ {
+ ArgumentNullException.ThrowIfNull(builder);
+ ArgumentException.ThrowIfNullOrWhiteSpace(stageName);
+
+ builder.Resource.StageName = stageName;
+ return builder;
+ }
+
+ ///
+ /// Sets the immutable release tag.
+ ///
+ public static IResourceBuilder WithConfigurationTag(
+ this IResourceBuilder builder,
+ IResourceBuilder configurationTag)
+ {
+ ArgumentNullException.ThrowIfNull(builder);
+ ArgumentNullException.ThrowIfNull(configurationTag);
+
+ builder.Resource.ConfigurationTagParameter = configurationTag.Resource;
+ builder.Resource.ConfigurationTag = null;
+ return builder;
+ }
+
+ ///
+ /// Sets the immutable release tag.
+ ///
+ public static IResourceBuilder WithConfigurationTag(
+ this IResourceBuilder builder,
+ string configurationTag)
+ {
+ ArgumentNullException.ThrowIfNull(builder);
+ ArgumentException.ThrowIfNullOrWhiteSpace(configurationTag);
+
+ builder.Resource.ConfigurationTag = configurationTag;
+ builder.Resource.ConfigurationTagParameter = null;
+ return builder;
+ }
+
+ ///
+ /// Uses the current Git commit as the default source schema version.
+ ///
+ public static IResourceBuilder
+ WithDefaultSourceVersionFromGitCommit(
+ this IResourceBuilder builder)
+ {
+ ArgumentNullException.ThrowIfNull(builder);
+ builder.Resource.UseGitCommitAsSourceVersion = true;
+ return builder;
+ }
+
+ ///
+ /// Configures whether Nitro waits for approval.
+ ///
+ public static IResourceBuilder WithApproval(
+ this IResourceBuilder builder,
+ bool waitForApproval)
+ {
+ ArgumentNullException.ThrowIfNull(builder);
+ builder.Resource.WaitForApproval = waitForApproval;
+ return builder;
+ }
+
+ ///
+ /// Configures whether validation failures may be forced.
+ ///
+ public static IResourceBuilder WithForce(
+ this IResourceBuilder builder,
+ bool force)
+ {
+ ArgumentNullException.ThrowIfNull(builder);
+ builder.Resource.Force = force;
+ return builder;
+ }
+
+ ///
+ /// Configures operation and approval timeouts.
+ ///
+ public static IResourceBuilder WithTimeouts(
+ this IResourceBuilder builder,
+ TimeSpan operation,
+ TimeSpan approval)
+ {
+ ArgumentNullException.ThrowIfNull(builder);
+ ArgumentOutOfRangeException.ThrowIfLessThanOrEqual(operation, TimeSpan.Zero);
+ ArgumentOutOfRangeException.ThrowIfLessThanOrEqual(approval, TimeSpan.Zero);
+
+ builder.Resource.OperationTimeout = operation;
+ builder.Resource.ApprovalTimeout = approval;
+ return builder;
+ }
+
+ private static void EnsureFusionPipeline(IDistributedApplicationBuilder builder)
+ {
+ if (builder.Resources.OfType().Any())
+ {
+ return;
+ }
+
+ var pipeline = builder.AddResource(
+ new FusionPipelineResource("fusion-nitro-pipeline"));
+ FusionPipeline.Configure(pipeline);
+ }
+
+ private static string NormalizeCloudUrl(string cloudUrl)
+ {
+ if (!Uri.TryCreate(cloudUrl, UriKind.Absolute, out var uri)
+ || uri.Scheme is not "https")
+ {
+ throw new ArgumentException(
+ "The Nitro cloud URL must be an absolute HTTPS URL.",
+ nameof(cloudUrl));
+ }
+
+ return uri.AbsoluteUri.TrimEnd('/');
+ }
+}
diff --git a/src/Nitro/Common/src/ChilliCream.Nitro.Aspire/README.md b/src/Nitro/Common/src/ChilliCream.Nitro.Aspire/README.md
new file mode 100644
index 00000000000..a357409c4a8
--- /dev/null
+++ b/src/Nitro/Common/src/ChilliCream.Nitro.Aspire/README.md
@@ -0,0 +1,29 @@
+# ChilliCream.Nitro.Aspire
+
+Publishes Hot Chocolate Fusion configurations through the .NET Aspire deployment pipeline.
+
+```csharp
+var nitroApiKey = builder.AddParameter("nitroApiKey", secret: true);
+var releaseId = builder.AddParameter("releaseId");
+
+var nitro = builder.AddNitro("nitro")
+ .WithCloudUrl("https://api.chillicream.com")
+ .WithApiId("products-fusion")
+ .WithApiKey(nitroApiKey);
+
+nitro.AddFusionDeployment("production")
+ .ForEnvironment("Production")
+ .ToStage("production")
+ .WithConfigurationTag(releaseId)
+ .WithDefaultSourceVersionFromGitCommit()
+ .WithApproval(waitForApproval: true)
+ .WithForce(false)
+ .WithTimeouts(
+ operation: TimeSpan.FromMinutes(15),
+ approval: TimeSpan.FromHours(2));
+```
+
+`aspire publish` creates portable Fusion artifacts and has no Nitro side effects. Use
+`aspire do fusion-upload` to reconcile source versions and `aspire do fusion-publish` to run the
+full readiness, composition, and publication graph. A matching `aspire deploy` also requires
+`fusion-publish` to finish successfully.
diff --git a/src/Nitro/Common/src/ChilliCream.Nitro.Client/FUSION_ASPIRE_PUBLISH_DEPLOY.md b/src/Nitro/Common/src/ChilliCream.Nitro.Client/FUSION_ASPIRE_PUBLISH_DEPLOY.md
new file mode 100644
index 00000000000..769454ae558
--- /dev/null
+++ b/src/Nitro/Common/src/ChilliCream.Nitro.Client/FUSION_ASPIRE_PUBLISH_DEPLOY.md
@@ -0,0 +1,386 @@
+# Fusion and .NET Aspire publishing and deployment
+
+## Decision
+
+`aspire deploy` is the canonical Fusion release command. When an AppHost explicitly declares a Fusion deployment for the selected Aspire environment, every matching `aspire deploy` must export, reconcile source-schema uploads, compose, and publish the Fusion configuration before the well-known Deploy step can complete.
+
+`aspire publish` remains artifact-only for Fusion. It produces portable schema inputs, templates, bindings, and provenance, but it does not call Nitro, resolve a Nitro credential, or mutate a Nitro stage. Named `aspire do` steps remain useful for inspection, repair, and controlled reconciliation, but they are supplementary and must not provide a weaker route around compute/readiness dependencies.
+
+The resulting invariant is:
+
+```text
+Fusion deployment declared for environment E
+ +
+aspire deploy --environment E
+ =
+Nitro stage reaches terminal success, or the Aspire deployment does not succeed
+```
+
+This is an explicit opt-in at AppHost design time, not an implicit inference. An AppHost without a matching Fusion deployment has no Nitro side effect.
+
+## Aspire version and API maturity
+
+At the time of research, the latest stable Aspire release is **13.4.6**, released June 20, 2026. See [Aspire 13.4.6](https://github.com/microsoft/aspire/releases/tag/v13.4.6). Aspire 13.4 made `aspire publish` and `aspire deploy` generally available. See [what's new in Aspire 13.4](https://aspire.dev/whats-new/aspire-13-4/).
+
+The programmatic pipeline APIs used to register and order custom steps remain experimental and emit `ASPIREPIPELINES001`. `aspire do` is the command for running a selected step and its dependencies, but that does not make every API behind custom step construction GA. Keep the experimental integration behind a narrow adapter and explicitly accept the diagnostic in that package. Sources: [deployment pipelines](https://aspire.dev/deployment/pipelines/), [ASPIREPIPELINES001](https://aspire.dev/diagnostics/aspirepipelines001/), [`aspire publish`](https://aspire.dev/reference/cli/commands/aspire-publish/), [`aspire deploy`](https://aspire.dev/reference/cli/commands/aspire-deploy/), and [`aspire do`](https://aspire.dev/reference/cli/commands/aspire-do/).
+
+This repository currently pins `Aspire.Hosting.AppHost`, `Aspire.Hosting`, and `Aspire.Hosting.PostgreSQL` to **13.1.2** in [`src/Directory.Packages.props`](../../../../Directory.Packages.props). The required step-discovery and pipeline configuration concepts exist in that pin. Implement and test against 13.1.2 first, then separately test and upgrade to the current stable line.
+
+## Command contract
+
+| Entry point | Fusion behavior | Remote effect |
+| --- | --- | --- |
+| `aspire publish` | Evaluate/build as Aspire requires, then emit Fusion SDL, settings templates, endpoint bindings, archive inputs, and provenance beneath the output path. | No Nitro API call, Nitro credential resolution, upload, slot request, or stage mutation. Aspire itself may still create/update local deployment configuration, verify certificates, build, or perform other non-Nitro work. |
+| `aspire deploy --environment Production` | Run the provider deployment and every Fusion deployment explicitly mapped to `Production`. It succeeds only after each mapped Nitro publication reaches terminal success. | Mandatory Nitro reconciliation for each matching declaration. |
+| `aspire do fusion-upload` | Produce portable Fusion inputs and reconcile immutable source versions. | Upload only. It is not equivalent to deployment completion. |
+| `aspire do fusion-publish` | Run the same compute discovery, readiness, upload, composition, and publication dependency graph as the matching deploy. | Safe supplementary reconciliation. It can redeploy or recheck prerequisites as dictated by its graph. |
+| `aspire destroy` | Destroy provider resources according to the deployment target. | Never infer deletion of shared Nitro schema history or stage configurations. Nitro retention needs a separate explicit design. |
+
+`aspire deploy` does not consume an arbitrary previously produced `aspire publish` directory as a promoted release. It evaluates the AppHost and executes pipeline dependencies for that invocation. Artifact promotion requires an explicit artifact-path/apply step or an external release tool.
+
+## Environment and stage selection
+
+The Fusion deployment declaration must map an Aspire environment to exactly one intended Nitro stage. Do not infer stage from branch, tag, provider, resource name, or `ASPNETCORE_ENVIRONMENT`. Do not deploy staging and production from the same invocation merely because both are declared.
+
+```csharp
+var nitro = builder.AddNitro("nitro")
+ .WithCloudUrl("https://api.chillicream.com")
+ .WithApiId("products-fusion")
+ .WithApiKey(builder.AddParameter("nitroApiKey", secret: true));
+
+nitro.AddFusionDeployment("production")
+ .ForEnvironment("Production")
+ .ToStage("production")
+ .WithConfigurationTag(builder.AddParameter("releaseId"))
+ .WithDefaultSourceVersionFromGitCommit()
+ .WithApproval(waitForApproval: true)
+ .WithForce(false)
+ .WithTimeouts(
+ operation: TimeSpan.FromMinutes(15),
+ approval: TimeSpan.FromHours(2));
+```
+
+Adding this resource opts Fusion publication into every `aspire deploy --environment Production`. A separate `.ForEnvironment("Staging").ToStage("staging")` declaration runs only when Staging is selected. Graph construction must fail when multiple Fusion deployments ambiguously claim the same environment/API/stage or when the selected environment has inconsistent mappings.
+
+The sketch is illustrative. Match the public API to Aspire 13.1.2 resource idioms and keep required values required.
+
+## Existing `HotChocolate.Fusion.Aspire` state
+
+The repository already has a source-schema and composition graph. Adapt it rather than creating a second Nitro-only graph.
+
+* [`GraphQLResourceBuilderExtensions.cs`](../../../../HotChocolate/Fusion/src/Fusion.Aspire/GraphQLResourceBuilderExtensions.cs) exposes `WithGraphQLSchemaFile`, `WithGraphQLSchemaEndpoint`, and `WithGraphQLSchemaComposition`.
+* [`SchemaComposition.cs`](../../../../HotChocolate/Fusion/src/Fusion.Aspire/SchemaComposition.cs) discovers referenced resources, creates internal `SourceSchemaInfo` records, and subscribes to `AfterResourcesCreatedEvent` through internal annotations and private discovery helpers.
+* Native endpoint acquisition uses `/graphql/schema.graphql`. `/graphql` is only for an explicitly identified Apollo Federation `_service.sdl` flow.
+* File mode can default its asserted name from the Aspire resource, while upload derives the authoritative name from `schema-settings.json`. The manifest must validate that the declared/manifest name exactly matches settings `name`.
+* Current runtime discovery is suitable for `aspire run`, but normal DCP application orchestration is disabled in publish mode in the inspected Aspire source. Publish cannot assume resource endpoints are running.
+
+Refactor these declarations into a reusable internal model while preserving composition relationships between the gateway/composition resource and its referenced sources. The deploy pipeline then augments those declarations with provider step discovery, deployment endpoint bindings, and readiness evidence.
+
+## Can `aspire publish` use Hot Chocolate command-line schema export?
+
+Yes, as an explicit short-lived child process. Aspire publish mode does not start normal AppHost/DCP resources, but the custom publish pipeline action can start the referenced GraphQL project itself to run `HotChocolate.AspNetCore.CommandLine`.
+
+This export is not a pure or side-effect-free metadata operation. The child process executes the application's `Program`, configuration loading, service registration, `Build`, and endpoint mapping. Resolving the request executor performs full Hot Chocolate schema initialization, including type modules, schema hooks, warmup tasks, and any user code reached by those paths. Kestrel and ordinary `IHostedService` instances do not start because command mode invokes the CLI and skips `host.Run`/`host.RunAsync`. See [`WebApplicationExtensions.cs`](../../../../HotChocolate/AspNetCore/src/AspNetCore.CommandLine/WebApplicationExtensions.cs) and [`ExportCommand.cs`](../../../../HotChocolate/AspNetCore/src/AspNetCore.CommandLine/Command/ExportCommand.cs).
+
+The correct registration symbol is `ExportSchemaOnStartup`, not `ExportSchemaFileOnStartup`. It registers a schema executor warmup task, so it can export again while the CLI export command initializes the executor. See [`HotChocolateAspNetCoreServiceCollectionExtensions.Warmup.cs`](../../../../HotChocolate/AspNetCore/src/AspNetCore/Extensions/HotChocolateAspNetCoreServiceCollectionExtensions.Warmup.cs). Projects used by the integration should either avoid the startup exporter in this mode or tolerate and isolate both writes.
+
+The application entry point must return the command exit code:
+
+```csharp
+return await app.RunWithGraphQLCommandsAsync(args);
+```
+
+Use an argument-safe process invocation equivalent to:
+
+```text
+dotnet run --project /absolute/path/Products.Subgraph.csproj --configuration Release --no-launch-profile -- schema export --output /isolated/products/schema.graphqls --schema-name Products
+```
+
+`schema` must be the first application argument after `--`, otherwise the application follows its normal server path. Always select the schema name explicitly. `ExportCommand` can print `No schemas registered.` and return successfully without creating output, so exit code zero is insufficient. The integration must validate the expected schema and settings artifacts.
+
+V1 should support checked-in/generated schema files and an explicit per-resource export command. Automatic `dotnet run` inference is opt-in because application startup and schema initialization can have arbitrary user side effects. Longer term, export from the exact published assembly or container that will be deployed, and bind schema provenance to its build/image digest.
+
+### Child-process requirements
+
+* Resolve a project with `ProjectResource.GetProjectMetadata().ProjectPath`. Reject resource types without a supported file/export declaration rather than guessing.
+* Precreate an isolated output directory per source resource and invocation. Never share the application working directory or accept a stale file as fallback.
+* Use `System.Diagnostics.Process` with `ProcessStartInfo.ArgumentList`, not shell concatenation. `WithProcessCommand` is a dashboard/resource command API, not the custom deployment pipeline runner.
+* Use an environment allowlist. Do not pass Nitro credentials or unrelated AppHost secrets to the child.
+* Record configuration, target framework, RID, working directory, launch-profile policy, project/assembly identity, and content/image digest in provenance. `--no-launch-profile` is the deterministic default.
+* Enforce timeout and cancellation, and kill the entire process tree on termination. Capture bounded stdout/stderr and redact sensitive values.
+* Validate freshness, non-empty SDL, parseable settings, exact `schema-settings.json` name, extensions, and the explicitly selected schema name.
+* Treat a generated settings URL that resolves to localhost/loopback as a template risk. Reject it for final deployment and materialize the provider-resolved production URL only after readiness.
+* Verify deterministic repeated exports for the same declared build inputs. Differences are a hard failure unless the differing provenance explains a new release input.
+
+Register the action with `WithPipelineStepFactory`. Use `WithPipelineConfiguration`, `PipelineConfigurationContext.GetSteps`, and `RequiredBy` to connect it to the release graph. There is no universal provider-neutral after-compute/readiness tag. Every supported provider needs an explicit step selector/readiness adapter.
+
+## Identity and configuration
+
+The recommended common path uses one immutable release ID as the configuration tag and as the default upload version for bare source names. The native model still keeps each source version explicit so an advanced rollout can select `products@version-a` and `inventory@version-b`.
+
+| Setting | Scope | Example | Policy |
+| --- | --- | --- | --- |
+| Cloud URL | Nitro target | `https://api.chillicream.com` | Explicit target/config value, then documented `NITRO_CLOUD_URL` compatibility fallback. HTTPS unless an explicit development exception exists. |
+| API ID | Nitro target | `products-fusion` | Explicit identifier, not a display name. |
+| API key | Credential | secret `ParameterResource` | Inject through CI/secret provider. Never store in artifacts or logs. |
+| Aspire environment | Deployment selector | `Production` | Required explicit `.ForEnvironment(...)` mapping. |
+| Stage | Nitro deployment | `production` | Required explicit mapping. Never inferred. |
+| Release/configuration tag | Deployment invocation | `build-842-a1b2c3d4` | Unique for the rollout and stable across its retries. Inject once per CI release invocation. |
+| Source version | Per source | `a1b2c3d4` or content hash | Immutable and derived from the exact deployed schema/build. Defaults to release tag only for bare-name compatibility. |
+| Approval | Deployment | `true` | Explicit policy. Deployment succeeds only at terminal Nitro success. |
+| Force | Deployment | `false` | Never infer and never default to true. |
+| Timeouts | Deployment | operation and approval limits | Explicit and conservative. Timeout returns failed/indeterminate plus the recoverable request ID. |
+| Stage ownership | Deployment | authoritative or additive | Explicit single-writer policy. |
+
+A Git commit alone is not always a rollout identity. Redeploying the same commit with different infrastructure, a dirty worktree, rebuilt image, changed endpoint binding, or altered settings can produce different desired state. CI should inject a unique release ID per release invocation and reuse it for retries of that same rollout. Do not derive the current release from stale Aspire deployment cache state.
+
+### Existing Nitro CLI input mapping
+
+| Existing input | Aspire-native input | Compatibility meaning |
+| --- | --- | --- |
+| `NITRO_API_ID` | `Nitro:ApiId` / `Parameters__nitroApiId` | API identity. |
+| `NITRO_STAGE` | deployment `.ToStage(...)` / `Parameters__nitroStage` | Explicit environment-to-stage mapping. |
+| `NITRO_TAG` | `configurationTag`, plus default source version for bare names | Publish uses it as configuration tag/default selected version; upload uses it as source version. Aspire splits the concepts internally. |
+| `NITRO_API_KEY` | secret `nitroApiKey` / `Parameters__nitroApiKey` | Never write to artifacts/logs. Aspire deployment cache can persist resolved secrets in plaintext as described below. |
+| `NITRO_CLOUD_URL` | `Nitro:CloudUrl` / `Parameters__nitroCloudUrl` | Compatibility override for the API base URL. |
+
+Prefer `ParameterResource` and Aspire configuration, including `Parameters__nitroApiKey` and `Parameters__releaseId`. Support `NITRO_*` only as a documented fallback with deterministic precedence. See [external parameters](https://aspire.dev/fundamentals/external-parameters/).
+
+Current source metadata must remain limited to the existing GitHub and Azure DevOps model. Richer provider/actor metadata is future work. Bind schema provenance to the exact build or container image digest deployed by the provider steps, not only to a mutable working directory.
+
+## Two-phase artifacts
+
+Some source-schema settings include deployment-resolved production URLs. A local publish cannot safely guess them. Artifact generation therefore has two phases.
+
+### Publish phase
+
+`aspire publish` emits immutable build inputs under the selected output path:
+
+```text
+/fusion/production/
+ nitro-deployment-template.json
+ sources/
+ products/
+ schema.graphqls
+ schema-settings.template.json
+ extensions/
+ provenance.json
+ inventory/
+ schema.graphqls
+ schema-settings.template.json
+ extensions/
+ provenance.json
+```
+
+Its Fusion graph ends at artifacts:
+
+```text
+source file or explicit child-process export
+ |
+ validate and record provenance
+ |
+ SDL/settings template/bindings
+ |
+ publish output complete
+```
+
+There is no Nitro credential resolution, upload, composition slot, commit, or stage mutation on this graph.
+
+Acquisition supports an existing SDL file and an explicit native export command such as:
+
+```text
+dotnet run --project /absolute/path/Products.Subgraph.csproj --configuration Release --no-launch-profile -- schema export --output /isolated/products/schema.graphqls --schema-name Products
+```
+
+Endpoint acquisition is unavailable by default in publish mode. An externally managed endpoint can be used only when explicitly declared and authenticated. Apollo `/graphql` requires an explicit Apollo source kind.
+
+### Deploy materialization phase
+
+After provider deployment and actual readiness, resolve production endpoint bindings, materialize final `schema-settings.json`, and build the archive with the public `HotChocolate.Fusion.SourceSchema.Packaging.FusionSourceSchemaArchive`. Stage composition and commit must occur after service deployment and actual readiness. The final manifest records the release and provider provenance:
+
+```json
+{
+ "formatVersion": 1,
+ "cloudUrl": "https://api.chillicream.com",
+ "apiId": "products-fusion",
+ "environment": "Production",
+ "stage": "production",
+ "configurationTag": "build-842-a1b2c3d4",
+ "stageOwnership": "authoritative",
+ "sources": [
+ {
+ "name": "products",
+ "sourceVersion": "a1b2c3d4",
+ "archive": "materialized/products-a1b2c3d4.zip",
+ "sha256": "...",
+ "imageDigest": "sha256:..."
+ }
+ ]
+}
+```
+
+The deployment manifest and its validation are new work. There is no existing Nitro CLI manifest/SDL validator to reuse. Validate all paths, hashes, settings names, bindings, and provenance. Write the final manifest atomically after all archives materialize.
+
+## Mandatory deploy graph
+
+The required ordering is:
+
+```text
+publish-time export/validation -----+
+ |
+provider source compute deploy | (may run in parallel)
+ | |
+actual production readiness --------+
+ |
+final settings/archive materialization
+ |
+reconcile source uploads
+ |
+request and claim Nitro slot
+ |
+re-download current stage FAR and selected archives
+ |
+authoritative local composition
+ |
+policy-aware remote validation and FAR commit
+ |
+terminal publication or approval completion
+ |
+WellKnownPipelineSteps.Deploy completes
+```
+
+Export can run in parallel with provider deployment. Readiness plus completed export feeds final settings/archive materialization, which precedes upload and stage composition. Upload may move earlier only when the final archive has no deployment-resolved input and its endpoint/provenance is already deployment-complete. If schema export itself requires deployment-only configuration, move that export after deployment/readiness or fail the resource as unsupported. Never claim a Nitro slot while waiting for compute deployment or readiness.
+
+The Nitro reconcile step must depend on the lowest provider deployment and readiness steps and be required by the well-known Deploy step. It must never depend on Deploy itself, because that creates a cycle.
+
+`RequiredBySteps = [WellKnownPipelineSteps.Deploy]` guarantees that reconciliation is included before Deploy completes. It does not order sibling prerequisites relative to one another. Register export with `WithPipelineStepFactory`. In `WithPipelineConfiguration`, discover concrete provider steps through `PipelineConfigurationContext.GetSteps(resource, WellKnownPipelineTags.DeployCompute)` where the provider supports it, then create explicit dependencies with `RequiredBy` from compute to readiness, export/readiness to materialization, upload to composition, and Nitro terminal status to root Deploy. These APIs are present in the repository-pinned Aspire 13.1.2 surface. There is no universal after-compute/readiness tag, so a provider adapter or explicit selector is required.
+
+Provider-neutral readiness is not proven. A `DeployCompute` step completing may mean a resource was submitted, not that its production endpoint accepts traffic. Provider adapters must add a supported readiness/check step. Graph construction must fail if an Aspire-managed source lacks supported deploy-step discovery or production readiness. A source explicitly declared as external may participate only with an explicit readiness proof.
+
+If Nitro publication is intended as an application-wide finalizer, it must also depend on all unrelated release prerequisites whose failure should prevent cutover. Merely being a sibling prerequisite of Deploy does not provide that ordering.
+
+## Current Nitro reconciliation flow
+
+For each matching deploy, the reconciliation step executes even if the desired state is unchanged:
+
+1. Resolve the selected environment declaration, release ID, stage ownership, force/approval policy, and timeouts.
+2. Run publish-time export/local validation in parallel with provider deployment where safe, then complete actual provider readiness. If export needs deployment-only configuration, run it after readiness or fail unsupported.
+3. After both export and readiness, resolve final production bindings, materialize source archives, and verify settings name/provenance/image digest.
+4. Reconcile each `name@sourceVersion`. Download an existing exact version and compare normalized schema, settings, and extensions. Identical is a verified no-op. Different content under the same identity is a hard collision. Upload only missing versions.
+5. Acquire stage serialization for `(cloudUrl, apiId, stage)`. Reconcile any persisted/server-backed request state before requesting a new slot.
+6. Request and claim the slot only after compute readiness. Re-download the latest stage FAR and every selected source archive after the slot is acquired so composition uses authoritative current inputs.
+7. Compose locally. Apply the selected stage ownership policy, preserving or removing undeclared schemas as defined below, and produce the desired FAR.
+8. Compare the desired FAR/intent with an existing publication for the same configuration tag. Identical is terminal success/no-op. Different intent for the same tag is a collision.
+9. When approval is disabled, validate the FAR before commit and apply the explicit force policy. When approval is enabled, commit starts processing and validation/approval states are observed through the subscription.
+10. Commit and subscribe until terminal success or failure. Approval-gated deployment succeeds only after terminal Nitro success.
+11. Complete the Nitro reconciliation prerequisite, allowing `WellKnownPipelineSteps.Deploy` to complete.
+
+On timeout, cancellation, or lost response, return failed/indeterminate and report the recoverable request ID. Release a claimed slot only when lifecycle-safe. An approval request can outlive a CI process, so a new invocation must resume/reconcile it rather than blindly create another publication.
+
+## Idempotency, serialization, and approvals
+
+Every-deploy reconciliation makes idempotency mandatory:
+
+* Same source name/version plus normalized-identical content is success/no-op. Same identity plus different content is a collision.
+* Same release/configuration tag plus identical desired FAR and selected source intent is success/no-op. Same tag plus different intent is a collision.
+* Persist `requestId`, phase, desired FAR digest, release ID, and source selection. Local cache alone is insufficient because CI runners are ephemeral and responses can be lost. Require server-backed lookup/idempotency or an equivalent durable release record before claiming robust retry behavior.
+* Serialize publishers by `(cloudUrl, apiId, stage)`. A stale approval must never supersede a newer rollout. Enforce stage queue/order on the server or fail when it cannot be proven.
+* Retry only bounded, known-transient transport/server failures with exponential backoff and jitter. Never retry authorization, invalid schema/settings, stage/API not found, force-policy rejection, or identity collisions.
+
+Aspire stores deployment state under `~/.aspire/deployments`, including resolved parameter values and secrets in plaintext. Never share, publish, or commit this cache. Inject credentials and the release ID from CI, and use clear-cache behavior when state is stale or compromised. The cache cannot be the authority for Nitro idempotency. See [deployment state caching](https://aspire.dev/deployment/deployment-state-caching/).
+
+## Stage ownership and partial state
+
+Choose and document one stage ownership policy:
+
+| Policy | Behavior | Constraint |
+| --- | --- | --- |
+| Authoritative declared set | The resulting FAR contains exactly the AppHost-declared source set for this deployment. Undeclared schemas are removed. | Recommended for a single release owner. Requires complete declarations. |
+| Additive preserve-undeclared | Replace declared sources and preserve undeclared sources from the latest stage FAR. | Required for shared ownership, but prone to drift. Still requires one serialized writer/coordinator per stage. |
+
+There is no transaction across the service deployment provider, artifact uploads, and Nitro stage publication. Uploads can remain orphaned. Compute can be updated while the old FAR remains active if Nitro validation, approval, or commit fails. Automatic rollback across the compute provider and Nitro is unsafe without a provider-specific, tested rollback protocol.
+
+Source-service changes must remain backward-compatible with the old FAR during this window. Operators need a documented recovery path using the persisted request ID, release manifest, image digests, and previous FAR identity. The deployment result must report partial state precisely instead of claiming rollback.
+
+## Named `aspire do` operations
+
+Use target-specific names and actual CLI options:
+
+```bash
+aspire publish --output-path ./artifacts/aspire --environment Production --non-interactive
+aspire do fusion-upload --output-path ./artifacts/aspire --environment Production --non-interactive
+aspire do fusion-publish --output-path ./artifacts/aspire --environment Production --non-interactive
+aspire do fusion-publish --list-steps
+```
+
+`aspire do` evaluates and builds the AppHost unless `--no-build` is used, and it reruns the selected step's dependencies. Deployment commands default to Production. Inspect scope with `--list-steps`. The safe reconcile command carries the same provider compute/readiness dependencies as Deploy, so it may redeploy or recheck resources.
+
+`aspire publish` remains the artifact inspection path, and upload alone does not publish a release. `fusion-publish` requires the supported compute and readiness graph before it claims a slot.
+
+## Packaging and implementation plan
+
+`ChilliCream.Nitro.Client` is explicitly non-packable in [`ChilliCream.Nitro.Client.csproj`](ChilliCream.Nitro.Client.csproj). Extract/move the supported client and workflow into a packable assembly or deliberately co-ship supported assemblies. A public `ChilliCream.Nitro.Aspire` package must not depend on an internal non-packable project.
+
+| Area | Work |
+| --- | --- |
+| Existing Fusion Aspire | Adapt its source annotations and composition relationships into a reusable declaration model. |
+| Artifact layer | Reuse `FusionSourceSchemaArchive`; add template, binding, provenance, manifest, normalization, and validation code. |
+| Nitro workflow | Extract current local FAR composition and `IFusionConfigurationClient` orchestration behind a packable supported API. |
+| Aspire pipeline | Add environment-filtered resources, provider adapters, readiness proof, exact step dependencies, Deploy completion prerequisite, and `do` commands. |
+| State/recovery | Add server-backed request/tag lookup or durable release-state service, stage serialization, resume, collision checks, and terminal status reporting. |
+
+### Release-critical phases
+
+1. Prove pipeline wiring on Aspire 13.1.2: environment filtering, `GetSteps(...DeployCompute)`, exact dependencies, `RequiredBySteps`, `do --list-steps`, and cycle detection.
+2. Refactor existing Fusion Aspire declarations and implement two-phase artifacts with provenance bound to deployed build/image digest.
+3. Implement provider adapter one, including production endpoint readiness. Fail unsupported graphs closed.
+4. Implement mandatory upload reconciliation and normalized duplicate policy.
+5. Implement stage serialization, request resume/idempotency, authoritative re-download/local FAR composition, validation/commit, approvals, and terminal reporting.
+6. Integrate reconciliation as a prerequisite of WellKnown Deploy for every environment-matched declaration.
+7. Exercise partial-state and recovery behavior end to end, then upgrade/test against Aspire 13.4.6.
+
+## Tests and acceptance criteria
+
+| Layer | Required evidence |
+| --- | --- |
+| Environment selection | Production deploy runs only Production Fusion deployment; Staging runs only Staging; ambiguous mappings fail graph construction. |
+| Publish | Produces templates/provenance and has no Nitro calls, credential resolution, upload, slot, or stage mutation. |
+| Export lifecycle | Sentinels prove `Program`, configuration, service registration, endpoint mapping, schema hooks/modules, and executor warmups run. Sentinels also prove Kestrel and normal `IHostedService` instances do not start in command mode. |
+| Export command | Uses argv-safe `ArgumentList`, explicit schema name, isolated/precreated output, bounded redacted output, timeout/cancellation/tree kill, and no Nitro secrets in the environment. |
+| Export validation | Multi-schema selection is exact; zero exit with no registered schema/no output fails; localhost settings fail final materialization; stale output never falls back; repeated identical input exports deterministically. |
+| Export provenance | Configuration, TFM, RID, working directory, launch-profile policy, project/assembly and exact build/image digest match the deployed resource. Unsupported resource types fail closed. |
+| Pipeline topology | Export may parallel compute; export plus actual readiness precede final materialization/upload; upload/readiness precede slot; Nitro terminal success precedes Deploy completion. Sibling prerequisites cannot race and no step depends on Deploy. |
+| Provider readiness | Supported provider proves a real production endpoint, and unsupported Aspire-managed sources fail graph construction. External source requires explicit proof. |
+| Materialization | Production bindings and exact image/build digest produce the final archive; settings name equals declared name. |
+| Upload reconciliation | Exact normalized source identity is no-op; mismatch is collision; missing source uploads once under bounded retries. |
+| Composition | Acquires slot after readiness, re-downloads latest FAR and sources, applies declared stage ownership, composes locally, and validates/commits the FAR. |
+| Publication identity | Same release tag/identical intent is no-op; same tag/different intent fails; new release is serialized after existing stage work. |
+| Resume/approval | Lost response or ephemeral runner resumes by request ID/server record. Approval timeout is failed/indeterminate, and Deploy cannot succeed before terminal Nitro success. Stale approval cannot supersede a later rollout. |
+| Partial state | Nitro failure after compute update reports new compute plus old FAR, leaves recoverable state, and does not claim automatic rollback. |
+| `aspire do` | Safe reconcile includes compute/readiness dependencies. Export/upload inspection cannot masquerade as completed deployment. |
+| Compatibility | Focused suite passes on repository pin 13.1.2 and on 13.4.6 before support is advertised. |
+
+Done means every matching `aspire deploy` executes Fusion reconciliation, can verified-no-op on identical desired state, and cannot complete until Nitro reaches terminal success. It also means the pipeline refuses to construct when exact compute/readiness ordering cannot be proven.
+
+## Remaining questions
+
+1. Which provider is the first supported adapter, and what concrete step proves its production endpoint ready rather than merely submitted?
+2. Which Nitro server lookup/idempotency API can recover request ID and phase from `(api, stage, release tag, desired digest)` on a new CI runner?
+3. Can the server reject or serialize stale approvals so an older request can never become current after a newer rollout?
+4. Which fields form normalized source archive equality, and can packaging APIs expose them without duplicate parsing?
+5. Is authoritative stage ownership acceptable for the first integration, or is additive multi-owner composition required?
+6. Which unrelated application prerequisites must Nitro cutover wait for when it acts as the global finalizer?
+7. How should a same-commit rebuild derive source versions and release IDs when schema content, endpoint bindings, or image digests differ?
+8. Which resources can safely opt into automatic child-process export, and which initialization hooks need explicit isolation guidance?
+
+## Sources
+
+* [What's new in Aspire 13.4](https://aspire.dev/whats-new/aspire-13-4/)
+* [Aspire 13.4.6 release](https://github.com/microsoft/aspire/releases/tag/v13.4.6)
+* [Deploy with Aspire](https://aspire.dev/deployment/deploy-with-aspire/)
+* [Aspire deployment pipelines](https://aspire.dev/deployment/pipelines/)
+* [`aspire publish`](https://aspire.dev/reference/cli/commands/aspire-publish/), [`aspire deploy`](https://aspire.dev/reference/cli/commands/aspire-deploy/), and [`aspire do`](https://aspire.dev/reference/cli/commands/aspire-do/)
+* [Aspire external parameters](https://aspire.dev/fundamentals/external-parameters/)
+* [ASPIREPIPELINES001](https://aspire.dev/diagnostics/aspirepipelines001/)
+* [Aspire deployment state caching](https://aspire.dev/deployment/deployment-state-caching/)
+* Local code: [`GraphQLResourceBuilderExtensions.cs`](../../../../HotChocolate/Fusion/src/Fusion.Aspire/GraphQLResourceBuilderExtensions.cs), [`SchemaComposition.cs`](../../../../HotChocolate/Fusion/src/Fusion.Aspire/SchemaComposition.cs), [`WebApplicationExtensions.cs`](../../../../HotChocolate/AspNetCore/src/AspNetCore.CommandLine/WebApplicationExtensions.cs), [`ExportCommand.cs`](../../../../HotChocolate/AspNetCore/src/AspNetCore.CommandLine/Command/ExportCommand.cs), [`HotChocolateAspNetCoreServiceCollectionExtensions.Warmup.cs`](../../../../HotChocolate/AspNetCore/src/AspNetCore/Extensions/HotChocolateAspNetCoreServiceCollectionExtensions.Warmup.cs), [`FusionConfiguration/IFusionConfigurationClient.cs`](FusionConfiguration/IFusionConfigurationClient.cs), [`FusionConfiguration/FusionConfigurationClient.cs`](FusionConfiguration/FusionConfigurationClient.cs), [`ChilliCream.Nitro.Client.csproj`](ChilliCream.Nitro.Client.csproj), and [`src/Directory.Packages.props`](../../../../Directory.Packages.props).
diff --git a/src/Nitro/Common/src/ChilliCream.Nitro.Fusion/.graphqlrc.json b/src/Nitro/Common/src/ChilliCream.Nitro.Fusion/.graphqlrc.json
new file mode 100644
index 00000000000..87f7b94b3a8
--- /dev/null
+++ b/src/Nitro/Common/src/ChilliCream.Nitro.Fusion/.graphqlrc.json
@@ -0,0 +1,25 @@
+{
+ "name": "ChilliCream.Nitro.Fusion",
+ "schema": "../ChilliCream.Nitro.Client/schema.graphql",
+ "documents": "Operations/*.graphql",
+ "extensions": {
+ "strawberryShake": {
+ "name": "FusionApiClient",
+ "namespace": "ChilliCream.Nitro.Fusion.Transport",
+ "accessModifier": "internal",
+ "emitGeneratedCode": true,
+ "noStore": true,
+ "records": {
+ "inputs": true,
+ "entities": true
+ },
+ "transportProfiles": [
+ {
+ "name": "Default",
+ "default": "HTTP",
+ "subscription": "HTTP"
+ }
+ ]
+ }
+ }
+}
diff --git a/src/Nitro/Common/src/ChilliCream.Nitro.Fusion/ChilliCream.Nitro.Fusion.csproj b/src/Nitro/Common/src/ChilliCream.Nitro.Fusion/ChilliCream.Nitro.Fusion.csproj
new file mode 100644
index 00000000000..1a6d03773e7
--- /dev/null
+++ b/src/Nitro/Common/src/ChilliCream.Nitro.Fusion/ChilliCream.Nitro.Fusion.csproj
@@ -0,0 +1,33 @@
+
+
+
+ ChilliCream.Nitro.Fusion
+ ChilliCream.Nitro.Fusion
+ net11.0;net10.0;net9.0
+ false
+ Provides deterministic Nitro upload and publication workflows for Hot Chocolate Fusion.
+ README.md
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Nitro/Common/src/ChilliCream.Nitro.Fusion/FusionArchiveContent.cs b/src/Nitro/Common/src/ChilliCream.Nitro.Fusion/FusionArchiveContent.cs
new file mode 100644
index 00000000000..a5ebf1301a5
--- /dev/null
+++ b/src/Nitro/Common/src/ChilliCream.Nitro.Fusion/FusionArchiveContent.cs
@@ -0,0 +1,140 @@
+using System.Text;
+using System.Text.Json;
+using HotChocolate.Fusion.SourceSchema.Packaging;
+using HotChocolate.Language;
+
+namespace ChilliCream.Nitro.Fusion;
+
+internal sealed record FusionArchiveContent(
+ string Schema,
+ string? SchemaExtensions,
+ string Settings)
+{
+ public static async Task ReadAsync(
+ string archivePath,
+ string expectedName,
+ CancellationToken cancellationToken)
+ {
+ await using var stream = File.OpenRead(archivePath);
+ return await ReadAsync(stream, expectedName, cancellationToken);
+ }
+
+ public static async Task ReadAsync(
+ Stream stream,
+ string expectedName,
+ CancellationToken cancellationToken)
+ {
+ try
+ {
+ using var archive = FusionSourceSchemaArchive.Open(
+ stream,
+ leaveOpen: true);
+ var schema = await archive.TryGetSchemaAsync(cancellationToken)
+ ?? throw new FusionDeploymentException(
+ "The Fusion source schema archive contains no schema.");
+ var extensions =
+ await archive.TryGetSchemaExtensionsAsync(cancellationToken);
+ using var settings = await archive.TryGetSettingsAsync(cancellationToken)
+ ?? throw new FusionDeploymentException(
+ "The Fusion source schema archive contains no settings.");
+
+ if (!settings.RootElement.TryGetProperty("name", out var name)
+ || name.ValueKind is not JsonValueKind.String
+ || !string.Equals(
+ name.GetString(),
+ expectedName,
+ StringComparison.Ordinal))
+ {
+ throw new FusionDeploymentException(
+ "The source schema settings name must exactly match "
+ + $"'{expectedName}'.");
+ }
+
+ return new FusionArchiveContent(
+ NormalizeGraphQL(schema),
+ extensions is null
+ ? null
+ : NormalizeGraphQL(extensions.Value),
+ NormalizeJson(settings.RootElement));
+ }
+ catch (FusionDeploymentException)
+ {
+ throw;
+ }
+ catch (Exception exception) when (
+ exception is InvalidDataException
+ or JsonException
+ or SyntaxException)
+ {
+ throw new FusionDeploymentException(
+ "The Fusion source schema archive is invalid.",
+ exception);
+ }
+ }
+
+ private static string NormalizeGraphQL(ReadOnlyMemory source)
+ => Utf8GraphQLParser.Parse(source.Span).ToString();
+
+ private static string NormalizeJson(JsonElement value)
+ {
+ using var stream = new MemoryStream();
+ using (var writer = new Utf8JsonWriter(stream))
+ {
+ WriteCanonicalJson(writer, value);
+ }
+
+ return Encoding.UTF8.GetString(stream.GetBuffer(), 0, (int)stream.Length);
+ }
+
+ private static void WriteCanonicalJson(
+ Utf8JsonWriter writer,
+ JsonElement value)
+ {
+ switch (value.ValueKind)
+ {
+ case JsonValueKind.Object:
+ writer.WriteStartObject();
+ foreach (var property in value.EnumerateObject()
+ .OrderBy(property => property.Name, StringComparer.Ordinal))
+ {
+ writer.WritePropertyName(property.Name);
+ WriteCanonicalJson(writer, property.Value);
+ }
+ writer.WriteEndObject();
+ break;
+
+ case JsonValueKind.Array:
+ writer.WriteStartArray();
+ foreach (var item in value.EnumerateArray())
+ {
+ WriteCanonicalJson(writer, item);
+ }
+ writer.WriteEndArray();
+ break;
+
+ case JsonValueKind.String:
+ writer.WriteStringValue(value.GetString());
+ break;
+
+ case JsonValueKind.Number:
+ writer.WriteRawValue(value.GetRawText());
+ break;
+
+ case JsonValueKind.True:
+ writer.WriteBooleanValue(true);
+ break;
+
+ case JsonValueKind.False:
+ writer.WriteBooleanValue(false);
+ break;
+
+ case JsonValueKind.Null:
+ writer.WriteNullValue();
+ break;
+
+ default:
+ throw new JsonException(
+ $"Unsupported JSON token kind '{value.ValueKind}'.");
+ }
+ }
+}
diff --git a/src/Nitro/Common/src/ChilliCream.Nitro.Fusion/FusionDeploymentException.cs b/src/Nitro/Common/src/ChilliCream.Nitro.Fusion/FusionDeploymentException.cs
new file mode 100644
index 00000000000..73ab3035a91
--- /dev/null
+++ b/src/Nitro/Common/src/ChilliCream.Nitro.Fusion/FusionDeploymentException.cs
@@ -0,0 +1,17 @@
+namespace ChilliCream.Nitro.Fusion;
+
+///
+/// The base exception for failures reported by the Fusion deployment workflow.
+///
+public class FusionDeploymentException : Exception
+{
+ public FusionDeploymentException(string message)
+ : base(message)
+ {
+ }
+
+ public FusionDeploymentException(string message, Exception innerException)
+ : base(message, innerException)
+ {
+ }
+}
diff --git a/src/Nitro/Common/src/ChilliCream.Nitro.Fusion/FusionDeploymentWorkflow.cs b/src/Nitro/Common/src/ChilliCream.Nitro.Fusion/FusionDeploymentWorkflow.cs
new file mode 100644
index 00000000000..d595f5c818f
--- /dev/null
+++ b/src/Nitro/Common/src/ChilliCream.Nitro.Fusion/FusionDeploymentWorkflow.cs
@@ -0,0 +1,593 @@
+using System.Security.Cryptography;
+using ChilliCream.Nitro.Fusion.Transport;
+
+namespace ChilliCream.Nitro.Fusion;
+
+internal sealed class FusionDeploymentWorkflow(
+ IFusionDeploymentTransportFactory transportFactory)
+ : IFusionDeploymentWorkflow
+{
+ public async Task ReconcileSourceSchemaAsync(
+ FusionTarget target,
+ FusionSourceSchemaUpload source,
+ CancellationToken cancellationToken)
+ {
+ ValidateTarget(target);
+ ValidateSource(source);
+
+ var localContent = await FusionArchiveContent.ReadAsync(
+ source.ArchivePath,
+ source.Name,
+ cancellationToken);
+ await VerifySha256Async(source, cancellationToken);
+
+ await using var transport = await transportFactory.OpenAsync(
+ target,
+ cancellationToken);
+ var remoteArchive = await transport.DownloadSourceSchemaAsync(
+ source.Name,
+ source.Version,
+ cancellationToken);
+
+ if (remoteArchive is not null)
+ {
+ await EnsureContentMatchesAsync(
+ source,
+ localContent,
+ remoteArchive,
+ cancellationToken);
+ return;
+ }
+
+ FusionRemoteCommandResult uploadResult;
+ try
+ {
+ uploadResult = await transport.UploadSourceSchemaAsync(
+ source.Version,
+ source.ArchivePath,
+ cancellationToken);
+ }
+ catch (OperationCanceledException) when (
+ cancellationToken.IsCancellationRequested)
+ {
+ throw;
+ }
+ catch (Exception exception)
+ {
+ await ReconcileAfterUncertainUploadAsync(
+ transport,
+ source,
+ localContent,
+ exception,
+ cancellationToken);
+ return;
+ }
+
+ if (uploadResult.Succeeded)
+ {
+ return;
+ }
+
+ if (uploadResult.IsDuplicate)
+ {
+ var racedArchive = await transport.DownloadSourceSchemaAsync(
+ source.Name,
+ source.Version,
+ cancellationToken);
+ if (racedArchive is null)
+ {
+ throw new FusionIndeterminateStateException(
+ $"Nitro reported source schema '{source.Name}' version "
+ + $"'{source.Version}' as duplicated, but the version "
+ + "could not be read back.");
+ }
+
+ await EnsureContentMatchesAsync(
+ source,
+ localContent,
+ racedArchive,
+ cancellationToken);
+ return;
+ }
+
+ throw CreateRemoteFailure(
+ "Nitro rejected the Fusion source schema upload.",
+ uploadResult.Errors);
+ }
+
+ public async Task PublishAsync(
+ FusionPublicationRequest request,
+ string fusionArchivePath,
+ CancellationToken cancellationToken)
+ {
+ ValidatePublication(request, fusionArchivePath);
+
+ using var timeout = CancellationTokenSource.CreateLinkedTokenSource(
+ cancellationToken);
+ timeout.CancelAfter(request.OperationTimeout);
+ var operationToken = timeout.Token;
+ string? requestId = null;
+
+ try
+ {
+ await using var transport = await transportFactory.OpenAsync(
+ request.Target,
+ operationToken);
+ FusionRemoteBeginResult begin;
+
+ try
+ {
+ begin = await transport.BeginPublishAsync(
+ request,
+ operationToken);
+ }
+ catch (Exception exception) when (
+ exception is not OperationCanceledException)
+ {
+ throw new FusionIndeterminateStateException(
+ "The Fusion publication request may have been created, "
+ + "but Nitro did not return a verifiable result.",
+ exception);
+ }
+
+ if (begin.Errors.Count > 0)
+ {
+ throw CreateRemoteFailure(
+ "Nitro rejected the Fusion publication request.",
+ begin.Errors);
+ }
+
+ requestId = begin.RequestId;
+ if (string.IsNullOrWhiteSpace(requestId))
+ {
+ throw new FusionIndeterminateStateException(
+ "Nitro accepted the Fusion publication request without "
+ + "returning a request identifier.");
+ }
+
+ await using var events = transport.WatchPublishAsync(
+ requestId,
+ operationToken)
+ .GetAsyncEnumerator(operationToken);
+
+ var readyResult = await WaitForReadyAsync(
+ events,
+ requestId,
+ operationToken);
+ if (readyResult is PublishWaitResult.Succeeded)
+ {
+ return;
+ }
+
+ await EnsureRemoteCommandSucceededAsync(
+ () => transport.ClaimPublishAsync(requestId, operationToken),
+ "claim the Fusion publication slot",
+ requestId);
+
+ if (!request.WaitForApproval)
+ {
+ await EnsureRemoteCommandSucceededAsync(
+ () => transport.ValidatePublishAsync(
+ requestId,
+ fusionArchivePath,
+ operationToken),
+ "validate the Fusion configuration",
+ requestId);
+
+ var validation = await WaitForValidationAsync(
+ events,
+ requestId,
+ operationToken);
+ if (validation is { Succeeded: false } && !request.Force)
+ {
+ await ReleaseKnownFailedValidationAsync(
+ transport,
+ requestId,
+ operationToken);
+ throw CreateRemoteFailure(
+ "Nitro rejected the Fusion configuration validation.",
+ validation.Errors);
+ }
+ }
+
+ await EnsureRemoteCommandSucceededAsync(
+ () => transport.CommitPublishAsync(
+ requestId,
+ fusionArchivePath,
+ operationToken),
+ "commit the Fusion configuration",
+ requestId);
+
+ await WaitForTerminalPublishAsync(
+ events,
+ requestId,
+ timeout,
+ request.ApprovalTimeout,
+ operationToken);
+ }
+ catch (OperationCanceledException) when (
+ !cancellationToken.IsCancellationRequested)
+ {
+ throw new FusionIndeterminateStateException(
+ "The Fusion publication timed out before a terminal result "
+ + "could be verified.",
+ requestId);
+ }
+ }
+
+ private static async Task ReconcileAfterUncertainUploadAsync(
+ IFusionDeploymentTransport transport,
+ FusionSourceSchemaUpload source,
+ FusionArchiveContent localContent,
+ Exception uploadException,
+ CancellationToken cancellationToken)
+ {
+ byte[]? remoteArchive;
+ try
+ {
+ remoteArchive = await transport.DownloadSourceSchemaAsync(
+ source.Name,
+ source.Version,
+ cancellationToken);
+ }
+ catch (Exception readException)
+ {
+ throw new FusionIndeterminateStateException(
+ $"The upload of source schema '{source.Name}' version "
+ + $"'{source.Version}' may have succeeded and could not be "
+ + "verified.",
+ new AggregateException(uploadException, readException));
+ }
+
+ if (remoteArchive is null)
+ {
+ throw new FusionIndeterminateStateException(
+ $"The upload of source schema '{source.Name}' version "
+ + $"'{source.Version}' returned an uncertain result and the "
+ + "version was not available for verification.",
+ uploadException);
+ }
+
+ await EnsureContentMatchesAsync(
+ source,
+ localContent,
+ remoteArchive,
+ cancellationToken);
+ }
+
+ private static async Task EnsureContentMatchesAsync(
+ FusionSourceSchemaUpload source,
+ FusionArchiveContent localContent,
+ byte[] remoteArchive,
+ CancellationToken cancellationToken)
+ {
+ await using var stream = new MemoryStream(remoteArchive, writable: false);
+ var remoteContent = await FusionArchiveContent.ReadAsync(
+ stream,
+ source.Name,
+ cancellationToken);
+
+ if (localContent != remoteContent)
+ {
+ throw new FusionIdentityCollisionException(
+ $"Source schema '{source.Name}' version '{source.Version}' "
+ + "already exists with different normalized schema, settings, "
+ + "or extensions.");
+ }
+ }
+
+ private static async Task VerifySha256Async(
+ FusionSourceSchemaUpload source,
+ CancellationToken cancellationToken)
+ {
+ if (source.Sha256.Length is not 64
+ || !source.Sha256.All(Uri.IsHexDigit))
+ {
+ throw new FusionDeploymentException(
+ "The source schema SHA-256 must contain exactly 64 "
+ + "hexadecimal characters.");
+ }
+
+ await using var stream = File.OpenRead(source.ArchivePath);
+ var actual = Convert.ToHexString(
+ await SHA256.HashDataAsync(stream, cancellationToken));
+ if (!string.Equals(
+ actual,
+ source.Sha256,
+ StringComparison.OrdinalIgnoreCase))
+ {
+ throw new FusionDeploymentException(
+ $"The SHA-256 for source schema '{source.Name}' version "
+ + $"'{source.Version}' does not match its archive.");
+ }
+ }
+
+ private static async Task WaitForReadyAsync(
+ IAsyncEnumerator events,
+ string requestId,
+ CancellationToken cancellationToken)
+ {
+ while (await MoveNextAsync(events, requestId, cancellationToken))
+ {
+ switch (events.Current.Kind)
+ {
+ case FusionRemoteEventKind.Ready:
+ return PublishWaitResult.Ready;
+ case FusionRemoteEventKind.PublishingSucceeded:
+ return PublishWaitResult.Succeeded;
+ case FusionRemoteEventKind.PublishingFailed:
+ throw CreateRemoteFailure(
+ "The Fusion publication failed.",
+ events.Current.Errors);
+ case FusionRemoteEventKind.Queued:
+ continue;
+ default:
+ throw new FusionIndeterminateStateException(
+ "The Fusion publication request was already in an "
+ + $"ambiguous '{events.Current.Kind}' state.",
+ requestId);
+ }
+ }
+
+ throw CreateEndedEarly(requestId);
+ }
+
+ private static async Task WaitForValidationAsync(
+ IAsyncEnumerator events,
+ string requestId,
+ CancellationToken cancellationToken)
+ {
+ while (await MoveNextAsync(events, requestId, cancellationToken))
+ {
+ switch (events.Current.Kind)
+ {
+ case FusionRemoteEventKind.ValidationSucceeded:
+ return new FusionValidationResult(true, []);
+ case FusionRemoteEventKind.ValidationFailed:
+ return new FusionValidationResult(
+ false,
+ events.Current.Errors);
+ case FusionRemoteEventKind.InProgress:
+ continue;
+ case FusionRemoteEventKind.PublishingFailed:
+ throw CreateRemoteFailure(
+ "The Fusion publication failed during validation.",
+ events.Current.Errors);
+ default:
+ throw new FusionIndeterminateStateException(
+ "Nitro reported an unexpected Fusion validation state "
+ + $"'{events.Current.Kind}'.",
+ requestId);
+ }
+ }
+
+ throw CreateEndedEarly(requestId);
+ }
+
+ private static async Task WaitForTerminalPublishAsync(
+ IAsyncEnumerator events,
+ string requestId,
+ CancellationTokenSource timeout,
+ TimeSpan approvalTimeout,
+ CancellationToken cancellationToken)
+ {
+ while (await MoveNextAsync(events, requestId, cancellationToken))
+ {
+ switch (events.Current.Kind)
+ {
+ case FusionRemoteEventKind.PublishingSucceeded:
+ return;
+ case FusionRemoteEventKind.PublishingFailed:
+ throw CreateRemoteFailure(
+ "The Fusion publication failed.",
+ events.Current.Errors);
+ case FusionRemoteEventKind.WaitingForApproval:
+ timeout.CancelAfter(approvalTimeout);
+ continue;
+ case FusionRemoteEventKind.Approved:
+ case FusionRemoteEventKind.InProgress:
+ case FusionRemoteEventKind.ValidationSucceeded:
+ continue;
+ default:
+ throw new FusionIndeterminateStateException(
+ "Nitro reported an unexpected Fusion publishing state "
+ + $"'{events.Current.Kind}'.",
+ requestId);
+ }
+ }
+
+ throw CreateEndedEarly(requestId);
+ }
+
+ private static async Task MoveNextAsync(
+ IAsyncEnumerator events,
+ string requestId,
+ CancellationToken cancellationToken)
+ {
+ try
+ {
+ var hasNext = await events.MoveNextAsync();
+ cancellationToken.ThrowIfCancellationRequested();
+ return hasNext;
+ }
+ catch (OperationCanceledException)
+ {
+ throw;
+ }
+ catch (Exception exception)
+ {
+ throw new FusionIndeterminateStateException(
+ "The Fusion publication event stream ended with an error.",
+ exception,
+ requestId);
+ }
+ }
+
+ private static async Task EnsureRemoteCommandSucceededAsync(
+ Func> command,
+ string operation,
+ string requestId)
+ {
+ FusionRemoteCommandResult result;
+ try
+ {
+ result = await command();
+ }
+ catch (OperationCanceledException)
+ {
+ throw;
+ }
+ catch (Exception exception)
+ {
+ throw new FusionIndeterminateStateException(
+ $"Nitro may have completed the operation to {operation}, but "
+ + "its result could not be verified.",
+ exception,
+ requestId);
+ }
+
+ if (!result.Succeeded)
+ {
+ throw new FusionIndeterminateStateException(
+ $"Nitro could not {operation}: "
+ + FormatErrors(result.Errors),
+ requestId);
+ }
+ }
+
+ private static async Task ReleaseKnownFailedValidationAsync(
+ IFusionDeploymentTransport transport,
+ string requestId,
+ CancellationToken cancellationToken)
+ {
+ var result = await transport.ReleasePublishAsync(
+ requestId,
+ cancellationToken);
+ if (!result.Succeeded)
+ {
+ throw new FusionIndeterminateStateException(
+ "The failed Fusion validation was known, but its publication "
+ + "slot could not be released: "
+ + FormatErrors(result.Errors),
+ requestId);
+ }
+ }
+
+ private static FusionIndeterminateStateException CreateEndedEarly(
+ string requestId)
+ => new(
+ "The Fusion publication event stream ended before Nitro reported "
+ + "a terminal result.",
+ requestId);
+
+ private static FusionDeploymentException CreateRemoteFailure(
+ string message,
+ IReadOnlyList errors)
+ => new($"{message} {FormatErrors(errors)}");
+
+ private static string FormatErrors(IReadOnlyList errors)
+ => errors.Count is 0
+ ? "Nitro returned no error details."
+ : string.Join(" ", errors);
+
+ private static void ValidateTarget(FusionTarget target)
+ {
+ ArgumentNullException.ThrowIfNull(target);
+ if (!target.CloudUrl.IsAbsoluteUri)
+ {
+ throw new ArgumentException(
+ "The Nitro cloud URL must be absolute.",
+ nameof(target));
+ }
+
+ ArgumentException.ThrowIfNullOrWhiteSpace(target.ApiId);
+ ArgumentException.ThrowIfNullOrWhiteSpace(target.ApiKey);
+ }
+
+ private static void ValidateSource(FusionSourceSchemaUpload source)
+ {
+ ArgumentNullException.ThrowIfNull(source);
+ ArgumentException.ThrowIfNullOrWhiteSpace(source.Name);
+ ArgumentException.ThrowIfNullOrWhiteSpace(source.Version);
+ ArgumentException.ThrowIfNullOrWhiteSpace(source.ArchivePath);
+ ArgumentException.ThrowIfNullOrWhiteSpace(source.Sha256);
+ if (!File.Exists(source.ArchivePath))
+ {
+ throw new FileNotFoundException(
+ "The Fusion source schema archive does not exist.",
+ source.ArchivePath);
+ }
+ }
+
+ private static void ValidatePublication(
+ FusionPublicationRequest request,
+ string fusionArchivePath)
+ {
+ ArgumentNullException.ThrowIfNull(request);
+ ValidateTarget(request.Target);
+ ArgumentException.ThrowIfNullOrWhiteSpace(request.Stage);
+ ArgumentException.ThrowIfNullOrWhiteSpace(request.ConfigurationTag);
+ ArgumentException.ThrowIfNullOrWhiteSpace(fusionArchivePath);
+ ArgumentNullException.ThrowIfNull(request.SourceSchemas);
+
+ if (request.SourceSchemas.Count is 0)
+ {
+ throw new ArgumentException(
+ "At least one source schema version must be selected.",
+ nameof(request));
+ }
+
+ foreach (var source in request.SourceSchemas)
+ {
+ ArgumentNullException.ThrowIfNull(source);
+ ArgumentException.ThrowIfNullOrWhiteSpace(source.Name);
+ ArgumentException.ThrowIfNullOrWhiteSpace(source.Version);
+ }
+
+ if (request.SourceSchemas
+ .GroupBy(source => source.Name, StringComparer.Ordinal)
+ .Any(group => group.Count() > 1))
+ {
+ throw new ArgumentException(
+ "A source schema may only be selected once.",
+ nameof(request));
+ }
+
+ if (request.OperationTimeout <= TimeSpan.Zero)
+ {
+ throw new ArgumentOutOfRangeException(
+ nameof(request),
+ "The operation timeout must be greater than zero.");
+ }
+
+ if (request.ApprovalTimeout <= TimeSpan.Zero)
+ {
+ throw new ArgumentOutOfRangeException(
+ nameof(request),
+ "The approval timeout must be greater than zero.");
+ }
+
+ if (!File.Exists(fusionArchivePath))
+ {
+ throw new FileNotFoundException(
+ "The Fusion configuration archive does not exist.",
+ fusionArchivePath);
+ }
+
+ if (new FileInfo(fusionArchivePath).Length is 0)
+ {
+ throw new FusionDeploymentException(
+ "The Fusion configuration archive is empty.");
+ }
+ }
+
+ private sealed record FusionValidationResult(
+ bool Succeeded,
+ IReadOnlyList Errors);
+
+ private enum PublishWaitResult
+ {
+ Ready,
+ Succeeded
+ }
+}
diff --git a/src/Nitro/Common/src/ChilliCream.Nitro.Fusion/FusionIdentityCollisionException.cs b/src/Nitro/Common/src/ChilliCream.Nitro.Fusion/FusionIdentityCollisionException.cs
new file mode 100644
index 00000000000..ab12e8eb981
--- /dev/null
+++ b/src/Nitro/Common/src/ChilliCream.Nitro.Fusion/FusionIdentityCollisionException.cs
@@ -0,0 +1,12 @@
+namespace ChilliCream.Nitro.Fusion;
+
+///
+/// A source schema name and version already exist with different content.
+///
+public sealed class FusionIdentityCollisionException : FusionDeploymentException
+{
+ public FusionIdentityCollisionException(string message)
+ : base(message)
+ {
+ }
+}
diff --git a/src/Nitro/Common/src/ChilliCream.Nitro.Fusion/FusionIndeterminateStateException.cs b/src/Nitro/Common/src/ChilliCream.Nitro.Fusion/FusionIndeterminateStateException.cs
new file mode 100644
index 00000000000..fff49777d30
--- /dev/null
+++ b/src/Nitro/Common/src/ChilliCream.Nitro.Fusion/FusionIndeterminateStateException.cs
@@ -0,0 +1,27 @@
+namespace ChilliCream.Nitro.Fusion;
+
+///
+/// A remote operation may have changed state, but its result could not be verified.
+///
+public sealed class FusionIndeterminateStateException : FusionDeploymentException
+{
+ public FusionIndeterminateStateException(string message, string? requestId = null)
+ : base(message)
+ {
+ RequestId = requestId;
+ }
+
+ public FusionIndeterminateStateException(
+ string message,
+ Exception innerException,
+ string? requestId = null)
+ : base(message, innerException)
+ {
+ RequestId = requestId;
+ }
+
+ ///
+ /// Gets the remote publication request identifier when one is known.
+ ///
+ public string? RequestId { get; }
+}
diff --git a/src/Nitro/Common/src/ChilliCream.Nitro.Fusion/FusionPublicationRequest.cs b/src/Nitro/Common/src/ChilliCream.Nitro.Fusion/FusionPublicationRequest.cs
new file mode 100644
index 00000000000..f0eb321f6c3
--- /dev/null
+++ b/src/Nitro/Common/src/ChilliCream.Nitro.Fusion/FusionPublicationRequest.cs
@@ -0,0 +1,14 @@
+namespace ChilliCream.Nitro.Fusion;
+
+///
+/// Describes a Fusion configuration publication.
+///
+public sealed record FusionPublicationRequest(
+ FusionTarget Target,
+ string Stage,
+ string ConfigurationTag,
+ IReadOnlyList SourceSchemas,
+ bool WaitForApproval,
+ bool Force,
+ TimeSpan OperationTimeout,
+ TimeSpan ApprovalTimeout);
diff --git a/src/Nitro/Common/src/ChilliCream.Nitro.Fusion/FusionSourceSchemaUpload.cs b/src/Nitro/Common/src/ChilliCream.Nitro.Fusion/FusionSourceSchemaUpload.cs
new file mode 100644
index 00000000000..a06cd096c9a
--- /dev/null
+++ b/src/Nitro/Common/src/ChilliCream.Nitro.Fusion/FusionSourceSchemaUpload.cs
@@ -0,0 +1,10 @@
+namespace ChilliCream.Nitro.Fusion;
+
+///
+/// Describes an immutable Fusion source schema archive to reconcile.
+///
+public sealed record FusionSourceSchemaUpload(
+ string Name,
+ string Version,
+ string ArchivePath,
+ string Sha256);
diff --git a/src/Nitro/Common/src/ChilliCream.Nitro.Fusion/FusionSourceSchemaVersion.cs b/src/Nitro/Common/src/ChilliCream.Nitro.Fusion/FusionSourceSchemaVersion.cs
new file mode 100644
index 00000000000..2f3c8ebf331
--- /dev/null
+++ b/src/Nitro/Common/src/ChilliCream.Nitro.Fusion/FusionSourceSchemaVersion.cs
@@ -0,0 +1,6 @@
+namespace ChilliCream.Nitro.Fusion;
+
+///
+/// Selects one immutable source schema version for a Fusion publication.
+///
+public sealed record FusionSourceSchemaVersion(string Name, string Version);
diff --git a/src/Nitro/Common/src/ChilliCream.Nitro.Fusion/FusionTarget.cs b/src/Nitro/Common/src/ChilliCream.Nitro.Fusion/FusionTarget.cs
new file mode 100644
index 00000000000..cddc1edc94b
--- /dev/null
+++ b/src/Nitro/Common/src/ChilliCream.Nitro.Fusion/FusionTarget.cs
@@ -0,0 +1,10 @@
+namespace ChilliCream.Nitro.Fusion;
+
+///
+/// Identifies a Nitro API and the credentials used to access it.
+///
+public sealed record FusionTarget(Uri CloudUrl, string ApiId, string ApiKey)
+{
+ ///
+ public override string ToString() => $"{CloudUrl} (API {ApiId})";
+}
diff --git a/src/Nitro/Common/src/ChilliCream.Nitro.Fusion/Generated/FusionApiClient.Client.cs b/src/Nitro/Common/src/ChilliCream.Nitro.Fusion/Generated/FusionApiClient.Client.cs
new file mode 100644
index 00000000000..1c881506ba9
--- /dev/null
+++ b/src/Nitro/Common/src/ChilliCream.Nitro.Fusion/Generated/FusionApiClient.Client.cs
@@ -0,0 +1,11092 @@
+//
+#nullable enable annotations
+#nullable disable warnings
+
+namespace ChilliCream.Nitro.Fusion.Transport
+{
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class UploadFusionSourceSchemaResult : global::System.IEquatable, IUploadFusionSourceSchemaResult
+ {
+ public UploadFusionSourceSchemaResult(global::ChilliCream.Nitro.Fusion.Transport.IUploadFusionSourceSchema_UploadFusionSubgraph uploadFusionSubgraph)
+ {
+ UploadFusionSubgraph = uploadFusionSubgraph;
+ }
+
+ public global::ChilliCream.Nitro.Fusion.Transport.IUploadFusionSourceSchema_UploadFusionSubgraph UploadFusionSubgraph { get; }
+
+ public virtual global::System.Boolean Equals(UploadFusionSourceSchemaResult? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (UploadFusionSubgraph.Equals(other.UploadFusionSubgraph));
+ }
+
+ public override global::System.Boolean Equals(global::System.Object? obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((UploadFusionSourceSchemaResult)obj);
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ hash ^= 397 * UploadFusionSubgraph.GetHashCode();
+ return hash;
+ }
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class UploadFusionSourceSchema_UploadFusionSubgraph_UploadFusionSubgraphPayload : global::System.IEquatable, IUploadFusionSourceSchema_UploadFusionSubgraph_UploadFusionSubgraphPayload
+ {
+ public UploadFusionSourceSchema_UploadFusionSubgraph_UploadFusionSubgraphPayload(global::ChilliCream.Nitro.Fusion.Transport.IUploadFusionSourceSchema_UploadFusionSubgraph_FusionSubgraphVersion? fusionSubgraphVersion, global::System.Collections.Generic.IReadOnlyList? errors)
+ {
+ FusionSubgraphVersion = fusionSubgraphVersion;
+ Errors = errors;
+ }
+
+ public global::ChilliCream.Nitro.Fusion.Transport.IUploadFusionSourceSchema_UploadFusionSubgraph_FusionSubgraphVersion? FusionSubgraphVersion { get; }
+ public global::System.Collections.Generic.IReadOnlyList? Errors { get; }
+
+ public virtual global::System.Boolean Equals(UploadFusionSourceSchema_UploadFusionSubgraph_UploadFusionSubgraphPayload? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (((FusionSubgraphVersion is null && other.FusionSubgraphVersion is null) || FusionSubgraphVersion != null && FusionSubgraphVersion.Equals(other.FusionSubgraphVersion))) && global::StrawberryShake.Internal.ComparisonHelper.SequenceEqual(Errors, other.Errors);
+ }
+
+ public override global::System.Boolean Equals(global::System.Object? obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((UploadFusionSourceSchema_UploadFusionSubgraph_UploadFusionSubgraphPayload)obj);
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ if (FusionSubgraphVersion != null)
+ {
+ hash ^= 397 * FusionSubgraphVersion.GetHashCode();
+ }
+
+ if (Errors != null)
+ {
+ foreach (var Errors_elm in Errors)
+ {
+ hash ^= 397 * Errors_elm.GetHashCode();
+ }
+ }
+
+ return hash;
+ }
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class UploadFusionSourceSchema_UploadFusionSubgraph_FusionSubgraphVersion_FusionSubgraphVersion : global::System.IEquatable, IUploadFusionSourceSchema_UploadFusionSubgraph_FusionSubgraphVersion_FusionSubgraphVersion
+ {
+ public UploadFusionSourceSchema_UploadFusionSubgraph_FusionSubgraphVersion_FusionSubgraphVersion(global::System.String id)
+ {
+ Id = id;
+ }
+
+ public global::System.String Id { get; }
+
+ public virtual global::System.Boolean Equals(UploadFusionSourceSchema_UploadFusionSubgraph_FusionSubgraphVersion_FusionSubgraphVersion? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (Id.Equals(other.Id));
+ }
+
+ public override global::System.Boolean Equals(global::System.Object? obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((UploadFusionSourceSchema_UploadFusionSubgraph_FusionSubgraphVersion_FusionSubgraphVersion)obj);
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ hash ^= 397 * Id.GetHashCode();
+ return hash;
+ }
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class UploadFusionSourceSchema_UploadFusionSubgraph_Errors_InvalidFusionSourceSchemaArchiveError : global::System.IEquatable, IUploadFusionSourceSchema_UploadFusionSubgraph_Errors_InvalidFusionSourceSchemaArchiveError
+ {
+ public UploadFusionSourceSchema_UploadFusionSubgraph_Errors_InvalidFusionSourceSchemaArchiveError(global::System.String __typename, global::System.String message)
+ {
+ this.__typename = __typename;
+ Message = message;
+ }
+
+ ///
+ /// The name of the current Object type at runtime.
+ ///
+ public global::System.String __typename { get; }
+ public global::System.String Message { get; }
+
+ public virtual global::System.Boolean Equals(UploadFusionSourceSchema_UploadFusionSubgraph_Errors_InvalidFusionSourceSchemaArchiveError? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (__typename.Equals(other.__typename)) && Message.Equals(other.Message);
+ }
+
+ public override global::System.Boolean Equals(global::System.Object? obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((UploadFusionSourceSchema_UploadFusionSubgraph_Errors_InvalidFusionSourceSchemaArchiveError)obj);
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ hash ^= 397 * __typename.GetHashCode();
+ hash ^= 397 * Message.GetHashCode();
+ return hash;
+ }
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class UploadFusionSourceSchema_UploadFusionSubgraph_Errors_ApiNotFoundError : global::System.IEquatable, IUploadFusionSourceSchema_UploadFusionSubgraph_Errors_ApiNotFoundError
+ {
+ public UploadFusionSourceSchema_UploadFusionSubgraph_Errors_ApiNotFoundError(global::System.String __typename, global::System.String message)
+ {
+ this.__typename = __typename;
+ Message = message;
+ }
+
+ ///
+ /// The name of the current Object type at runtime.
+ ///
+ public global::System.String __typename { get; }
+ public global::System.String Message { get; }
+
+ public virtual global::System.Boolean Equals(UploadFusionSourceSchema_UploadFusionSubgraph_Errors_ApiNotFoundError? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (__typename.Equals(other.__typename)) && Message.Equals(other.Message);
+ }
+
+ public override global::System.Boolean Equals(global::System.Object? obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((UploadFusionSourceSchema_UploadFusionSubgraph_Errors_ApiNotFoundError)obj);
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ hash ^= 397 * __typename.GetHashCode();
+ hash ^= 397 * Message.GetHashCode();
+ return hash;
+ }
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class UploadFusionSourceSchema_UploadFusionSubgraph_Errors_ConcurrentOperationError : global::System.IEquatable, IUploadFusionSourceSchema_UploadFusionSubgraph_Errors_ConcurrentOperationError
+ {
+ public UploadFusionSourceSchema_UploadFusionSubgraph_Errors_ConcurrentOperationError(global::System.String __typename, global::System.String message)
+ {
+ this.__typename = __typename;
+ Message = message;
+ }
+
+ ///
+ /// The name of the current Object type at runtime.
+ ///
+ public global::System.String __typename { get; }
+ public global::System.String Message { get; }
+
+ public virtual global::System.Boolean Equals(UploadFusionSourceSchema_UploadFusionSubgraph_Errors_ConcurrentOperationError? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (__typename.Equals(other.__typename)) && Message.Equals(other.Message);
+ }
+
+ public override global::System.Boolean Equals(global::System.Object? obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((UploadFusionSourceSchema_UploadFusionSubgraph_Errors_ConcurrentOperationError)obj);
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ hash ^= 397 * __typename.GetHashCode();
+ hash ^= 397 * Message.GetHashCode();
+ return hash;
+ }
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class UploadFusionSourceSchema_UploadFusionSubgraph_Errors_UnauthorizedOperation : global::System.IEquatable, IUploadFusionSourceSchema_UploadFusionSubgraph_Errors_UnauthorizedOperation
+ {
+ public UploadFusionSourceSchema_UploadFusionSubgraph_Errors_UnauthorizedOperation(global::System.String __typename, global::System.String message)
+ {
+ this.__typename = __typename;
+ Message = message;
+ }
+
+ ///
+ /// The name of the current Object type at runtime.
+ ///
+ public global::System.String __typename { get; }
+ public global::System.String Message { get; }
+
+ public virtual global::System.Boolean Equals(UploadFusionSourceSchema_UploadFusionSubgraph_Errors_UnauthorizedOperation? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (__typename.Equals(other.__typename)) && Message.Equals(other.Message);
+ }
+
+ public override global::System.Boolean Equals(global::System.Object? obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((UploadFusionSourceSchema_UploadFusionSubgraph_Errors_UnauthorizedOperation)obj);
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ hash ^= 397 * __typename.GetHashCode();
+ hash ^= 397 * Message.GetHashCode();
+ return hash;
+ }
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class UploadFusionSourceSchema_UploadFusionSubgraph_Errors_DuplicatedTagError : global::System.IEquatable, IUploadFusionSourceSchema_UploadFusionSubgraph_Errors_DuplicatedTagError
+ {
+ public UploadFusionSourceSchema_UploadFusionSubgraph_Errors_DuplicatedTagError(global::System.String __typename, global::System.String message)
+ {
+ this.__typename = __typename;
+ Message = message;
+ }
+
+ ///
+ /// The name of the current Object type at runtime.
+ ///
+ public global::System.String __typename { get; }
+ public global::System.String Message { get; }
+
+ public virtual global::System.Boolean Equals(UploadFusionSourceSchema_UploadFusionSubgraph_Errors_DuplicatedTagError? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (__typename.Equals(other.__typename)) && Message.Equals(other.Message);
+ }
+
+ public override global::System.Boolean Equals(global::System.Object? obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((UploadFusionSourceSchema_UploadFusionSubgraph_Errors_DuplicatedTagError)obj);
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ hash ^= 397 * __typename.GetHashCode();
+ hash ^= 397 * Message.GetHashCode();
+ return hash;
+ }
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class UploadFusionSourceSchema_UploadFusionSubgraph_Errors_InvalidSourceMetadataInputError : global::System.IEquatable, IUploadFusionSourceSchema_UploadFusionSubgraph_Errors_InvalidSourceMetadataInputError
+ {
+ public UploadFusionSourceSchema_UploadFusionSubgraph_Errors_InvalidSourceMetadataInputError(global::System.String __typename, global::System.String message)
+ {
+ this.__typename = __typename;
+ Message = message;
+ }
+
+ ///
+ /// The name of the current Object type at runtime.
+ ///
+ public global::System.String __typename { get; }
+ public global::System.String Message { get; }
+
+ public virtual global::System.Boolean Equals(UploadFusionSourceSchema_UploadFusionSubgraph_Errors_InvalidSourceMetadataInputError? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (__typename.Equals(other.__typename)) && Message.Equals(other.Message);
+ }
+
+ public override global::System.Boolean Equals(global::System.Object? obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((UploadFusionSourceSchema_UploadFusionSubgraph_Errors_InvalidSourceMetadataInputError)obj);
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ hash ^= 397 * __typename.GetHashCode();
+ hash ^= 397 * Message.GetHashCode();
+ return hash;
+ }
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IUploadFusionSourceSchemaResult
+ {
+ public global::ChilliCream.Nitro.Fusion.Transport.IUploadFusionSourceSchema_UploadFusionSubgraph UploadFusionSubgraph { get; }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IUploadFusionSourceSchema_UploadFusionSubgraph
+ {
+ public global::ChilliCream.Nitro.Fusion.Transport.IUploadFusionSourceSchema_UploadFusionSubgraph_FusionSubgraphVersion? FusionSubgraphVersion { get; }
+ public global::System.Collections.Generic.IReadOnlyList? Errors { get; }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IUploadFusionSourceSchema_UploadFusionSubgraph_UploadFusionSubgraphPayload : IUploadFusionSourceSchema_UploadFusionSubgraph
+ {
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IUploadFusionSourceSchema_UploadFusionSubgraph_FusionSubgraphVersion
+ {
+ public global::System.String Id { get; }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IUploadFusionSourceSchema_UploadFusionSubgraph_FusionSubgraphVersion_FusionSubgraphVersion : IUploadFusionSourceSchema_UploadFusionSubgraph_FusionSubgraphVersion
+ {
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IUploadFusionSourceSchema_UploadFusionSubgraph_Errors
+ {
+ public global::System.String __typename { get; }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IFusionError
+ {
+ public global::System.String Message { get; }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IUploadFusionSourceSchema_UploadFusionSubgraph_Errors_InvalidFusionSourceSchemaArchiveError : IUploadFusionSourceSchema_UploadFusionSubgraph_Errors, IFusionError
+ {
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IUploadFusionSourceSchema_UploadFusionSubgraph_Errors_ApiNotFoundError : IUploadFusionSourceSchema_UploadFusionSubgraph_Errors, IFusionError
+ {
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IUploadFusionSourceSchema_UploadFusionSubgraph_Errors_ConcurrentOperationError : IUploadFusionSourceSchema_UploadFusionSubgraph_Errors, IFusionError
+ {
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IUploadFusionSourceSchema_UploadFusionSubgraph_Errors_UnauthorizedOperation : IUploadFusionSourceSchema_UploadFusionSubgraph_Errors, IFusionError
+ {
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IUploadFusionSourceSchema_UploadFusionSubgraph_Errors_DuplicatedTagError : IUploadFusionSourceSchema_UploadFusionSubgraph_Errors, IFusionError
+ {
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IUploadFusionSourceSchema_UploadFusionSubgraph_Errors_InvalidSourceMetadataInputError : IUploadFusionSourceSchema_UploadFusionSubgraph_Errors, IFusionError
+ {
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class BeginFusionDeploymentResult : global::System.IEquatable, IBeginFusionDeploymentResult
+ {
+ public BeginFusionDeploymentResult(global::ChilliCream.Nitro.Fusion.Transport.IBeginFusionDeployment_BeginFusionConfigurationPublish beginFusionConfigurationPublish)
+ {
+ BeginFusionConfigurationPublish = beginFusionConfigurationPublish;
+ }
+
+ public global::ChilliCream.Nitro.Fusion.Transport.IBeginFusionDeployment_BeginFusionConfigurationPublish BeginFusionConfigurationPublish { get; }
+
+ public virtual global::System.Boolean Equals(BeginFusionDeploymentResult? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (BeginFusionConfigurationPublish.Equals(other.BeginFusionConfigurationPublish));
+ }
+
+ public override global::System.Boolean Equals(global::System.Object? obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((BeginFusionDeploymentResult)obj);
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ hash ^= 397 * BeginFusionConfigurationPublish.GetHashCode();
+ return hash;
+ }
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class BeginFusionDeployment_BeginFusionConfigurationPublish_BeginFusionConfigurationPublishPayload : global::System.IEquatable, IBeginFusionDeployment_BeginFusionConfigurationPublish_BeginFusionConfigurationPublishPayload
+ {
+ public BeginFusionDeployment_BeginFusionConfigurationPublish_BeginFusionConfigurationPublishPayload(global::System.String? requestId, global::System.Collections.Generic.IReadOnlyList? errors)
+ {
+ RequestId = requestId;
+ Errors = errors;
+ }
+
+ public global::System.String? RequestId { get; }
+ public global::System.Collections.Generic.IReadOnlyList? Errors { get; }
+
+ public virtual global::System.Boolean Equals(BeginFusionDeployment_BeginFusionConfigurationPublish_BeginFusionConfigurationPublishPayload? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (((RequestId is null && other.RequestId is null) || RequestId != null && RequestId.Equals(other.RequestId))) && global::StrawberryShake.Internal.ComparisonHelper.SequenceEqual(Errors, other.Errors);
+ }
+
+ public override global::System.Boolean Equals(global::System.Object? obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((BeginFusionDeployment_BeginFusionConfigurationPublish_BeginFusionConfigurationPublishPayload)obj);
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ if (RequestId != null)
+ {
+ hash ^= 397 * RequestId.GetHashCode();
+ }
+
+ if (Errors != null)
+ {
+ foreach (var Errors_elm in Errors)
+ {
+ hash ^= 397 * Errors_elm.GetHashCode();
+ }
+ }
+
+ return hash;
+ }
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class BeginFusionDeployment_BeginFusionConfigurationPublish_Errors_UnauthorizedOperation : global::System.IEquatable, IBeginFusionDeployment_BeginFusionConfigurationPublish_Errors_UnauthorizedOperation
+ {
+ public BeginFusionDeployment_BeginFusionConfigurationPublish_Errors_UnauthorizedOperation(global::System.String __typename, global::System.String message)
+ {
+ this.__typename = __typename;
+ Message = message;
+ }
+
+ ///
+ /// The name of the current Object type at runtime.
+ ///
+ public global::System.String __typename { get; }
+ public global::System.String Message { get; }
+
+ public virtual global::System.Boolean Equals(BeginFusionDeployment_BeginFusionConfigurationPublish_Errors_UnauthorizedOperation? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (__typename.Equals(other.__typename)) && Message.Equals(other.Message);
+ }
+
+ public override global::System.Boolean Equals(global::System.Object? obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((BeginFusionDeployment_BeginFusionConfigurationPublish_Errors_UnauthorizedOperation)obj);
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ hash ^= 397 * __typename.GetHashCode();
+ hash ^= 397 * Message.GetHashCode();
+ return hash;
+ }
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class BeginFusionDeployment_BeginFusionConfigurationPublish_Errors_ApiNotFoundError : global::System.IEquatable, IBeginFusionDeployment_BeginFusionConfigurationPublish_Errors_ApiNotFoundError
+ {
+ public BeginFusionDeployment_BeginFusionConfigurationPublish_Errors_ApiNotFoundError(global::System.String __typename, global::System.String message)
+ {
+ this.__typename = __typename;
+ Message = message;
+ }
+
+ ///
+ /// The name of the current Object type at runtime.
+ ///
+ public global::System.String __typename { get; }
+ public global::System.String Message { get; }
+
+ public virtual global::System.Boolean Equals(BeginFusionDeployment_BeginFusionConfigurationPublish_Errors_ApiNotFoundError? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (__typename.Equals(other.__typename)) && Message.Equals(other.Message);
+ }
+
+ public override global::System.Boolean Equals(global::System.Object? obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((BeginFusionDeployment_BeginFusionConfigurationPublish_Errors_ApiNotFoundError)obj);
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ hash ^= 397 * __typename.GetHashCode();
+ hash ^= 397 * Message.GetHashCode();
+ return hash;
+ }
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class BeginFusionDeployment_BeginFusionConfigurationPublish_Errors_StageNotFoundError : global::System.IEquatable, IBeginFusionDeployment_BeginFusionConfigurationPublish_Errors_StageNotFoundError
+ {
+ public BeginFusionDeployment_BeginFusionConfigurationPublish_Errors_StageNotFoundError(global::System.String __typename, global::System.String message)
+ {
+ this.__typename = __typename;
+ Message = message;
+ }
+
+ ///
+ /// The name of the current Object type at runtime.
+ ///
+ public global::System.String __typename { get; }
+ public global::System.String Message { get; }
+
+ public virtual global::System.Boolean Equals(BeginFusionDeployment_BeginFusionConfigurationPublish_Errors_StageNotFoundError? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (__typename.Equals(other.__typename)) && Message.Equals(other.Message);
+ }
+
+ public override global::System.Boolean Equals(global::System.Object? obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((BeginFusionDeployment_BeginFusionConfigurationPublish_Errors_StageNotFoundError)obj);
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ hash ^= 397 * __typename.GetHashCode();
+ hash ^= 397 * Message.GetHashCode();
+ return hash;
+ }
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class BeginFusionDeployment_BeginFusionConfigurationPublish_Errors_SubgraphInvalidError : global::System.IEquatable, IBeginFusionDeployment_BeginFusionConfigurationPublish_Errors_SubgraphInvalidError
+ {
+ public BeginFusionDeployment_BeginFusionConfigurationPublish_Errors_SubgraphInvalidError(global::System.String __typename, global::System.String message)
+ {
+ this.__typename = __typename;
+ Message = message;
+ }
+
+ ///
+ /// The name of the current Object type at runtime.
+ ///
+ public global::System.String __typename { get; }
+ public global::System.String Message { get; }
+
+ public virtual global::System.Boolean Equals(BeginFusionDeployment_BeginFusionConfigurationPublish_Errors_SubgraphInvalidError? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (__typename.Equals(other.__typename)) && Message.Equals(other.Message);
+ }
+
+ public override global::System.Boolean Equals(global::System.Object? obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((BeginFusionDeployment_BeginFusionConfigurationPublish_Errors_SubgraphInvalidError)obj);
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ hash ^= 397 * __typename.GetHashCode();
+ hash ^= 397 * Message.GetHashCode();
+ return hash;
+ }
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class BeginFusionDeployment_BeginFusionConfigurationPublish_Errors_InvalidProcessingStateTransitionError : global::System.IEquatable, IBeginFusionDeployment_BeginFusionConfigurationPublish_Errors_InvalidProcessingStateTransitionError
+ {
+ public BeginFusionDeployment_BeginFusionConfigurationPublish_Errors_InvalidProcessingStateTransitionError(global::System.String __typename, global::System.String message)
+ {
+ this.__typename = __typename;
+ Message = message;
+ }
+
+ ///
+ /// The name of the current Object type at runtime.
+ ///
+ public global::System.String __typename { get; }
+ public global::System.String Message { get; }
+
+ public virtual global::System.Boolean Equals(BeginFusionDeployment_BeginFusionConfigurationPublish_Errors_InvalidProcessingStateTransitionError? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (__typename.Equals(other.__typename)) && Message.Equals(other.Message);
+ }
+
+ public override global::System.Boolean Equals(global::System.Object? obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((BeginFusionDeployment_BeginFusionConfigurationPublish_Errors_InvalidProcessingStateTransitionError)obj);
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ hash ^= 397 * __typename.GetHashCode();
+ hash ^= 397 * Message.GetHashCode();
+ return hash;
+ }
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class BeginFusionDeployment_BeginFusionConfigurationPublish_Errors_InvalidSourceMetadataInputError : global::System.IEquatable, IBeginFusionDeployment_BeginFusionConfigurationPublish_Errors_InvalidSourceMetadataInputError
+ {
+ public BeginFusionDeployment_BeginFusionConfigurationPublish_Errors_InvalidSourceMetadataInputError(global::System.String __typename, global::System.String message)
+ {
+ this.__typename = __typename;
+ Message = message;
+ }
+
+ ///
+ /// The name of the current Object type at runtime.
+ ///
+ public global::System.String __typename { get; }
+ public global::System.String Message { get; }
+
+ public virtual global::System.Boolean Equals(BeginFusionDeployment_BeginFusionConfigurationPublish_Errors_InvalidSourceMetadataInputError? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (__typename.Equals(other.__typename)) && Message.Equals(other.Message);
+ }
+
+ public override global::System.Boolean Equals(global::System.Object? obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((BeginFusionDeployment_BeginFusionConfigurationPublish_Errors_InvalidSourceMetadataInputError)obj);
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ hash ^= 397 * __typename.GetHashCode();
+ hash ^= 397 * Message.GetHashCode();
+ return hash;
+ }
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IBeginFusionDeploymentResult
+ {
+ public global::ChilliCream.Nitro.Fusion.Transport.IBeginFusionDeployment_BeginFusionConfigurationPublish BeginFusionConfigurationPublish { get; }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IBeginFusionDeployment_BeginFusionConfigurationPublish
+ {
+ public global::System.String? RequestId { get; }
+ public global::System.Collections.Generic.IReadOnlyList? Errors { get; }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IBeginFusionDeployment_BeginFusionConfigurationPublish_BeginFusionConfigurationPublishPayload : IBeginFusionDeployment_BeginFusionConfigurationPublish
+ {
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IBeginFusionDeployment_BeginFusionConfigurationPublish_Errors
+ {
+ public global::System.String __typename { get; }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IBeginFusionDeployment_BeginFusionConfigurationPublish_Errors_UnauthorizedOperation : IBeginFusionDeployment_BeginFusionConfigurationPublish_Errors, IFusionError
+ {
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IBeginFusionDeployment_BeginFusionConfigurationPublish_Errors_ApiNotFoundError : IBeginFusionDeployment_BeginFusionConfigurationPublish_Errors, IFusionError
+ {
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IBeginFusionDeployment_BeginFusionConfigurationPublish_Errors_StageNotFoundError : IBeginFusionDeployment_BeginFusionConfigurationPublish_Errors, IFusionError
+ {
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IBeginFusionDeployment_BeginFusionConfigurationPublish_Errors_SubgraphInvalidError : IBeginFusionDeployment_BeginFusionConfigurationPublish_Errors, IFusionError
+ {
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IBeginFusionDeployment_BeginFusionConfigurationPublish_Errors_InvalidProcessingStateTransitionError : IBeginFusionDeployment_BeginFusionConfigurationPublish_Errors, IFusionError
+ {
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IBeginFusionDeployment_BeginFusionConfigurationPublish_Errors_InvalidSourceMetadataInputError : IBeginFusionDeployment_BeginFusionConfigurationPublish_Errors, IFusionError
+ {
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class ClaimFusionDeploymentResult : global::System.IEquatable, IClaimFusionDeploymentResult
+ {
+ public ClaimFusionDeploymentResult(global::ChilliCream.Nitro.Fusion.Transport.IClaimFusionDeployment_StartFusionConfigurationComposition startFusionConfigurationComposition)
+ {
+ StartFusionConfigurationComposition = startFusionConfigurationComposition;
+ }
+
+ public global::ChilliCream.Nitro.Fusion.Transport.IClaimFusionDeployment_StartFusionConfigurationComposition StartFusionConfigurationComposition { get; }
+
+ public virtual global::System.Boolean Equals(ClaimFusionDeploymentResult? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (StartFusionConfigurationComposition.Equals(other.StartFusionConfigurationComposition));
+ }
+
+ public override global::System.Boolean Equals(global::System.Object? obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((ClaimFusionDeploymentResult)obj);
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ hash ^= 397 * StartFusionConfigurationComposition.GetHashCode();
+ return hash;
+ }
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class ClaimFusionDeployment_StartFusionConfigurationComposition_StartFusionConfigurationCompositionPayload : global::System.IEquatable, IClaimFusionDeployment_StartFusionConfigurationComposition_StartFusionConfigurationCompositionPayload
+ {
+ public ClaimFusionDeployment_StartFusionConfigurationComposition_StartFusionConfigurationCompositionPayload(global::System.Collections.Generic.IReadOnlyList? errors)
+ {
+ Errors = errors;
+ }
+
+ public global::System.Collections.Generic.IReadOnlyList? Errors { get; }
+
+ public virtual global::System.Boolean Equals(ClaimFusionDeployment_StartFusionConfigurationComposition_StartFusionConfigurationCompositionPayload? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (global::StrawberryShake.Internal.ComparisonHelper.SequenceEqual(Errors, other.Errors));
+ }
+
+ public override global::System.Boolean Equals(global::System.Object? obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((ClaimFusionDeployment_StartFusionConfigurationComposition_StartFusionConfigurationCompositionPayload)obj);
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ if (Errors != null)
+ {
+ foreach (var Errors_elm in Errors)
+ {
+ hash ^= 397 * Errors_elm.GetHashCode();
+ }
+ }
+
+ return hash;
+ }
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class ClaimFusionDeployment_StartFusionConfigurationComposition_Errors_UnauthorizedOperation : global::System.IEquatable, IClaimFusionDeployment_StartFusionConfigurationComposition_Errors_UnauthorizedOperation
+ {
+ public ClaimFusionDeployment_StartFusionConfigurationComposition_Errors_UnauthorizedOperation(global::System.String __typename, global::System.String message)
+ {
+ this.__typename = __typename;
+ Message = message;
+ }
+
+ ///
+ /// The name of the current Object type at runtime.
+ ///
+ public global::System.String __typename { get; }
+ public global::System.String Message { get; }
+
+ public virtual global::System.Boolean Equals(ClaimFusionDeployment_StartFusionConfigurationComposition_Errors_UnauthorizedOperation? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (__typename.Equals(other.__typename)) && Message.Equals(other.Message);
+ }
+
+ public override global::System.Boolean Equals(global::System.Object? obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((ClaimFusionDeployment_StartFusionConfigurationComposition_Errors_UnauthorizedOperation)obj);
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ hash ^= 397 * __typename.GetHashCode();
+ hash ^= 397 * Message.GetHashCode();
+ return hash;
+ }
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class ClaimFusionDeployment_StartFusionConfigurationComposition_Errors_FusionConfigurationRequestNotFoundError : global::System.IEquatable, IClaimFusionDeployment_StartFusionConfigurationComposition_Errors_FusionConfigurationRequestNotFoundError
+ {
+ public ClaimFusionDeployment_StartFusionConfigurationComposition_Errors_FusionConfigurationRequestNotFoundError(global::System.String __typename, global::System.String message)
+ {
+ this.__typename = __typename;
+ Message = message;
+ }
+
+ ///
+ /// The name of the current Object type at runtime.
+ ///
+ public global::System.String __typename { get; }
+ public global::System.String Message { get; }
+
+ public virtual global::System.Boolean Equals(ClaimFusionDeployment_StartFusionConfigurationComposition_Errors_FusionConfigurationRequestNotFoundError? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (__typename.Equals(other.__typename)) && Message.Equals(other.Message);
+ }
+
+ public override global::System.Boolean Equals(global::System.Object? obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((ClaimFusionDeployment_StartFusionConfigurationComposition_Errors_FusionConfigurationRequestNotFoundError)obj);
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ hash ^= 397 * __typename.GetHashCode();
+ hash ^= 397 * Message.GetHashCode();
+ return hash;
+ }
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class ClaimFusionDeployment_StartFusionConfigurationComposition_Errors_InvalidProcessingStateTransitionError : global::System.IEquatable, IClaimFusionDeployment_StartFusionConfigurationComposition_Errors_InvalidProcessingStateTransitionError
+ {
+ public ClaimFusionDeployment_StartFusionConfigurationComposition_Errors_InvalidProcessingStateTransitionError(global::System.String __typename, global::System.String message)
+ {
+ this.__typename = __typename;
+ Message = message;
+ }
+
+ ///
+ /// The name of the current Object type at runtime.
+ ///
+ public global::System.String __typename { get; }
+ public global::System.String Message { get; }
+
+ public virtual global::System.Boolean Equals(ClaimFusionDeployment_StartFusionConfigurationComposition_Errors_InvalidProcessingStateTransitionError? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (__typename.Equals(other.__typename)) && Message.Equals(other.Message);
+ }
+
+ public override global::System.Boolean Equals(global::System.Object? obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((ClaimFusionDeployment_StartFusionConfigurationComposition_Errors_InvalidProcessingStateTransitionError)obj);
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ hash ^= 397 * __typename.GetHashCode();
+ hash ^= 397 * Message.GetHashCode();
+ return hash;
+ }
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IClaimFusionDeploymentResult
+ {
+ public global::ChilliCream.Nitro.Fusion.Transport.IClaimFusionDeployment_StartFusionConfigurationComposition StartFusionConfigurationComposition { get; }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IClaimFusionDeployment_StartFusionConfigurationComposition
+ {
+ public global::System.Collections.Generic.IReadOnlyList? Errors { get; }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IClaimFusionDeployment_StartFusionConfigurationComposition_StartFusionConfigurationCompositionPayload : IClaimFusionDeployment_StartFusionConfigurationComposition
+ {
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IClaimFusionDeployment_StartFusionConfigurationComposition_Errors
+ {
+ public global::System.String __typename { get; }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IClaimFusionDeployment_StartFusionConfigurationComposition_Errors_UnauthorizedOperation : IClaimFusionDeployment_StartFusionConfigurationComposition_Errors, IFusionError
+ {
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IClaimFusionDeployment_StartFusionConfigurationComposition_Errors_FusionConfigurationRequestNotFoundError : IClaimFusionDeployment_StartFusionConfigurationComposition_Errors, IFusionError
+ {
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IClaimFusionDeployment_StartFusionConfigurationComposition_Errors_InvalidProcessingStateTransitionError : IClaimFusionDeployment_StartFusionConfigurationComposition_Errors, IFusionError
+ {
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class ReleaseFusionDeploymentResult : global::System.IEquatable, IReleaseFusionDeploymentResult
+ {
+ public ReleaseFusionDeploymentResult(global::ChilliCream.Nitro.Fusion.Transport.IReleaseFusionDeployment_CancelFusionConfigurationComposition cancelFusionConfigurationComposition)
+ {
+ CancelFusionConfigurationComposition = cancelFusionConfigurationComposition;
+ }
+
+ public global::ChilliCream.Nitro.Fusion.Transport.IReleaseFusionDeployment_CancelFusionConfigurationComposition CancelFusionConfigurationComposition { get; }
+
+ public virtual global::System.Boolean Equals(ReleaseFusionDeploymentResult? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (CancelFusionConfigurationComposition.Equals(other.CancelFusionConfigurationComposition));
+ }
+
+ public override global::System.Boolean Equals(global::System.Object? obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((ReleaseFusionDeploymentResult)obj);
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ hash ^= 397 * CancelFusionConfigurationComposition.GetHashCode();
+ return hash;
+ }
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class ReleaseFusionDeployment_CancelFusionConfigurationComposition_CancelFusionConfigurationCompositionPayload : global::System.IEquatable, IReleaseFusionDeployment_CancelFusionConfigurationComposition_CancelFusionConfigurationCompositionPayload
+ {
+ public ReleaseFusionDeployment_CancelFusionConfigurationComposition_CancelFusionConfigurationCompositionPayload(global::System.Collections.Generic.IReadOnlyList? errors)
+ {
+ Errors = errors;
+ }
+
+ public global::System.Collections.Generic.IReadOnlyList? Errors { get; }
+
+ public virtual global::System.Boolean Equals(ReleaseFusionDeployment_CancelFusionConfigurationComposition_CancelFusionConfigurationCompositionPayload? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (global::StrawberryShake.Internal.ComparisonHelper.SequenceEqual(Errors, other.Errors));
+ }
+
+ public override global::System.Boolean Equals(global::System.Object? obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((ReleaseFusionDeployment_CancelFusionConfigurationComposition_CancelFusionConfigurationCompositionPayload)obj);
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ if (Errors != null)
+ {
+ foreach (var Errors_elm in Errors)
+ {
+ hash ^= 397 * Errors_elm.GetHashCode();
+ }
+ }
+
+ return hash;
+ }
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class ReleaseFusionDeployment_CancelFusionConfigurationComposition_Errors_UnauthorizedOperation : global::System.IEquatable, IReleaseFusionDeployment_CancelFusionConfigurationComposition_Errors_UnauthorizedOperation
+ {
+ public ReleaseFusionDeployment_CancelFusionConfigurationComposition_Errors_UnauthorizedOperation(global::System.String __typename, global::System.String message)
+ {
+ this.__typename = __typename;
+ Message = message;
+ }
+
+ ///
+ /// The name of the current Object type at runtime.
+ ///
+ public global::System.String __typename { get; }
+ public global::System.String Message { get; }
+
+ public virtual global::System.Boolean Equals(ReleaseFusionDeployment_CancelFusionConfigurationComposition_Errors_UnauthorizedOperation? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (__typename.Equals(other.__typename)) && Message.Equals(other.Message);
+ }
+
+ public override global::System.Boolean Equals(global::System.Object? obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((ReleaseFusionDeployment_CancelFusionConfigurationComposition_Errors_UnauthorizedOperation)obj);
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ hash ^= 397 * __typename.GetHashCode();
+ hash ^= 397 * Message.GetHashCode();
+ return hash;
+ }
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class ReleaseFusionDeployment_CancelFusionConfigurationComposition_Errors_FusionConfigurationRequestNotFoundError : global::System.IEquatable, IReleaseFusionDeployment_CancelFusionConfigurationComposition_Errors_FusionConfigurationRequestNotFoundError
+ {
+ public ReleaseFusionDeployment_CancelFusionConfigurationComposition_Errors_FusionConfigurationRequestNotFoundError(global::System.String __typename, global::System.String message)
+ {
+ this.__typename = __typename;
+ Message = message;
+ }
+
+ ///
+ /// The name of the current Object type at runtime.
+ ///
+ public global::System.String __typename { get; }
+ public global::System.String Message { get; }
+
+ public virtual global::System.Boolean Equals(ReleaseFusionDeployment_CancelFusionConfigurationComposition_Errors_FusionConfigurationRequestNotFoundError? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (__typename.Equals(other.__typename)) && Message.Equals(other.Message);
+ }
+
+ public override global::System.Boolean Equals(global::System.Object? obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((ReleaseFusionDeployment_CancelFusionConfigurationComposition_Errors_FusionConfigurationRequestNotFoundError)obj);
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ hash ^= 397 * __typename.GetHashCode();
+ hash ^= 397 * Message.GetHashCode();
+ return hash;
+ }
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class ReleaseFusionDeployment_CancelFusionConfigurationComposition_Errors_InvalidProcessingStateTransitionError : global::System.IEquatable, IReleaseFusionDeployment_CancelFusionConfigurationComposition_Errors_InvalidProcessingStateTransitionError
+ {
+ public ReleaseFusionDeployment_CancelFusionConfigurationComposition_Errors_InvalidProcessingStateTransitionError(global::System.String __typename, global::System.String message)
+ {
+ this.__typename = __typename;
+ Message = message;
+ }
+
+ ///
+ /// The name of the current Object type at runtime.
+ ///
+ public global::System.String __typename { get; }
+ public global::System.String Message { get; }
+
+ public virtual global::System.Boolean Equals(ReleaseFusionDeployment_CancelFusionConfigurationComposition_Errors_InvalidProcessingStateTransitionError? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (__typename.Equals(other.__typename)) && Message.Equals(other.Message);
+ }
+
+ public override global::System.Boolean Equals(global::System.Object? obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((ReleaseFusionDeployment_CancelFusionConfigurationComposition_Errors_InvalidProcessingStateTransitionError)obj);
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ hash ^= 397 * __typename.GetHashCode();
+ hash ^= 397 * Message.GetHashCode();
+ return hash;
+ }
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IReleaseFusionDeploymentResult
+ {
+ public global::ChilliCream.Nitro.Fusion.Transport.IReleaseFusionDeployment_CancelFusionConfigurationComposition CancelFusionConfigurationComposition { get; }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IReleaseFusionDeployment_CancelFusionConfigurationComposition
+ {
+ public global::System.Collections.Generic.IReadOnlyList? Errors { get; }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IReleaseFusionDeployment_CancelFusionConfigurationComposition_CancelFusionConfigurationCompositionPayload : IReleaseFusionDeployment_CancelFusionConfigurationComposition
+ {
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IReleaseFusionDeployment_CancelFusionConfigurationComposition_Errors
+ {
+ public global::System.String __typename { get; }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IReleaseFusionDeployment_CancelFusionConfigurationComposition_Errors_UnauthorizedOperation : IReleaseFusionDeployment_CancelFusionConfigurationComposition_Errors, IFusionError
+ {
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IReleaseFusionDeployment_CancelFusionConfigurationComposition_Errors_FusionConfigurationRequestNotFoundError : IReleaseFusionDeployment_CancelFusionConfigurationComposition_Errors, IFusionError
+ {
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IReleaseFusionDeployment_CancelFusionConfigurationComposition_Errors_InvalidProcessingStateTransitionError : IReleaseFusionDeployment_CancelFusionConfigurationComposition_Errors, IFusionError
+ {
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class ValidateFusionDeploymentResult : global::System.IEquatable, IValidateFusionDeploymentResult
+ {
+ public ValidateFusionDeploymentResult(global::ChilliCream.Nitro.Fusion.Transport.IValidateFusionDeployment_ValidateFusionConfigurationComposition validateFusionConfigurationComposition)
+ {
+ ValidateFusionConfigurationComposition = validateFusionConfigurationComposition;
+ }
+
+ public global::ChilliCream.Nitro.Fusion.Transport.IValidateFusionDeployment_ValidateFusionConfigurationComposition ValidateFusionConfigurationComposition { get; }
+
+ public virtual global::System.Boolean Equals(ValidateFusionDeploymentResult? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (ValidateFusionConfigurationComposition.Equals(other.ValidateFusionConfigurationComposition));
+ }
+
+ public override global::System.Boolean Equals(global::System.Object? obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((ValidateFusionDeploymentResult)obj);
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ hash ^= 397 * ValidateFusionConfigurationComposition.GetHashCode();
+ return hash;
+ }
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class ValidateFusionDeployment_ValidateFusionConfigurationComposition_ValidateFusionConfigurationCompositionPayload : global::System.IEquatable, IValidateFusionDeployment_ValidateFusionConfigurationComposition_ValidateFusionConfigurationCompositionPayload
+ {
+ public ValidateFusionDeployment_ValidateFusionConfigurationComposition_ValidateFusionConfigurationCompositionPayload(global::System.Collections.Generic.IReadOnlyList? errors)
+ {
+ Errors = errors;
+ }
+
+ public global::System.Collections.Generic.IReadOnlyList? Errors { get; }
+
+ public virtual global::System.Boolean Equals(ValidateFusionDeployment_ValidateFusionConfigurationComposition_ValidateFusionConfigurationCompositionPayload? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (global::StrawberryShake.Internal.ComparisonHelper.SequenceEqual(Errors, other.Errors));
+ }
+
+ public override global::System.Boolean Equals(global::System.Object? obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((ValidateFusionDeployment_ValidateFusionConfigurationComposition_ValidateFusionConfigurationCompositionPayload)obj);
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ if (Errors != null)
+ {
+ foreach (var Errors_elm in Errors)
+ {
+ hash ^= 397 * Errors_elm.GetHashCode();
+ }
+ }
+
+ return hash;
+ }
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class ValidateFusionDeployment_ValidateFusionConfigurationComposition_Errors_UnauthorizedOperation : global::System.IEquatable, IValidateFusionDeployment_ValidateFusionConfigurationComposition_Errors_UnauthorizedOperation
+ {
+ public ValidateFusionDeployment_ValidateFusionConfigurationComposition_Errors_UnauthorizedOperation(global::System.String __typename, global::System.String message)
+ {
+ this.__typename = __typename;
+ Message = message;
+ }
+
+ ///
+ /// The name of the current Object type at runtime.
+ ///
+ public global::System.String __typename { get; }
+ public global::System.String Message { get; }
+
+ public virtual global::System.Boolean Equals(ValidateFusionDeployment_ValidateFusionConfigurationComposition_Errors_UnauthorizedOperation? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (__typename.Equals(other.__typename)) && Message.Equals(other.Message);
+ }
+
+ public override global::System.Boolean Equals(global::System.Object? obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((ValidateFusionDeployment_ValidateFusionConfigurationComposition_Errors_UnauthorizedOperation)obj);
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ hash ^= 397 * __typename.GetHashCode();
+ hash ^= 397 * Message.GetHashCode();
+ return hash;
+ }
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class ValidateFusionDeployment_ValidateFusionConfigurationComposition_Errors_FusionConfigurationRequestNotFoundError : global::System.IEquatable, IValidateFusionDeployment_ValidateFusionConfigurationComposition_Errors_FusionConfigurationRequestNotFoundError
+ {
+ public ValidateFusionDeployment_ValidateFusionConfigurationComposition_Errors_FusionConfigurationRequestNotFoundError(global::System.String __typename, global::System.String message)
+ {
+ this.__typename = __typename;
+ Message = message;
+ }
+
+ ///
+ /// The name of the current Object type at runtime.
+ ///
+ public global::System.String __typename { get; }
+ public global::System.String Message { get; }
+
+ public virtual global::System.Boolean Equals(ValidateFusionDeployment_ValidateFusionConfigurationComposition_Errors_FusionConfigurationRequestNotFoundError? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (__typename.Equals(other.__typename)) && Message.Equals(other.Message);
+ }
+
+ public override global::System.Boolean Equals(global::System.Object? obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((ValidateFusionDeployment_ValidateFusionConfigurationComposition_Errors_FusionConfigurationRequestNotFoundError)obj);
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ hash ^= 397 * __typename.GetHashCode();
+ hash ^= 397 * Message.GetHashCode();
+ return hash;
+ }
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class ValidateFusionDeployment_ValidateFusionConfigurationComposition_Errors_InvalidProcessingStateTransitionError : global::System.IEquatable, IValidateFusionDeployment_ValidateFusionConfigurationComposition_Errors_InvalidProcessingStateTransitionError
+ {
+ public ValidateFusionDeployment_ValidateFusionConfigurationComposition_Errors_InvalidProcessingStateTransitionError(global::System.String __typename, global::System.String message)
+ {
+ this.__typename = __typename;
+ Message = message;
+ }
+
+ ///
+ /// The name of the current Object type at runtime.
+ ///
+ public global::System.String __typename { get; }
+ public global::System.String Message { get; }
+
+ public virtual global::System.Boolean Equals(ValidateFusionDeployment_ValidateFusionConfigurationComposition_Errors_InvalidProcessingStateTransitionError? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (__typename.Equals(other.__typename)) && Message.Equals(other.Message);
+ }
+
+ public override global::System.Boolean Equals(global::System.Object? obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((ValidateFusionDeployment_ValidateFusionConfigurationComposition_Errors_InvalidProcessingStateTransitionError)obj);
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ hash ^= 397 * __typename.GetHashCode();
+ hash ^= 397 * Message.GetHashCode();
+ return hash;
+ }
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IValidateFusionDeploymentResult
+ {
+ public global::ChilliCream.Nitro.Fusion.Transport.IValidateFusionDeployment_ValidateFusionConfigurationComposition ValidateFusionConfigurationComposition { get; }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IValidateFusionDeployment_ValidateFusionConfigurationComposition
+ {
+ public global::System.Collections.Generic.IReadOnlyList? Errors { get; }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IValidateFusionDeployment_ValidateFusionConfigurationComposition_ValidateFusionConfigurationCompositionPayload : IValidateFusionDeployment_ValidateFusionConfigurationComposition
+ {
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IValidateFusionDeployment_ValidateFusionConfigurationComposition_Errors
+ {
+ public global::System.String __typename { get; }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IValidateFusionDeployment_ValidateFusionConfigurationComposition_Errors_UnauthorizedOperation : IValidateFusionDeployment_ValidateFusionConfigurationComposition_Errors, IFusionError
+ {
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IValidateFusionDeployment_ValidateFusionConfigurationComposition_Errors_FusionConfigurationRequestNotFoundError : IValidateFusionDeployment_ValidateFusionConfigurationComposition_Errors, IFusionError
+ {
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IValidateFusionDeployment_ValidateFusionConfigurationComposition_Errors_InvalidProcessingStateTransitionError : IValidateFusionDeployment_ValidateFusionConfigurationComposition_Errors, IFusionError
+ {
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class CommitFusionDeploymentResult : global::System.IEquatable, ICommitFusionDeploymentResult
+ {
+ public CommitFusionDeploymentResult(global::ChilliCream.Nitro.Fusion.Transport.ICommitFusionDeployment_CommitFusionConfigurationPublish commitFusionConfigurationPublish)
+ {
+ CommitFusionConfigurationPublish = commitFusionConfigurationPublish;
+ }
+
+ public global::ChilliCream.Nitro.Fusion.Transport.ICommitFusionDeployment_CommitFusionConfigurationPublish CommitFusionConfigurationPublish { get; }
+
+ public virtual global::System.Boolean Equals(CommitFusionDeploymentResult? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (CommitFusionConfigurationPublish.Equals(other.CommitFusionConfigurationPublish));
+ }
+
+ public override global::System.Boolean Equals(global::System.Object? obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((CommitFusionDeploymentResult)obj);
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ hash ^= 397 * CommitFusionConfigurationPublish.GetHashCode();
+ return hash;
+ }
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class CommitFusionDeployment_CommitFusionConfigurationPublish_CommitFusionConfigurationPublishPayload : global::System.IEquatable, ICommitFusionDeployment_CommitFusionConfigurationPublish_CommitFusionConfigurationPublishPayload
+ {
+ public CommitFusionDeployment_CommitFusionConfigurationPublish_CommitFusionConfigurationPublishPayload(global::System.Collections.Generic.IReadOnlyList? errors)
+ {
+ Errors = errors;
+ }
+
+ public global::System.Collections.Generic.IReadOnlyList? Errors { get; }
+
+ public virtual global::System.Boolean Equals(CommitFusionDeployment_CommitFusionConfigurationPublish_CommitFusionConfigurationPublishPayload? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (global::StrawberryShake.Internal.ComparisonHelper.SequenceEqual(Errors, other.Errors));
+ }
+
+ public override global::System.Boolean Equals(global::System.Object? obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((CommitFusionDeployment_CommitFusionConfigurationPublish_CommitFusionConfigurationPublishPayload)obj);
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ if (Errors != null)
+ {
+ foreach (var Errors_elm in Errors)
+ {
+ hash ^= 397 * Errors_elm.GetHashCode();
+ }
+ }
+
+ return hash;
+ }
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class CommitFusionDeployment_CommitFusionConfigurationPublish_Errors_UnauthorizedOperation : global::System.IEquatable, ICommitFusionDeployment_CommitFusionConfigurationPublish_Errors_UnauthorizedOperation
+ {
+ public CommitFusionDeployment_CommitFusionConfigurationPublish_Errors_UnauthorizedOperation(global::System.String __typename, global::System.String message)
+ {
+ this.__typename = __typename;
+ Message = message;
+ }
+
+ ///
+ /// The name of the current Object type at runtime.
+ ///
+ public global::System.String __typename { get; }
+ public global::System.String Message { get; }
+
+ public virtual global::System.Boolean Equals(CommitFusionDeployment_CommitFusionConfigurationPublish_Errors_UnauthorizedOperation? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (__typename.Equals(other.__typename)) && Message.Equals(other.Message);
+ }
+
+ public override global::System.Boolean Equals(global::System.Object? obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((CommitFusionDeployment_CommitFusionConfigurationPublish_Errors_UnauthorizedOperation)obj);
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ hash ^= 397 * __typename.GetHashCode();
+ hash ^= 397 * Message.GetHashCode();
+ return hash;
+ }
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class CommitFusionDeployment_CommitFusionConfigurationPublish_Errors_FusionConfigurationRequestNotFoundError : global::System.IEquatable, ICommitFusionDeployment_CommitFusionConfigurationPublish_Errors_FusionConfigurationRequestNotFoundError
+ {
+ public CommitFusionDeployment_CommitFusionConfigurationPublish_Errors_FusionConfigurationRequestNotFoundError(global::System.String __typename, global::System.String message)
+ {
+ this.__typename = __typename;
+ Message = message;
+ }
+
+ ///
+ /// The name of the current Object type at runtime.
+ ///
+ public global::System.String __typename { get; }
+ public global::System.String Message { get; }
+
+ public virtual global::System.Boolean Equals(CommitFusionDeployment_CommitFusionConfigurationPublish_Errors_FusionConfigurationRequestNotFoundError? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (__typename.Equals(other.__typename)) && Message.Equals(other.Message);
+ }
+
+ public override global::System.Boolean Equals(global::System.Object? obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((CommitFusionDeployment_CommitFusionConfigurationPublish_Errors_FusionConfigurationRequestNotFoundError)obj);
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ hash ^= 397 * __typename.GetHashCode();
+ hash ^= 397 * Message.GetHashCode();
+ return hash;
+ }
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class CommitFusionDeployment_CommitFusionConfigurationPublish_Errors_InvalidProcessingStateTransitionError : global::System.IEquatable, ICommitFusionDeployment_CommitFusionConfigurationPublish_Errors_InvalidProcessingStateTransitionError
+ {
+ public CommitFusionDeployment_CommitFusionConfigurationPublish_Errors_InvalidProcessingStateTransitionError(global::System.String __typename, global::System.String message)
+ {
+ this.__typename = __typename;
+ Message = message;
+ }
+
+ ///
+ /// The name of the current Object type at runtime.
+ ///
+ public global::System.String __typename { get; }
+ public global::System.String Message { get; }
+
+ public virtual global::System.Boolean Equals(CommitFusionDeployment_CommitFusionConfigurationPublish_Errors_InvalidProcessingStateTransitionError? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (__typename.Equals(other.__typename)) && Message.Equals(other.Message);
+ }
+
+ public override global::System.Boolean Equals(global::System.Object? obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((CommitFusionDeployment_CommitFusionConfigurationPublish_Errors_InvalidProcessingStateTransitionError)obj);
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ hash ^= 397 * __typename.GetHashCode();
+ hash ^= 397 * Message.GetHashCode();
+ return hash;
+ }
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface ICommitFusionDeploymentResult
+ {
+ public global::ChilliCream.Nitro.Fusion.Transport.ICommitFusionDeployment_CommitFusionConfigurationPublish CommitFusionConfigurationPublish { get; }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface ICommitFusionDeployment_CommitFusionConfigurationPublish
+ {
+ public global::System.Collections.Generic.IReadOnlyList? Errors { get; }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface ICommitFusionDeployment_CommitFusionConfigurationPublish_CommitFusionConfigurationPublishPayload : ICommitFusionDeployment_CommitFusionConfigurationPublish
+ {
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface ICommitFusionDeployment_CommitFusionConfigurationPublish_Errors
+ {
+ public global::System.String __typename { get; }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface ICommitFusionDeployment_CommitFusionConfigurationPublish_Errors_UnauthorizedOperation : ICommitFusionDeployment_CommitFusionConfigurationPublish_Errors, IFusionError
+ {
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface ICommitFusionDeployment_CommitFusionConfigurationPublish_Errors_FusionConfigurationRequestNotFoundError : ICommitFusionDeployment_CommitFusionConfigurationPublish_Errors, IFusionError
+ {
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface ICommitFusionDeployment_CommitFusionConfigurationPublish_Errors_InvalidProcessingStateTransitionError : ICommitFusionDeployment_CommitFusionConfigurationPublish_Errors, IFusionError
+ {
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class WatchFusionDeploymentResult : global::System.IEquatable, IWatchFusionDeploymentResult
+ {
+ public WatchFusionDeploymentResult(global::ChilliCream.Nitro.Fusion.Transport.IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged onFusionConfigurationPublishingTaskChanged)
+ {
+ OnFusionConfigurationPublishingTaskChanged = onFusionConfigurationPublishingTaskChanged;
+ }
+
+ public global::ChilliCream.Nitro.Fusion.Transport.IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged OnFusionConfigurationPublishingTaskChanged { get; }
+
+ public virtual global::System.Boolean Equals(WatchFusionDeploymentResult? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (OnFusionConfigurationPublishingTaskChanged.Equals(other.OnFusionConfigurationPublishingTaskChanged));
+ }
+
+ public override global::System.Boolean Equals(global::System.Object? obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((WatchFusionDeploymentResult)obj);
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ hash ^= 397 * OnFusionConfigurationPublishingTaskChanged.GetHashCode();
+ return hash;
+ }
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_FusionConfigurationPublishingFailed : global::System.IEquatable, IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_FusionConfigurationPublishingFailed
+ {
+ public WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_FusionConfigurationPublishingFailed(global::System.String __typename, global::ChilliCream.Nitro.Fusion.Transport.ProcessingState state, global::System.Collections.Generic.IReadOnlyList errors)
+ {
+ this.__typename = __typename;
+ State = state;
+ Errors = errors;
+ }
+
+ ///
+ /// The name of the current Object type at runtime.
+ ///
+ public global::System.String __typename { get; }
+ public global::ChilliCream.Nitro.Fusion.Transport.ProcessingState State { get; }
+ public global::System.Collections.Generic.IReadOnlyList Errors { get; }
+
+ public virtual global::System.Boolean Equals(WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_FusionConfigurationPublishingFailed? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (__typename.Equals(other.__typename)) && State.Equals(other.State) && global::StrawberryShake.Internal.ComparisonHelper.SequenceEqual(Errors, other.Errors);
+ }
+
+ public override global::System.Boolean Equals(global::System.Object? obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_FusionConfigurationPublishingFailed)obj);
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ hash ^= 397 * __typename.GetHashCode();
+ hash ^= 397 * State.GetHashCode();
+ foreach (var Errors_elm in Errors)
+ {
+ hash ^= 397 * Errors_elm.GetHashCode();
+ }
+
+ return hash;
+ }
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_FusionConfigurationPublishingSuccess : global::System.IEquatable, IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_FusionConfigurationPublishingSuccess
+ {
+ public WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_FusionConfigurationPublishingSuccess(global::System.String __typename, global::ChilliCream.Nitro.Fusion.Transport.ProcessingState state)
+ {
+ this.__typename = __typename;
+ State = state;
+ }
+
+ ///
+ /// The name of the current Object type at runtime.
+ ///
+ public global::System.String __typename { get; }
+ public global::ChilliCream.Nitro.Fusion.Transport.ProcessingState State { get; }
+
+ public virtual global::System.Boolean Equals(WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_FusionConfigurationPublishingSuccess? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (__typename.Equals(other.__typename)) && State.Equals(other.State);
+ }
+
+ public override global::System.Boolean Equals(global::System.Object? obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_FusionConfigurationPublishingSuccess)obj);
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ hash ^= 397 * __typename.GetHashCode();
+ hash ^= 397 * State.GetHashCode();
+ return hash;
+ }
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_FusionConfigurationValidationFailed : global::System.IEquatable, IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_FusionConfigurationValidationFailed
+ {
+ public WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_FusionConfigurationValidationFailed(global::System.String __typename, global::ChilliCream.Nitro.Fusion.Transport.ProcessingState state, global::System.Collections.Generic.IReadOnlyList errors)
+ {
+ this.__typename = __typename;
+ State = state;
+ Errors = errors;
+ }
+
+ ///
+ /// The name of the current Object type at runtime.
+ ///
+ public global::System.String __typename { get; }
+ public global::ChilliCream.Nitro.Fusion.Transport.ProcessingState State { get; }
+ public global::System.Collections.Generic.IReadOnlyList Errors { get; }
+
+ public virtual global::System.Boolean Equals(WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_FusionConfigurationValidationFailed? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (__typename.Equals(other.__typename)) && State.Equals(other.State) && global::StrawberryShake.Internal.ComparisonHelper.SequenceEqual(Errors, other.Errors);
+ }
+
+ public override global::System.Boolean Equals(global::System.Object? obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_FusionConfigurationValidationFailed)obj);
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ hash ^= 397 * __typename.GetHashCode();
+ hash ^= 397 * State.GetHashCode();
+ foreach (var Errors_elm in Errors)
+ {
+ hash ^= 397 * Errors_elm.GetHashCode();
+ }
+
+ return hash;
+ }
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_FusionConfigurationValidationSuccess : global::System.IEquatable, IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_FusionConfigurationValidationSuccess
+ {
+ public WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_FusionConfigurationValidationSuccess(global::System.String __typename, global::ChilliCream.Nitro.Fusion.Transport.ProcessingState state)
+ {
+ this.__typename = __typename;
+ State = state;
+ }
+
+ ///
+ /// The name of the current Object type at runtime.
+ ///
+ public global::System.String __typename { get; }
+ public global::ChilliCream.Nitro.Fusion.Transport.ProcessingState State { get; }
+
+ public virtual global::System.Boolean Equals(WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_FusionConfigurationValidationSuccess? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (__typename.Equals(other.__typename)) && State.Equals(other.State);
+ }
+
+ public override global::System.Boolean Equals(global::System.Object? obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_FusionConfigurationValidationSuccess)obj);
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ hash ^= 397 * __typename.GetHashCode();
+ hash ^= 397 * State.GetHashCode();
+ return hash;
+ }
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_OperationInProgress : global::System.IEquatable, IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_OperationInProgress
+ {
+ public WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_OperationInProgress(global::System.String __typename, global::ChilliCream.Nitro.Fusion.Transport.ProcessingState state)
+ {
+ this.__typename = __typename;
+ State = state;
+ }
+
+ ///
+ /// The name of the current Object type at runtime.
+ ///
+ public global::System.String __typename { get; }
+ public global::ChilliCream.Nitro.Fusion.Transport.ProcessingState State { get; }
+
+ public virtual global::System.Boolean Equals(WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_OperationInProgress? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (__typename.Equals(other.__typename)) && State.Equals(other.State);
+ }
+
+ public override global::System.Boolean Equals(global::System.Object? obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_OperationInProgress)obj);
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ hash ^= 397 * __typename.GetHashCode();
+ hash ^= 397 * State.GetHashCode();
+ return hash;
+ }
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_ProcessingTaskApproved : global::System.IEquatable, IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_ProcessingTaskApproved
+ {
+ public WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_ProcessingTaskApproved(global::System.String __typename, global::ChilliCream.Nitro.Fusion.Transport.ProcessingState state)
+ {
+ this.__typename = __typename;
+ State = state;
+ }
+
+ ///
+ /// The name of the current Object type at runtime.
+ ///
+ public global::System.String __typename { get; }
+ public global::ChilliCream.Nitro.Fusion.Transport.ProcessingState State { get; }
+
+ public virtual global::System.Boolean Equals(WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_ProcessingTaskApproved? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (__typename.Equals(other.__typename)) && State.Equals(other.State);
+ }
+
+ public override global::System.Boolean Equals(global::System.Object? obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_ProcessingTaskApproved)obj);
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ hash ^= 397 * __typename.GetHashCode();
+ hash ^= 397 * State.GetHashCode();
+ return hash;
+ }
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_ProcessingTaskIsQueued : global::System.IEquatable, IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_ProcessingTaskIsQueued
+ {
+ public WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_ProcessingTaskIsQueued(global::System.String __typename, global::ChilliCream.Nitro.Fusion.Transport.ProcessingState state, global::System.Int32 queuePosition)
+ {
+ this.__typename = __typename;
+ State = state;
+ QueuePosition = queuePosition;
+ }
+
+ ///
+ /// The name of the current Object type at runtime.
+ ///
+ public global::System.String __typename { get; }
+ public global::ChilliCream.Nitro.Fusion.Transport.ProcessingState State { get; }
+ public global::System.Int32 QueuePosition { get; }
+
+ public virtual global::System.Boolean Equals(WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_ProcessingTaskIsQueued? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (__typename.Equals(other.__typename)) && State.Equals(other.State) && global::System.Object.Equals(QueuePosition, other.QueuePosition);
+ }
+
+ public override global::System.Boolean Equals(global::System.Object? obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_ProcessingTaskIsQueued)obj);
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ hash ^= 397 * __typename.GetHashCode();
+ hash ^= 397 * State.GetHashCode();
+ hash ^= 397 * QueuePosition.GetHashCode();
+ return hash;
+ }
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_ProcessingTaskIsReady : global::System.IEquatable, IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_ProcessingTaskIsReady
+ {
+ public WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_ProcessingTaskIsReady(global::System.String __typename, global::ChilliCream.Nitro.Fusion.Transport.ProcessingState state)
+ {
+ this.__typename = __typename;
+ State = state;
+ }
+
+ ///
+ /// The name of the current Object type at runtime.
+ ///
+ public global::System.String __typename { get; }
+ public global::ChilliCream.Nitro.Fusion.Transport.ProcessingState State { get; }
+
+ public virtual global::System.Boolean Equals(WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_ProcessingTaskIsReady? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (__typename.Equals(other.__typename)) && State.Equals(other.State);
+ }
+
+ public override global::System.Boolean Equals(global::System.Object? obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_ProcessingTaskIsReady)obj);
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ hash ^= 397 * __typename.GetHashCode();
+ hash ^= 397 * State.GetHashCode();
+ return hash;
+ }
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_ValidationInProgress : global::System.IEquatable, IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_ValidationInProgress
+ {
+ public WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_ValidationInProgress(global::System.String __typename, global::ChilliCream.Nitro.Fusion.Transport.ProcessingState state)
+ {
+ this.__typename = __typename;
+ State = state;
+ }
+
+ ///
+ /// The name of the current Object type at runtime.
+ ///
+ public global::System.String __typename { get; }
+ public global::ChilliCream.Nitro.Fusion.Transport.ProcessingState State { get; }
+
+ public virtual global::System.Boolean Equals(WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_ValidationInProgress? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (__typename.Equals(other.__typename)) && State.Equals(other.State);
+ }
+
+ public override global::System.Boolean Equals(global::System.Object? obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_ValidationInProgress)obj);
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ hash ^= 397 * __typename.GetHashCode();
+ hash ^= 397 * State.GetHashCode();
+ return hash;
+ }
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_WaitForApproval : global::System.IEquatable, IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_WaitForApproval
+ {
+ public WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_WaitForApproval(global::System.String __typename, global::ChilliCream.Nitro.Fusion.Transport.ProcessingState state)
+ {
+ this.__typename = __typename;
+ State = state;
+ }
+
+ ///
+ /// The name of the current Object type at runtime.
+ ///
+ public global::System.String __typename { get; }
+ public global::ChilliCream.Nitro.Fusion.Transport.ProcessingState State { get; }
+
+ public virtual global::System.Boolean Equals(WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_WaitForApproval? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (__typename.Equals(other.__typename)) && State.Equals(other.State);
+ }
+
+ public override global::System.Boolean Equals(global::System.Object? obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_WaitForApproval)obj);
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ hash ^= 397 * __typename.GetHashCode();
+ hash ^= 397 * State.GetHashCode();
+ return hash;
+ }
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_ConcurrentOperationError : global::System.IEquatable, IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_ConcurrentOperationError
+ {
+ public WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_ConcurrentOperationError(global::System.String message)
+ {
+ Message = message;
+ }
+
+ public global::System.String Message { get; }
+
+ public virtual global::System.Boolean Equals(WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_ConcurrentOperationError? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (Message.Equals(other.Message));
+ }
+
+ public override global::System.Boolean Equals(global::System.Object? obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_ConcurrentOperationError)obj);
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ hash ^= 397 * Message.GetHashCode();
+ return hash;
+ }
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_InvalidGraphQLSchemaError : global::System.IEquatable, IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_InvalidGraphQLSchemaError
+ {
+ public WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_InvalidGraphQLSchemaError(global::System.String message)
+ {
+ Message = message;
+ }
+
+ public global::System.String Message { get; }
+
+ public virtual global::System.Boolean Equals(WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_InvalidGraphQLSchemaError? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (Message.Equals(other.Message));
+ }
+
+ public override global::System.Boolean Equals(global::System.Object? obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_InvalidGraphQLSchemaError)obj);
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ hash ^= 397 * Message.GetHashCode();
+ return hash;
+ }
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_ProcessingTimeoutError : global::System.IEquatable, IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_ProcessingTimeoutError
+ {
+ public WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_ProcessingTimeoutError(global::System.String message)
+ {
+ Message = message;
+ }
+
+ public global::System.String Message { get; }
+
+ public virtual global::System.Boolean Equals(WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_ProcessingTimeoutError? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (Message.Equals(other.Message));
+ }
+
+ public override global::System.Boolean Equals(global::System.Object? obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_ProcessingTimeoutError)obj);
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ hash ^= 397 * Message.GetHashCode();
+ return hash;
+ }
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_ReadyTimeoutError : global::System.IEquatable, IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_ReadyTimeoutError
+ {
+ public WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_ReadyTimeoutError(global::System.String message)
+ {
+ Message = message;
+ }
+
+ public global::System.String Message { get; }
+
+ public virtual global::System.Boolean Equals(WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_ReadyTimeoutError? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (Message.Equals(other.Message));
+ }
+
+ public override global::System.Boolean Equals(global::System.Object? obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_ReadyTimeoutError)obj);
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ hash ^= 397 * Message.GetHashCode();
+ return hash;
+ }
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_UnexpectedProcessingError : global::System.IEquatable, IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_UnexpectedProcessingError
+ {
+ public WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_UnexpectedProcessingError(global::System.String message)
+ {
+ Message = message;
+ }
+
+ public global::System.String Message { get; }
+
+ public virtual global::System.Boolean Equals(WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_UnexpectedProcessingError? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (Message.Equals(other.Message));
+ }
+
+ public override global::System.Boolean Equals(global::System.Object? obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_UnexpectedProcessingError)obj);
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ hash ^= 397 * Message.GetHashCode();
+ return hash;
+ }
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_InvalidGraphQLSchemaError_1 : global::System.IEquatable, IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_InvalidGraphQLSchemaError_1
+ {
+ public WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_InvalidGraphQLSchemaError_1(global::System.String message)
+ {
+ Message = message;
+ }
+
+ public global::System.String Message { get; }
+
+ public virtual global::System.Boolean Equals(WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_InvalidGraphQLSchemaError_1? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (Message.Equals(other.Message));
+ }
+
+ public override global::System.Boolean Equals(global::System.Object? obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_InvalidGraphQLSchemaError_1)obj);
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ hash ^= 397 * Message.GetHashCode();
+ return hash;
+ }
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_McpFeatureCollectionValidationError : global::System.IEquatable, IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_McpFeatureCollectionValidationError
+ {
+ public WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_McpFeatureCollectionValidationError(global::System.String message)
+ {
+ Message = message;
+ }
+
+ public global::System.String Message { get; }
+
+ public virtual global::System.Boolean Equals(WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_McpFeatureCollectionValidationError? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (Message.Equals(other.Message));
+ }
+
+ public override global::System.Boolean Equals(global::System.Object? obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_McpFeatureCollectionValidationError)obj);
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ hash ^= 397 * Message.GetHashCode();
+ return hash;
+ }
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_OpenApiCollectionValidationError : global::System.IEquatable, IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_OpenApiCollectionValidationError
+ {
+ public WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_OpenApiCollectionValidationError(global::System.String message)
+ {
+ Message = message;
+ }
+
+ public global::System.String Message { get; }
+
+ public virtual global::System.Boolean Equals(WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_OpenApiCollectionValidationError? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (Message.Equals(other.Message));
+ }
+
+ public override global::System.Boolean Equals(global::System.Object? obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_OpenApiCollectionValidationError)obj);
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ hash ^= 397 * Message.GetHashCode();
+ return hash;
+ }
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_PersistedQueryValidationError : global::System.IEquatable, IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_PersistedQueryValidationError
+ {
+ public WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_PersistedQueryValidationError(global::System.String message)
+ {
+ Message = message;
+ }
+
+ public global::System.String Message { get; }
+
+ public virtual global::System.Boolean Equals(WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_PersistedQueryValidationError? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (Message.Equals(other.Message));
+ }
+
+ public override global::System.Boolean Equals(global::System.Object? obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_PersistedQueryValidationError)obj);
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ hash ^= 397 * Message.GetHashCode();
+ return hash;
+ }
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_SchemaVersionChangeViolationError : global::System.IEquatable, IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_SchemaVersionChangeViolationError
+ {
+ public WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_SchemaVersionChangeViolationError(global::System.String message)
+ {
+ Message = message;
+ }
+
+ public global::System.String Message { get; }
+
+ public virtual global::System.Boolean Equals(WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_SchemaVersionChangeViolationError? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (Message.Equals(other.Message));
+ }
+
+ public override global::System.Boolean Equals(global::System.Object? obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_SchemaVersionChangeViolationError)obj);
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ hash ^= 397 * Message.GetHashCode();
+ return hash;
+ }
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_UnexpectedProcessingError_1 : global::System.IEquatable, IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_UnexpectedProcessingError_1
+ {
+ public WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_UnexpectedProcessingError_1(global::System.String message)
+ {
+ Message = message;
+ }
+
+ public global::System.String Message { get; }
+
+ public virtual global::System.Boolean Equals(WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_UnexpectedProcessingError_1? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (Message.Equals(other.Message));
+ }
+
+ public override global::System.Boolean Equals(global::System.Object? obj)
+ {
+ if (ReferenceEquals(null, obj))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return Equals((WatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_UnexpectedProcessingError_1)obj);
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ hash ^= 397 * Message.GetHashCode();
+ return hash;
+ }
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IWatchFusionDeploymentResult
+ {
+ public global::ChilliCream.Nitro.Fusion.Transport.IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged OnFusionConfigurationPublishingTaskChanged { get; }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged
+ {
+ public global::System.String __typename { get; }
+ public global::ChilliCream.Nitro.Fusion.Transport.ProcessingState State { get; }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_FusionConfigurationPublishingFailed : IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged
+ {
+ public global::System.Collections.Generic.IReadOnlyList Errors { get; }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_FusionConfigurationPublishingSuccess : IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged
+ {
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_FusionConfigurationValidationFailed : IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged
+ {
+ public global::System.Collections.Generic.IReadOnlyList Errors { get; }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_FusionConfigurationValidationSuccess : IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged
+ {
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_OperationInProgress : IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged
+ {
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_ProcessingTaskApproved : IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged
+ {
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_ProcessingTaskIsQueued : IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged
+ {
+ public global::System.Int32 QueuePosition { get; }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_ProcessingTaskIsReady : IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged
+ {
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_ValidationInProgress : IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged
+ {
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_WaitForApproval : IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged
+ {
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors
+ {
+ public global::System.String Message { get; }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_ConcurrentOperationError : IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors
+ {
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_InvalidGraphQLSchemaError : IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors
+ {
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_ProcessingTimeoutError : IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors
+ {
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_ReadyTimeoutError : IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors
+ {
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_UnexpectedProcessingError : IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors
+ {
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_1
+ {
+ public global::System.String Message { get; }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_InvalidGraphQLSchemaError_1 : IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_1
+ {
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_McpFeatureCollectionValidationError : IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_1
+ {
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_OpenApiCollectionValidationError : IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_1
+ {
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_PersistedQueryValidationError : IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_1
+ {
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_SchemaVersionChangeViolationError : IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_1
+ {
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.ResultInterfaceGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial interface IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_UnexpectedProcessingError_1 : IWatchFusionDeployment_OnFusionConfigurationPublishingTaskChanged_Errors_1
+ {
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.InputValueFormatterGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class UploadFusionSubgraphInputInputValueFormatter : global::StrawberryShake.Serialization.IInputObjectFormatter
+ {
+ private global::StrawberryShake.Serialization.IInputValueFormatter _iDFormatter = default !;
+ private global::StrawberryShake.Serialization.IInputValueFormatter _uploadFormatter = default !;
+ private global::StrawberryShake.Serialization.IInputValueFormatter _sourceMetadataInputFormatter = default !;
+ private global::StrawberryShake.Serialization.IInputValueFormatter _stringFormatter = default !;
+ public global::System.String TypeName => "UploadFusionSubgraphInput";
+
+ public void Initialize(global::StrawberryShake.Serialization.ISerializerResolver serializerResolver)
+ {
+ _iDFormatter = serializerResolver.GetInputValueFormatter("ID");
+ _uploadFormatter = serializerResolver.GetInputValueFormatter("Upload");
+ _sourceMetadataInputFormatter = serializerResolver.GetInputValueFormatter("SourceMetadataInput");
+ _stringFormatter = serializerResolver.GetInputValueFormatter("String");
+ }
+
+ public global::System.Object? Format(global::System.Object? runtimeValue)
+ {
+ if (runtimeValue is null)
+ {
+ return null;
+ }
+
+ var input = runtimeValue as global::ChilliCream.Nitro.Fusion.Transport.UploadFusionSubgraphInput;
+ var inputInfo = runtimeValue as global::ChilliCream.Nitro.Fusion.Transport.State.IUploadFusionSubgraphInputInfo;
+ if (input is null || inputInfo is null)
+ {
+ throw new global::System.ArgumentException(nameof(runtimeValue));
+ }
+
+ var fields = new global::System.Collections.Generic.List>();
+ if (inputInfo.IsApiIdSet)
+ {
+ fields.Add(new global::System.Collections.Generic.KeyValuePair("apiId", FormatApiId(input.ApiId)));
+ }
+
+ if (inputInfo.IsArchiveSet)
+ {
+ fields.Add(new global::System.Collections.Generic.KeyValuePair("archive", FormatArchive(input.Archive)));
+ }
+
+ if (inputInfo.IsSourceSet)
+ {
+ fields.Add(new global::System.Collections.Generic.KeyValuePair("source", FormatSource(input.Source)));
+ }
+
+ if (inputInfo.IsTagSet)
+ {
+ fields.Add(new global::System.Collections.Generic.KeyValuePair("tag", FormatTag(input.Tag)));
+ }
+
+ return fields;
+ }
+
+ private global::System.Object? FormatApiId(global::System.String input)
+ {
+ if (input is null)
+ {
+ throw new global::System.ArgumentNullException(nameof(input));
+ }
+
+ return _iDFormatter.Format(input);
+ }
+
+ private global::System.Object? FormatArchive(global::StrawberryShake.Upload input)
+ {
+ return _uploadFormatter.Format(input);
+ }
+
+ private global::System.Object? FormatSource(global::ChilliCream.Nitro.Fusion.Transport.SourceMetadataInput? input)
+ {
+ if (input is null)
+ {
+ return input;
+ }
+ else
+ {
+ return _sourceMetadataInputFormatter.Format(input);
+ }
+ }
+
+ private global::System.Object? FormatTag(global::System.String input)
+ {
+ if (input is null)
+ {
+ throw new global::System.ArgumentNullException(nameof(input));
+ }
+
+ return _stringFormatter.Format(input);
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.InputTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "0.0.0.0")]
+ internal partial record UploadFusionSubgraphInput : global::ChilliCream.Nitro.Fusion.Transport.State.IUploadFusionSubgraphInputInfo
+ {
+ public virtual global::System.Boolean Equals(UploadFusionSubgraphInput? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (ApiId.Equals(other.ApiId)) && Archive.Equals(other.Archive) && ((Source is null && other.Source is null) || Source != null && Source.Equals(other.Source)) && Tag.Equals(other.Tag);
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ hash ^= 397 * ApiId.GetHashCode();
+ hash ^= 397 * Archive.GetHashCode();
+ if (Source != null)
+ {
+ hash ^= 397 * Source.GetHashCode();
+ }
+
+ hash ^= 397 * Tag.GetHashCode();
+ return hash;
+ }
+ }
+
+ private global::System.String _value_apiId = default !;
+ private global::System.Boolean _set_apiId;
+ private global::StrawberryShake.Upload _value_archive;
+ private global::System.Boolean _set_archive;
+ private global::ChilliCream.Nitro.Fusion.Transport.SourceMetadataInput? _value_source;
+ private global::System.Boolean _set_source;
+ private global::System.String _value_tag = default !;
+ private global::System.Boolean _set_tag;
+ public global::System.String ApiId
+ {
+ get => _value_apiId;
+ init
+ {
+ _set_apiId = true;
+ _value_apiId = value;
+ }
+ }
+
+ global::System.Boolean global::ChilliCream.Nitro.Fusion.Transport.State.IUploadFusionSubgraphInputInfo.IsApiIdSet => _set_apiId;
+
+ public global::StrawberryShake.Upload Archive
+ {
+ get => _value_archive;
+ init
+ {
+ _set_archive = true;
+ _value_archive = value;
+ }
+ }
+
+ global::System.Boolean global::ChilliCream.Nitro.Fusion.Transport.State.IUploadFusionSubgraphInputInfo.IsArchiveSet => _set_archive;
+
+ public global::ChilliCream.Nitro.Fusion.Transport.SourceMetadataInput? Source
+ {
+ get => _value_source;
+ init
+ {
+ _set_source = true;
+ _value_source = value;
+ }
+ }
+
+ global::System.Boolean global::ChilliCream.Nitro.Fusion.Transport.State.IUploadFusionSubgraphInputInfo.IsSourceSet => _set_source;
+
+ public global::System.String Tag
+ {
+ get => _value_tag;
+ init
+ {
+ _set_tag = true;
+ _value_tag = value;
+ }
+ }
+
+ global::System.Boolean global::ChilliCream.Nitro.Fusion.Transport.State.IUploadFusionSubgraphInputInfo.IsTagSet => _set_tag;
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.InputValueFormatterGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class SourceMetadataInputInputValueFormatter : global::StrawberryShake.Serialization.IInputObjectFormatter
+ {
+ private global::StrawberryShake.Serialization.IInputValueFormatter _azureDevOpsSourceMetadataInputFormatter = default !;
+ private global::StrawberryShake.Serialization.IInputValueFormatter _gitHubSourceMetadataInputFormatter = default !;
+ public global::System.String TypeName => "SourceMetadataInput";
+
+ public void Initialize(global::StrawberryShake.Serialization.ISerializerResolver serializerResolver)
+ {
+ _azureDevOpsSourceMetadataInputFormatter = serializerResolver.GetInputValueFormatter("AzureDevOpsSourceMetadataInput");
+ _gitHubSourceMetadataInputFormatter = serializerResolver.GetInputValueFormatter("GitHubSourceMetadataInput");
+ }
+
+ public global::System.Object? Format(global::System.Object? runtimeValue)
+ {
+ if (runtimeValue is null)
+ {
+ return null;
+ }
+
+ var input = runtimeValue as global::ChilliCream.Nitro.Fusion.Transport.SourceMetadataInput;
+ var inputInfo = runtimeValue as global::ChilliCream.Nitro.Fusion.Transport.State.ISourceMetadataInputInfo;
+ if (input is null || inputInfo is null)
+ {
+ throw new global::System.ArgumentException(nameof(runtimeValue));
+ }
+
+ var fields = new global::System.Collections.Generic.List>();
+ if (inputInfo.IsAzureDevOpsSet)
+ {
+ fields.Add(new global::System.Collections.Generic.KeyValuePair("azureDevOps", FormatAzureDevOps(input.AzureDevOps)));
+ }
+
+ if (inputInfo.IsGithubSet)
+ {
+ fields.Add(new global::System.Collections.Generic.KeyValuePair("github", FormatGithub(input.Github)));
+ }
+
+ return fields;
+ }
+
+ private global::System.Object? FormatAzureDevOps(global::ChilliCream.Nitro.Fusion.Transport.AzureDevOpsSourceMetadataInput? input)
+ {
+ if (input is null)
+ {
+ return input;
+ }
+ else
+ {
+ return _azureDevOpsSourceMetadataInputFormatter.Format(input);
+ }
+ }
+
+ private global::System.Object? FormatGithub(global::ChilliCream.Nitro.Fusion.Transport.GitHubSourceMetadataInput? input)
+ {
+ if (input is null)
+ {
+ return input;
+ }
+ else
+ {
+ return _gitHubSourceMetadataInputFormatter.Format(input);
+ }
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.InputTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "0.0.0.0")]
+ internal partial record SourceMetadataInput : global::ChilliCream.Nitro.Fusion.Transport.State.ISourceMetadataInputInfo
+ {
+ public virtual global::System.Boolean Equals(SourceMetadataInput? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (((AzureDevOps is null && other.AzureDevOps is null) || AzureDevOps != null && AzureDevOps.Equals(other.AzureDevOps))) && ((Github is null && other.Github is null) || Github != null && Github.Equals(other.Github));
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ if (AzureDevOps != null)
+ {
+ hash ^= 397 * AzureDevOps.GetHashCode();
+ }
+
+ if (Github != null)
+ {
+ hash ^= 397 * Github.GetHashCode();
+ }
+
+ return hash;
+ }
+ }
+
+ private global::ChilliCream.Nitro.Fusion.Transport.AzureDevOpsSourceMetadataInput? _value_azureDevOps;
+ private global::System.Boolean _set_azureDevOps;
+ private global::ChilliCream.Nitro.Fusion.Transport.GitHubSourceMetadataInput? _value_github;
+ private global::System.Boolean _set_github;
+ public global::ChilliCream.Nitro.Fusion.Transport.AzureDevOpsSourceMetadataInput? AzureDevOps
+ {
+ get => _value_azureDevOps;
+ init
+ {
+ _set_azureDevOps = true;
+ _value_azureDevOps = value;
+ }
+ }
+
+ global::System.Boolean global::ChilliCream.Nitro.Fusion.Transport.State.ISourceMetadataInputInfo.IsAzureDevOpsSet => _set_azureDevOps;
+
+ public global::ChilliCream.Nitro.Fusion.Transport.GitHubSourceMetadataInput? Github
+ {
+ get => _value_github;
+ init
+ {
+ _set_github = true;
+ _value_github = value;
+ }
+ }
+
+ global::System.Boolean global::ChilliCream.Nitro.Fusion.Transport.State.ISourceMetadataInputInfo.IsGithubSet => _set_github;
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.InputValueFormatterGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class AzureDevOpsSourceMetadataInputInputValueFormatter : global::StrawberryShake.Serialization.IInputObjectFormatter
+ {
+ private global::StrawberryShake.Serialization.IInputValueFormatter _azureDevOpsActorInputFormatter = default !;
+ private global::StrawberryShake.Serialization.IInputValueFormatter _stringFormatter = default !;
+ private global::StrawberryShake.Serialization.IInputValueFormatter _uRLFormatter = default !;
+ public global::System.String TypeName => "AzureDevOpsSourceMetadataInput";
+
+ public void Initialize(global::StrawberryShake.Serialization.ISerializerResolver serializerResolver)
+ {
+ _azureDevOpsActorInputFormatter = serializerResolver.GetInputValueFormatter("AzureDevOpsActorInput");
+ _stringFormatter = serializerResolver.GetInputValueFormatter("String");
+ _uRLFormatter = serializerResolver.GetInputValueFormatter("URL");
+ }
+
+ public global::System.Object? Format(global::System.Object? runtimeValue)
+ {
+ if (runtimeValue is null)
+ {
+ return null;
+ }
+
+ var input = runtimeValue as global::ChilliCream.Nitro.Fusion.Transport.AzureDevOpsSourceMetadataInput;
+ var inputInfo = runtimeValue as global::ChilliCream.Nitro.Fusion.Transport.State.IAzureDevOpsSourceMetadataInputInfo;
+ if (input is null || inputInfo is null)
+ {
+ throw new global::System.ArgumentException(nameof(runtimeValue));
+ }
+
+ var fields = new global::System.Collections.Generic.List>();
+ if (inputInfo.IsActorSet)
+ {
+ fields.Add(new global::System.Collections.Generic.KeyValuePair("actor", FormatActor(input.Actor)));
+ }
+
+ if (inputInfo.IsCommitHashSet)
+ {
+ fields.Add(new global::System.Collections.Generic.KeyValuePair("commitHash", FormatCommitHash(input.CommitHash)));
+ }
+
+ if (inputInfo.IsJobIdSet)
+ {
+ fields.Add(new global::System.Collections.Generic.KeyValuePair("jobId", FormatJobId(input.JobId)));
+ }
+
+ if (inputInfo.IsPipelineNameSet)
+ {
+ fields.Add(new global::System.Collections.Generic.KeyValuePair("pipelineName", FormatPipelineName(input.PipelineName)));
+ }
+
+ if (inputInfo.IsProjectUrlSet)
+ {
+ fields.Add(new global::System.Collections.Generic.KeyValuePair("projectUrl", FormatProjectUrl(input.ProjectUrl)));
+ }
+
+ if (inputInfo.IsRepositoryUrlSet)
+ {
+ fields.Add(new global::System.Collections.Generic.KeyValuePair("repositoryUrl", FormatRepositoryUrl(input.RepositoryUrl)));
+ }
+
+ if (inputInfo.IsRunIdSet)
+ {
+ fields.Add(new global::System.Collections.Generic.KeyValuePair("runId", FormatRunId(input.RunId)));
+ }
+
+ if (inputInfo.IsRunNumberSet)
+ {
+ fields.Add(new global::System.Collections.Generic.KeyValuePair("runNumber", FormatRunNumber(input.RunNumber)));
+ }
+
+ if (inputInfo.IsTaskIdSet)
+ {
+ fields.Add(new global::System.Collections.Generic.KeyValuePair("taskId", FormatTaskId(input.TaskId)));
+ }
+
+ return fields;
+ }
+
+ private global::System.Object? FormatActor(global::ChilliCream.Nitro.Fusion.Transport.AzureDevOpsActorInput input)
+ {
+ if (input is null)
+ {
+ throw new global::System.ArgumentNullException(nameof(input));
+ }
+
+ return _azureDevOpsActorInputFormatter.Format(input);
+ }
+
+ private global::System.Object? FormatCommitHash(global::System.String? input)
+ {
+ if (input is null)
+ {
+ return input;
+ }
+ else
+ {
+ return _stringFormatter.Format(input);
+ }
+ }
+
+ private global::System.Object? FormatJobId(global::System.String? input)
+ {
+ if (input is null)
+ {
+ return input;
+ }
+ else
+ {
+ return _stringFormatter.Format(input);
+ }
+ }
+
+ private global::System.Object? FormatPipelineName(global::System.String input)
+ {
+ if (input is null)
+ {
+ throw new global::System.ArgumentNullException(nameof(input));
+ }
+
+ return _stringFormatter.Format(input);
+ }
+
+ private global::System.Object? FormatProjectUrl(global::System.Uri input)
+ {
+ if (input is null)
+ {
+ throw new global::System.ArgumentNullException(nameof(input));
+ }
+
+ return _uRLFormatter.Format(input);
+ }
+
+ private global::System.Object? FormatRepositoryUrl(global::System.Uri? input)
+ {
+ if (input is null)
+ {
+ return input;
+ }
+ else
+ {
+ return _uRLFormatter.Format(input);
+ }
+ }
+
+ private global::System.Object? FormatRunId(global::System.String input)
+ {
+ if (input is null)
+ {
+ throw new global::System.ArgumentNullException(nameof(input));
+ }
+
+ return _stringFormatter.Format(input);
+ }
+
+ private global::System.Object? FormatRunNumber(global::System.String input)
+ {
+ if (input is null)
+ {
+ throw new global::System.ArgumentNullException(nameof(input));
+ }
+
+ return _stringFormatter.Format(input);
+ }
+
+ private global::System.Object? FormatTaskId(global::System.String? input)
+ {
+ if (input is null)
+ {
+ return input;
+ }
+ else
+ {
+ return _stringFormatter.Format(input);
+ }
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.InputTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "0.0.0.0")]
+ internal partial record AzureDevOpsSourceMetadataInput : global::ChilliCream.Nitro.Fusion.Transport.State.IAzureDevOpsSourceMetadataInputInfo
+ {
+ public virtual global::System.Boolean Equals(AzureDevOpsSourceMetadataInput? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (Actor.Equals(other.Actor)) && ((CommitHash is null && other.CommitHash is null) || CommitHash != null && CommitHash.Equals(other.CommitHash)) && ((JobId is null && other.JobId is null) || JobId != null && JobId.Equals(other.JobId)) && PipelineName.Equals(other.PipelineName) && ProjectUrl.Equals(other.ProjectUrl) && ((RepositoryUrl is null && other.RepositoryUrl is null) || RepositoryUrl != null && RepositoryUrl.Equals(other.RepositoryUrl)) && RunId.Equals(other.RunId) && RunNumber.Equals(other.RunNumber) && ((TaskId is null && other.TaskId is null) || TaskId != null && TaskId.Equals(other.TaskId));
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ hash ^= 397 * Actor.GetHashCode();
+ if (CommitHash != null)
+ {
+ hash ^= 397 * CommitHash.GetHashCode();
+ }
+
+ if (JobId != null)
+ {
+ hash ^= 397 * JobId.GetHashCode();
+ }
+
+ hash ^= 397 * PipelineName.GetHashCode();
+ hash ^= 397 * ProjectUrl.GetHashCode();
+ if (RepositoryUrl != null)
+ {
+ hash ^= 397 * RepositoryUrl.GetHashCode();
+ }
+
+ hash ^= 397 * RunId.GetHashCode();
+ hash ^= 397 * RunNumber.GetHashCode();
+ if (TaskId != null)
+ {
+ hash ^= 397 * TaskId.GetHashCode();
+ }
+
+ return hash;
+ }
+ }
+
+ private global::ChilliCream.Nitro.Fusion.Transport.AzureDevOpsActorInput _value_actor = default !;
+ private global::System.Boolean _set_actor;
+ private global::System.String? _value_commitHash;
+ private global::System.Boolean _set_commitHash;
+ private global::System.String? _value_jobId;
+ private global::System.Boolean _set_jobId;
+ private global::System.String _value_pipelineName = default !;
+ private global::System.Boolean _set_pipelineName;
+ private global::System.Uri _value_projectUrl = default !;
+ private global::System.Boolean _set_projectUrl;
+ private global::System.Uri? _value_repositoryUrl;
+ private global::System.Boolean _set_repositoryUrl;
+ private global::System.String _value_runId = default !;
+ private global::System.Boolean _set_runId;
+ private global::System.String _value_runNumber = default !;
+ private global::System.Boolean _set_runNumber;
+ private global::System.String? _value_taskId;
+ private global::System.Boolean _set_taskId;
+ public global::ChilliCream.Nitro.Fusion.Transport.AzureDevOpsActorInput Actor
+ {
+ get => _value_actor;
+ init
+ {
+ _set_actor = true;
+ _value_actor = value;
+ }
+ }
+
+ global::System.Boolean global::ChilliCream.Nitro.Fusion.Transport.State.IAzureDevOpsSourceMetadataInputInfo.IsActorSet => _set_actor;
+
+ public global::System.String? CommitHash
+ {
+ get => _value_commitHash;
+ init
+ {
+ _set_commitHash = true;
+ _value_commitHash = value;
+ }
+ }
+
+ global::System.Boolean global::ChilliCream.Nitro.Fusion.Transport.State.IAzureDevOpsSourceMetadataInputInfo.IsCommitHashSet => _set_commitHash;
+
+ public global::System.String? JobId
+ {
+ get => _value_jobId;
+ init
+ {
+ _set_jobId = true;
+ _value_jobId = value;
+ }
+ }
+
+ global::System.Boolean global::ChilliCream.Nitro.Fusion.Transport.State.IAzureDevOpsSourceMetadataInputInfo.IsJobIdSet => _set_jobId;
+
+ public global::System.String PipelineName
+ {
+ get => _value_pipelineName;
+ init
+ {
+ _set_pipelineName = true;
+ _value_pipelineName = value;
+ }
+ }
+
+ global::System.Boolean global::ChilliCream.Nitro.Fusion.Transport.State.IAzureDevOpsSourceMetadataInputInfo.IsPipelineNameSet => _set_pipelineName;
+
+ public global::System.Uri ProjectUrl
+ {
+ get => _value_projectUrl;
+ init
+ {
+ _set_projectUrl = true;
+ _value_projectUrl = value;
+ }
+ }
+
+ global::System.Boolean global::ChilliCream.Nitro.Fusion.Transport.State.IAzureDevOpsSourceMetadataInputInfo.IsProjectUrlSet => _set_projectUrl;
+
+ public global::System.Uri? RepositoryUrl
+ {
+ get => _value_repositoryUrl;
+ init
+ {
+ _set_repositoryUrl = true;
+ _value_repositoryUrl = value;
+ }
+ }
+
+ global::System.Boolean global::ChilliCream.Nitro.Fusion.Transport.State.IAzureDevOpsSourceMetadataInputInfo.IsRepositoryUrlSet => _set_repositoryUrl;
+
+ public global::System.String RunId
+ {
+ get => _value_runId;
+ init
+ {
+ _set_runId = true;
+ _value_runId = value;
+ }
+ }
+
+ global::System.Boolean global::ChilliCream.Nitro.Fusion.Transport.State.IAzureDevOpsSourceMetadataInputInfo.IsRunIdSet => _set_runId;
+
+ public global::System.String RunNumber
+ {
+ get => _value_runNumber;
+ init
+ {
+ _set_runNumber = true;
+ _value_runNumber = value;
+ }
+ }
+
+ global::System.Boolean global::ChilliCream.Nitro.Fusion.Transport.State.IAzureDevOpsSourceMetadataInputInfo.IsRunNumberSet => _set_runNumber;
+
+ public global::System.String? TaskId
+ {
+ get => _value_taskId;
+ init
+ {
+ _set_taskId = true;
+ _value_taskId = value;
+ }
+ }
+
+ global::System.Boolean global::ChilliCream.Nitro.Fusion.Transport.State.IAzureDevOpsSourceMetadataInputInfo.IsTaskIdSet => _set_taskId;
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.InputValueFormatterGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class AzureDevOpsActorInputInputValueFormatter : global::StrawberryShake.Serialization.IInputObjectFormatter
+ {
+ private global::StrawberryShake.Serialization.IInputValueFormatter _stringFormatter = default !;
+ public global::System.String TypeName => "AzureDevOpsActorInput";
+
+ public void Initialize(global::StrawberryShake.Serialization.ISerializerResolver serializerResolver)
+ {
+ _stringFormatter = serializerResolver.GetInputValueFormatter("String");
+ }
+
+ public global::System.Object? Format(global::System.Object? runtimeValue)
+ {
+ if (runtimeValue is null)
+ {
+ return null;
+ }
+
+ var input = runtimeValue as global::ChilliCream.Nitro.Fusion.Transport.AzureDevOpsActorInput;
+ var inputInfo = runtimeValue as global::ChilliCream.Nitro.Fusion.Transport.State.IAzureDevOpsActorInputInfo;
+ if (input is null || inputInfo is null)
+ {
+ throw new global::System.ArgumentException(nameof(runtimeValue));
+ }
+
+ var fields = new global::System.Collections.Generic.List>();
+ if (inputInfo.IsEmailSet)
+ {
+ fields.Add(new global::System.Collections.Generic.KeyValuePair("email", FormatEmail(input.Email)));
+ }
+
+ if (inputInfo.IsNameSet)
+ {
+ fields.Add(new global::System.Collections.Generic.KeyValuePair("name", FormatName(input.Name)));
+ }
+
+ return fields;
+ }
+
+ private global::System.Object? FormatEmail(global::System.String? input)
+ {
+ if (input is null)
+ {
+ return input;
+ }
+ else
+ {
+ return _stringFormatter.Format(input);
+ }
+ }
+
+ private global::System.Object? FormatName(global::System.String input)
+ {
+ if (input is null)
+ {
+ throw new global::System.ArgumentNullException(nameof(input));
+ }
+
+ return _stringFormatter.Format(input);
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.InputTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "0.0.0.0")]
+ internal partial record AzureDevOpsActorInput : global::ChilliCream.Nitro.Fusion.Transport.State.IAzureDevOpsActorInputInfo
+ {
+ public virtual global::System.Boolean Equals(AzureDevOpsActorInput? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (((Email is null && other.Email is null) || Email != null && Email.Equals(other.Email))) && Name.Equals(other.Name);
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ if (Email != null)
+ {
+ hash ^= 397 * Email.GetHashCode();
+ }
+
+ hash ^= 397 * Name.GetHashCode();
+ return hash;
+ }
+ }
+
+ private global::System.String? _value_email;
+ private global::System.Boolean _set_email;
+ private global::System.String _value_name = default !;
+ private global::System.Boolean _set_name;
+ public global::System.String? Email
+ {
+ get => _value_email;
+ init
+ {
+ _set_email = true;
+ _value_email = value;
+ }
+ }
+
+ global::System.Boolean global::ChilliCream.Nitro.Fusion.Transport.State.IAzureDevOpsActorInputInfo.IsEmailSet => _set_email;
+
+ public global::System.String Name
+ {
+ get => _value_name;
+ init
+ {
+ _set_name = true;
+ _value_name = value;
+ }
+ }
+
+ global::System.Boolean global::ChilliCream.Nitro.Fusion.Transport.State.IAzureDevOpsActorInputInfo.IsNameSet => _set_name;
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.InputValueFormatterGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class GitHubSourceMetadataInputInputValueFormatter : global::StrawberryShake.Serialization.IInputObjectFormatter
+ {
+ private global::StrawberryShake.Serialization.IInputValueFormatter _stringFormatter = default !;
+ private global::StrawberryShake.Serialization.IInputValueFormatter _uRLFormatter = default !;
+ public global::System.String TypeName => "GitHubSourceMetadataInput";
+
+ public void Initialize(global::StrawberryShake.Serialization.ISerializerResolver serializerResolver)
+ {
+ _stringFormatter = serializerResolver.GetInputValueFormatter("String");
+ _uRLFormatter = serializerResolver.GetInputValueFormatter("URL");
+ }
+
+ public global::System.Object? Format(global::System.Object? runtimeValue)
+ {
+ if (runtimeValue is null)
+ {
+ return null;
+ }
+
+ var input = runtimeValue as global::ChilliCream.Nitro.Fusion.Transport.GitHubSourceMetadataInput;
+ var inputInfo = runtimeValue as global::ChilliCream.Nitro.Fusion.Transport.State.IGitHubSourceMetadataInputInfo;
+ if (input is null || inputInfo is null)
+ {
+ throw new global::System.ArgumentException(nameof(runtimeValue));
+ }
+
+ var fields = new global::System.Collections.Generic.List>();
+ if (inputInfo.IsActorSet)
+ {
+ fields.Add(new global::System.Collections.Generic.KeyValuePair("actor", FormatActor(input.Actor)));
+ }
+
+ if (inputInfo.IsCommitHashSet)
+ {
+ fields.Add(new global::System.Collections.Generic.KeyValuePair("commitHash", FormatCommitHash(input.CommitHash)));
+ }
+
+ if (inputInfo.IsJobIdSet)
+ {
+ fields.Add(new global::System.Collections.Generic.KeyValuePair("jobId", FormatJobId(input.JobId)));
+ }
+
+ if (inputInfo.IsRepositoryUrlSet)
+ {
+ fields.Add(new global::System.Collections.Generic.KeyValuePair("repositoryUrl", FormatRepositoryUrl(input.RepositoryUrl)));
+ }
+
+ if (inputInfo.IsRunIdSet)
+ {
+ fields.Add(new global::System.Collections.Generic.KeyValuePair("runId", FormatRunId(input.RunId)));
+ }
+
+ if (inputInfo.IsRunNumberSet)
+ {
+ fields.Add(new global::System.Collections.Generic.KeyValuePair("runNumber", FormatRunNumber(input.RunNumber)));
+ }
+
+ if (inputInfo.IsWorkflowNameSet)
+ {
+ fields.Add(new global::System.Collections.Generic.KeyValuePair("workflowName", FormatWorkflowName(input.WorkflowName)));
+ }
+
+ return fields;
+ }
+
+ private global::System.Object? FormatActor(global::System.String input)
+ {
+ if (input is null)
+ {
+ throw new global::System.ArgumentNullException(nameof(input));
+ }
+
+ return _stringFormatter.Format(input);
+ }
+
+ private global::System.Object? FormatCommitHash(global::System.String input)
+ {
+ if (input is null)
+ {
+ throw new global::System.ArgumentNullException(nameof(input));
+ }
+
+ return _stringFormatter.Format(input);
+ }
+
+ private global::System.Object? FormatJobId(global::System.String? input)
+ {
+ if (input is null)
+ {
+ return input;
+ }
+ else
+ {
+ return _stringFormatter.Format(input);
+ }
+ }
+
+ private global::System.Object? FormatRepositoryUrl(global::System.Uri input)
+ {
+ if (input is null)
+ {
+ throw new global::System.ArgumentNullException(nameof(input));
+ }
+
+ return _uRLFormatter.Format(input);
+ }
+
+ private global::System.Object? FormatRunId(global::System.String input)
+ {
+ if (input is null)
+ {
+ throw new global::System.ArgumentNullException(nameof(input));
+ }
+
+ return _stringFormatter.Format(input);
+ }
+
+ private global::System.Object? FormatRunNumber(global::System.String input)
+ {
+ if (input is null)
+ {
+ throw new global::System.ArgumentNullException(nameof(input));
+ }
+
+ return _stringFormatter.Format(input);
+ }
+
+ private global::System.Object? FormatWorkflowName(global::System.String input)
+ {
+ if (input is null)
+ {
+ throw new global::System.ArgumentNullException(nameof(input));
+ }
+
+ return _stringFormatter.Format(input);
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.InputTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "0.0.0.0")]
+ internal partial record GitHubSourceMetadataInput : global::ChilliCream.Nitro.Fusion.Transport.State.IGitHubSourceMetadataInputInfo
+ {
+ public virtual global::System.Boolean Equals(GitHubSourceMetadataInput? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (Actor.Equals(other.Actor)) && CommitHash.Equals(other.CommitHash) && ((JobId is null && other.JobId is null) || JobId != null && JobId.Equals(other.JobId)) && RepositoryUrl.Equals(other.RepositoryUrl) && RunId.Equals(other.RunId) && RunNumber.Equals(other.RunNumber) && WorkflowName.Equals(other.WorkflowName);
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ hash ^= 397 * Actor.GetHashCode();
+ hash ^= 397 * CommitHash.GetHashCode();
+ if (JobId != null)
+ {
+ hash ^= 397 * JobId.GetHashCode();
+ }
+
+ hash ^= 397 * RepositoryUrl.GetHashCode();
+ hash ^= 397 * RunId.GetHashCode();
+ hash ^= 397 * RunNumber.GetHashCode();
+ hash ^= 397 * WorkflowName.GetHashCode();
+ return hash;
+ }
+ }
+
+ private global::System.String _value_actor = default !;
+ private global::System.Boolean _set_actor;
+ private global::System.String _value_commitHash = default !;
+ private global::System.Boolean _set_commitHash;
+ private global::System.String? _value_jobId;
+ private global::System.Boolean _set_jobId;
+ private global::System.Uri _value_repositoryUrl = default !;
+ private global::System.Boolean _set_repositoryUrl;
+ private global::System.String _value_runId = default !;
+ private global::System.Boolean _set_runId;
+ private global::System.String _value_runNumber = default !;
+ private global::System.Boolean _set_runNumber;
+ private global::System.String _value_workflowName = default !;
+ private global::System.Boolean _set_workflowName;
+ public global::System.String Actor
+ {
+ get => _value_actor;
+ init
+ {
+ _set_actor = true;
+ _value_actor = value;
+ }
+ }
+
+ global::System.Boolean global::ChilliCream.Nitro.Fusion.Transport.State.IGitHubSourceMetadataInputInfo.IsActorSet => _set_actor;
+
+ public global::System.String CommitHash
+ {
+ get => _value_commitHash;
+ init
+ {
+ _set_commitHash = true;
+ _value_commitHash = value;
+ }
+ }
+
+ global::System.Boolean global::ChilliCream.Nitro.Fusion.Transport.State.IGitHubSourceMetadataInputInfo.IsCommitHashSet => _set_commitHash;
+
+ public global::System.String? JobId
+ {
+ get => _value_jobId;
+ init
+ {
+ _set_jobId = true;
+ _value_jobId = value;
+ }
+ }
+
+ global::System.Boolean global::ChilliCream.Nitro.Fusion.Transport.State.IGitHubSourceMetadataInputInfo.IsJobIdSet => _set_jobId;
+
+ public global::System.Uri RepositoryUrl
+ {
+ get => _value_repositoryUrl;
+ init
+ {
+ _set_repositoryUrl = true;
+ _value_repositoryUrl = value;
+ }
+ }
+
+ global::System.Boolean global::ChilliCream.Nitro.Fusion.Transport.State.IGitHubSourceMetadataInputInfo.IsRepositoryUrlSet => _set_repositoryUrl;
+
+ public global::System.String RunId
+ {
+ get => _value_runId;
+ init
+ {
+ _set_runId = true;
+ _value_runId = value;
+ }
+ }
+
+ global::System.Boolean global::ChilliCream.Nitro.Fusion.Transport.State.IGitHubSourceMetadataInputInfo.IsRunIdSet => _set_runId;
+
+ public global::System.String RunNumber
+ {
+ get => _value_runNumber;
+ init
+ {
+ _set_runNumber = true;
+ _value_runNumber = value;
+ }
+ }
+
+ global::System.Boolean global::ChilliCream.Nitro.Fusion.Transport.State.IGitHubSourceMetadataInputInfo.IsRunNumberSet => _set_runNumber;
+
+ public global::System.String WorkflowName
+ {
+ get => _value_workflowName;
+ init
+ {
+ _set_workflowName = true;
+ _value_workflowName = value;
+ }
+ }
+
+ global::System.Boolean global::ChilliCream.Nitro.Fusion.Transport.State.IGitHubSourceMetadataInputInfo.IsWorkflowNameSet => _set_workflowName;
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.InputValueFormatterGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class BeginFusionConfigurationPublishInputInputValueFormatter : global::StrawberryShake.Serialization.IInputObjectFormatter
+ {
+ private global::StrawberryShake.Serialization.IInputValueFormatter _iDFormatter = default !;
+ private global::StrawberryShake.Serialization.IInputValueFormatter _sourceMetadataInputFormatter = default !;
+ private global::StrawberryShake.Serialization.IInputValueFormatter _stringFormatter = default !;
+ private global::StrawberryShake.Serialization.IInputValueFormatter _fusionSubgraphVersionInputFormatter = default !;
+ private global::StrawberryShake.Serialization.IInputValueFormatter _booleanFormatter = default !;
+ public global::System.String TypeName => "BeginFusionConfigurationPublishInput";
+
+ public void Initialize(global::StrawberryShake.Serialization.ISerializerResolver serializerResolver)
+ {
+ _iDFormatter = serializerResolver.GetInputValueFormatter("ID");
+ _sourceMetadataInputFormatter = serializerResolver.GetInputValueFormatter("SourceMetadataInput");
+ _stringFormatter = serializerResolver.GetInputValueFormatter("String");
+ _fusionSubgraphVersionInputFormatter = serializerResolver.GetInputValueFormatter("FusionSubgraphVersionInput");
+ _booleanFormatter = serializerResolver.GetInputValueFormatter("Boolean");
+ }
+
+ public global::System.Object? Format(global::System.Object? runtimeValue)
+ {
+ if (runtimeValue is null)
+ {
+ return null;
+ }
+
+ var input = runtimeValue as global::ChilliCream.Nitro.Fusion.Transport.BeginFusionConfigurationPublishInput;
+ var inputInfo = runtimeValue as global::ChilliCream.Nitro.Fusion.Transport.State.IBeginFusionConfigurationPublishInputInfo;
+ if (input is null || inputInfo is null)
+ {
+ throw new global::System.ArgumentException(nameof(runtimeValue));
+ }
+
+ var fields = new global::System.Collections.Generic.List>();
+ if (inputInfo.IsApiIdSet)
+ {
+ fields.Add(new global::System.Collections.Generic.KeyValuePair("apiId", FormatApiId(input.ApiId)));
+ }
+
+ if (inputInfo.IsSourceSet)
+ {
+ fields.Add(new global::System.Collections.Generic.KeyValuePair("source", FormatSource(input.Source)));
+ }
+
+ if (inputInfo.IsStageNameSet)
+ {
+ fields.Add(new global::System.Collections.Generic.KeyValuePair("stageName", FormatStageName(input.StageName)));
+ }
+
+ if (inputInfo.IsSubgraphApiIdSet)
+ {
+ fields.Add(new global::System.Collections.Generic.KeyValuePair("subgraphApiId", FormatSubgraphApiId(input.SubgraphApiId)));
+ }
+
+ if (inputInfo.IsSubgraphNameSet)
+ {
+ fields.Add(new global::System.Collections.Generic.KeyValuePair("subgraphName", FormatSubgraphName(input.SubgraphName)));
+ }
+
+ if (inputInfo.IsSubgraphsSet)
+ {
+ fields.Add(new global::System.Collections.Generic.KeyValuePair("subgraphs", FormatSubgraphs(input.Subgraphs)));
+ }
+
+ if (inputInfo.IsTagSet)
+ {
+ fields.Add(new global::System.Collections.Generic.KeyValuePair("tag", FormatTag(input.Tag)));
+ }
+
+ if (inputInfo.IsWaitForApprovalSet)
+ {
+ fields.Add(new global::System.Collections.Generic.KeyValuePair("waitForApproval", FormatWaitForApproval(input.WaitForApproval)));
+ }
+
+ return fields;
+ }
+
+ private global::System.Object? FormatApiId(global::System.String input)
+ {
+ if (input is null)
+ {
+ throw new global::System.ArgumentNullException(nameof(input));
+ }
+
+ return _iDFormatter.Format(input);
+ }
+
+ private global::System.Object? FormatSource(global::ChilliCream.Nitro.Fusion.Transport.SourceMetadataInput? input)
+ {
+ if (input is null)
+ {
+ return input;
+ }
+ else
+ {
+ return _sourceMetadataInputFormatter.Format(input);
+ }
+ }
+
+ private global::System.Object? FormatStageName(global::System.String input)
+ {
+ if (input is null)
+ {
+ throw new global::System.ArgumentNullException(nameof(input));
+ }
+
+ return _stringFormatter.Format(input);
+ }
+
+ private global::System.Object? FormatSubgraphApiId(global::System.String? input)
+ {
+ if (input is null)
+ {
+ return input;
+ }
+ else
+ {
+ return _iDFormatter.Format(input);
+ }
+ }
+
+ private global::System.Object? FormatSubgraphName(global::System.String? input)
+ {
+ if (input is null)
+ {
+ return input;
+ }
+ else
+ {
+ return _stringFormatter.Format(input);
+ }
+ }
+
+ private global::System.Object? FormatSubgraphs(global::System.Collections.Generic.IReadOnlyList? input)
+ {
+ if (input is null)
+ {
+ return input;
+ }
+ else
+ {
+ var input_list = new global::System.Collections.Generic.List();
+ foreach (var input_elm in input)
+ {
+ if (input_elm is null)
+ {
+ throw new global::System.ArgumentNullException(nameof(input_elm));
+ }
+
+ input_list.Add(_fusionSubgraphVersionInputFormatter.Format(input_elm));
+ }
+
+ return input_list;
+ }
+ }
+
+ private global::System.Object? FormatTag(global::System.String input)
+ {
+ if (input is null)
+ {
+ throw new global::System.ArgumentNullException(nameof(input));
+ }
+
+ return _stringFormatter.Format(input);
+ }
+
+ private global::System.Object? FormatWaitForApproval(global::System.Boolean? input)
+ {
+ if (input is null)
+ {
+ return input;
+ }
+ else
+ {
+ return _booleanFormatter.Format(input);
+ }
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.InputTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "0.0.0.0")]
+ internal partial record BeginFusionConfigurationPublishInput : global::ChilliCream.Nitro.Fusion.Transport.State.IBeginFusionConfigurationPublishInputInfo
+ {
+ public virtual global::System.Boolean Equals(BeginFusionConfigurationPublishInput? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (ApiId.Equals(other.ApiId)) && ((Source is null && other.Source is null) || Source != null && Source.Equals(other.Source)) && StageName.Equals(other.StageName) && ((SubgraphApiId is null && other.SubgraphApiId is null) || SubgraphApiId != null && SubgraphApiId.Equals(other.SubgraphApiId)) && ((SubgraphName is null && other.SubgraphName is null) || SubgraphName != null && SubgraphName.Equals(other.SubgraphName)) && global::StrawberryShake.Internal.ComparisonHelper.SequenceEqual(Subgraphs, other.Subgraphs) && Tag.Equals(other.Tag) && global::System.Object.Equals(WaitForApproval, other.WaitForApproval);
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ hash ^= 397 * ApiId.GetHashCode();
+ if (Source != null)
+ {
+ hash ^= 397 * Source.GetHashCode();
+ }
+
+ hash ^= 397 * StageName.GetHashCode();
+ if (SubgraphApiId != null)
+ {
+ hash ^= 397 * SubgraphApiId.GetHashCode();
+ }
+
+ if (SubgraphName != null)
+ {
+ hash ^= 397 * SubgraphName.GetHashCode();
+ }
+
+ if (Subgraphs != null)
+ {
+ foreach (var Subgraphs_elm in Subgraphs)
+ {
+ hash ^= 397 * Subgraphs_elm.GetHashCode();
+ }
+ }
+
+ hash ^= 397 * Tag.GetHashCode();
+ if (WaitForApproval != null)
+ {
+ hash ^= 397 * WaitForApproval.GetHashCode();
+ }
+
+ return hash;
+ }
+ }
+
+ private global::System.String _value_apiId = default !;
+ private global::System.Boolean _set_apiId;
+ private global::ChilliCream.Nitro.Fusion.Transport.SourceMetadataInput? _value_source;
+ private global::System.Boolean _set_source;
+ private global::System.String _value_stageName = default !;
+ private global::System.Boolean _set_stageName;
+ private global::System.String? _value_subgraphApiId;
+ private global::System.Boolean _set_subgraphApiId;
+ private global::System.String? _value_subgraphName;
+ private global::System.Boolean _set_subgraphName;
+ private global::System.Collections.Generic.IReadOnlyList? _value_subgraphs;
+ private global::System.Boolean _set_subgraphs;
+ private global::System.String _value_tag = default !;
+ private global::System.Boolean _set_tag;
+ private global::System.Boolean? _value_waitForApproval;
+ private global::System.Boolean _set_waitForApproval;
+ public global::System.String ApiId
+ {
+ get => _value_apiId;
+ init
+ {
+ _set_apiId = true;
+ _value_apiId = value;
+ }
+ }
+
+ global::System.Boolean global::ChilliCream.Nitro.Fusion.Transport.State.IBeginFusionConfigurationPublishInputInfo.IsApiIdSet => _set_apiId;
+
+ public global::ChilliCream.Nitro.Fusion.Transport.SourceMetadataInput? Source
+ {
+ get => _value_source;
+ init
+ {
+ _set_source = true;
+ _value_source = value;
+ }
+ }
+
+ global::System.Boolean global::ChilliCream.Nitro.Fusion.Transport.State.IBeginFusionConfigurationPublishInputInfo.IsSourceSet => _set_source;
+
+ public global::System.String StageName
+ {
+ get => _value_stageName;
+ init
+ {
+ _set_stageName = true;
+ _value_stageName = value;
+ }
+ }
+
+ global::System.Boolean global::ChilliCream.Nitro.Fusion.Transport.State.IBeginFusionConfigurationPublishInputInfo.IsStageNameSet => _set_stageName;
+
+ public global::System.String? SubgraphApiId
+ {
+ get => _value_subgraphApiId;
+ init
+ {
+ _set_subgraphApiId = true;
+ _value_subgraphApiId = value;
+ }
+ }
+
+ global::System.Boolean global::ChilliCream.Nitro.Fusion.Transport.State.IBeginFusionConfigurationPublishInputInfo.IsSubgraphApiIdSet => _set_subgraphApiId;
+
+ public global::System.String? SubgraphName
+ {
+ get => _value_subgraphName;
+ init
+ {
+ _set_subgraphName = true;
+ _value_subgraphName = value;
+ }
+ }
+
+ global::System.Boolean global::ChilliCream.Nitro.Fusion.Transport.State.IBeginFusionConfigurationPublishInputInfo.IsSubgraphNameSet => _set_subgraphName;
+
+ public global::System.Collections.Generic.IReadOnlyList? Subgraphs
+ {
+ get => _value_subgraphs;
+ init
+ {
+ _set_subgraphs = true;
+ _value_subgraphs = value;
+ }
+ }
+
+ global::System.Boolean global::ChilliCream.Nitro.Fusion.Transport.State.IBeginFusionConfigurationPublishInputInfo.IsSubgraphsSet => _set_subgraphs;
+
+ public global::System.String Tag
+ {
+ get => _value_tag;
+ init
+ {
+ _set_tag = true;
+ _value_tag = value;
+ }
+ }
+
+ global::System.Boolean global::ChilliCream.Nitro.Fusion.Transport.State.IBeginFusionConfigurationPublishInputInfo.IsTagSet => _set_tag;
+
+ public global::System.Boolean? WaitForApproval
+ {
+ get => _value_waitForApproval;
+ init
+ {
+ _set_waitForApproval = true;
+ _value_waitForApproval = value;
+ }
+ }
+
+ global::System.Boolean global::ChilliCream.Nitro.Fusion.Transport.State.IBeginFusionConfigurationPublishInputInfo.IsWaitForApprovalSet => _set_waitForApproval;
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.InputValueFormatterGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class FusionSubgraphVersionInputInputValueFormatter : global::StrawberryShake.Serialization.IInputObjectFormatter
+ {
+ private global::StrawberryShake.Serialization.IInputValueFormatter _stringFormatter = default !;
+ public global::System.String TypeName => "FusionSubgraphVersionInput";
+
+ public void Initialize(global::StrawberryShake.Serialization.ISerializerResolver serializerResolver)
+ {
+ _stringFormatter = serializerResolver.GetInputValueFormatter("String");
+ }
+
+ public global::System.Object? Format(global::System.Object? runtimeValue)
+ {
+ if (runtimeValue is null)
+ {
+ return null;
+ }
+
+ var input = runtimeValue as global::ChilliCream.Nitro.Fusion.Transport.FusionSubgraphVersionInput;
+ var inputInfo = runtimeValue as global::ChilliCream.Nitro.Fusion.Transport.State.IFusionSubgraphVersionInputInfo;
+ if (input is null || inputInfo is null)
+ {
+ throw new global::System.ArgumentException(nameof(runtimeValue));
+ }
+
+ var fields = new global::System.Collections.Generic.List>();
+ if (inputInfo.IsNameSet)
+ {
+ fields.Add(new global::System.Collections.Generic.KeyValuePair("name", FormatName(input.Name)));
+ }
+
+ if (inputInfo.IsTagSet)
+ {
+ fields.Add(new global::System.Collections.Generic.KeyValuePair("tag", FormatTag(input.Tag)));
+ }
+
+ return fields;
+ }
+
+ private global::System.Object? FormatName(global::System.String input)
+ {
+ if (input is null)
+ {
+ throw new global::System.ArgumentNullException(nameof(input));
+ }
+
+ return _stringFormatter.Format(input);
+ }
+
+ private global::System.Object? FormatTag(global::System.String input)
+ {
+ if (input is null)
+ {
+ throw new global::System.ArgumentNullException(nameof(input));
+ }
+
+ return _stringFormatter.Format(input);
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.InputTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "0.0.0.0")]
+ internal partial record FusionSubgraphVersionInput : global::ChilliCream.Nitro.Fusion.Transport.State.IFusionSubgraphVersionInputInfo
+ {
+ public virtual global::System.Boolean Equals(FusionSubgraphVersionInput? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (Name.Equals(other.Name)) && Tag.Equals(other.Tag);
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ hash ^= 397 * Name.GetHashCode();
+ hash ^= 397 * Tag.GetHashCode();
+ return hash;
+ }
+ }
+
+ private global::System.String _value_name = default !;
+ private global::System.Boolean _set_name;
+ private global::System.String _value_tag = default !;
+ private global::System.Boolean _set_tag;
+ public global::System.String Name
+ {
+ get => _value_name;
+ init
+ {
+ _set_name = true;
+ _value_name = value;
+ }
+ }
+
+ global::System.Boolean global::ChilliCream.Nitro.Fusion.Transport.State.IFusionSubgraphVersionInputInfo.IsNameSet => _set_name;
+
+ public global::System.String Tag
+ {
+ get => _value_tag;
+ init
+ {
+ _set_tag = true;
+ _value_tag = value;
+ }
+ }
+
+ global::System.Boolean global::ChilliCream.Nitro.Fusion.Transport.State.IFusionSubgraphVersionInputInfo.IsTagSet => _set_tag;
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.InputValueFormatterGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class StartFusionConfigurationCompositionInputInputValueFormatter : global::StrawberryShake.Serialization.IInputObjectFormatter
+ {
+ private global::StrawberryShake.Serialization.IInputValueFormatter _iDFormatter = default !;
+ public global::System.String TypeName => "StartFusionConfigurationCompositionInput";
+
+ public void Initialize(global::StrawberryShake.Serialization.ISerializerResolver serializerResolver)
+ {
+ _iDFormatter = serializerResolver.GetInputValueFormatter("ID");
+ }
+
+ public global::System.Object? Format(global::System.Object? runtimeValue)
+ {
+ if (runtimeValue is null)
+ {
+ return null;
+ }
+
+ var input = runtimeValue as global::ChilliCream.Nitro.Fusion.Transport.StartFusionConfigurationCompositionInput;
+ var inputInfo = runtimeValue as global::ChilliCream.Nitro.Fusion.Transport.State.IStartFusionConfigurationCompositionInputInfo;
+ if (input is null || inputInfo is null)
+ {
+ throw new global::System.ArgumentException(nameof(runtimeValue));
+ }
+
+ var fields = new global::System.Collections.Generic.List>();
+ if (inputInfo.IsRequestIdSet)
+ {
+ fields.Add(new global::System.Collections.Generic.KeyValuePair("requestId", FormatRequestId(input.RequestId)));
+ }
+
+ return fields;
+ }
+
+ private global::System.Object? FormatRequestId(global::System.String input)
+ {
+ if (input is null)
+ {
+ throw new global::System.ArgumentNullException(nameof(input));
+ }
+
+ return _iDFormatter.Format(input);
+ }
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.InputTypeGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "0.0.0.0")]
+ internal partial record StartFusionConfigurationCompositionInput : global::ChilliCream.Nitro.Fusion.Transport.State.IStartFusionConfigurationCompositionInputInfo
+ {
+ public virtual global::System.Boolean Equals(StartFusionConfigurationCompositionInput? other)
+ {
+ if (ReferenceEquals(null, other))
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, other))
+ {
+ return true;
+ }
+
+ if (other.GetType() != GetType())
+ {
+ return false;
+ }
+
+ return (RequestId.Equals(other.RequestId));
+ }
+
+ public override global::System.Int32 GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 5;
+ hash ^= 397 * RequestId.GetHashCode();
+ return hash;
+ }
+ }
+
+ private global::System.String _value_requestId = default !;
+ private global::System.Boolean _set_requestId;
+ public global::System.String RequestId
+ {
+ get => _value_requestId;
+ init
+ {
+ _set_requestId = true;
+ _value_requestId = value;
+ }
+ }
+
+ global::System.Boolean global::ChilliCream.Nitro.Fusion.Transport.State.IStartFusionConfigurationCompositionInputInfo.IsRequestIdSet => _set_requestId;
+ }
+
+ // StrawberryShake.CodeGeneration.CSharp.Generators.InputValueFormatterGenerator
+ [global::System.CodeDom.Compiler.GeneratedCode("StrawberryShake", "11.0.0")]
+ internal partial class CancelFusionConfigurationCompositionInputInputValueFormatter : global::StrawberryShake.Serialization.IInputObjectFormatter
+ {
+ private global::StrawberryShake.Serialization.IInputValueFormatter _iDFormatter = default !;
+ public global::System.String TypeName => "CancelFusionConfigurationCompositionInput";
+
+ public void Initialize(global::StrawberryShake.Serialization.ISerializerResolver serializerResolver)
+ {
+ _iDFormatter = serializerResolver.GetInputValueFormatter("ID");
+ }
+
+ public global::System.Object? Format(global::System.Object? runtimeValue)
+ {
+ if (runtimeValue is null)
+ {
+ return null;
+ }
+
+ var input = runtimeValue as global::ChilliCream.Nitro.Fusion.Transport.CancelFusionConfigurationCompositionInput;
+ var inputInfo = runtimeValue as global::ChilliCream.Nitro.Fusion.Transport.State.ICancelFusionConfigurationCompositionInputInfo;
+ if (input is null || inputInfo is null)
+ {
+ throw new global::System.ArgumentException(nameof(runtimeValue));
+ }
+
+ var fields = new global::System.Collections.Generic.List>();
+ if (inputInfo.IsRequestIdSet)
+ {
+ fields.Add(new global::System.Collections.Generic.KeyValuePair