feat(transport): name-map types + preview/selection/summary extensions (M8 A1)

This commit is contained in:
Joseph Doherty
2026-06-18 05:40:24 -04:00
parent 2f3c1a4e64
commit 4f1925870f
5 changed files with 233 additions and 3 deletions
@@ -0,0 +1,53 @@
namespace ZB.MOM.WW.ScadaBridge.Commons.Types.Transport;
/// <summary>
/// How a source-environment site or connection referenced by an incoming bundle is
/// resolved against the destination environment during import.
/// </summary>
public enum MappingAction
{
/// <summary>Bind the source name to an existing destination site/connection
/// (the corresponding <c>Target*</c> identifier is required).</summary>
MapToExisting,
/// <summary>Create a new destination site/connection from the bundle's payload
/// (the corresponding <c>Target*</c> identifier is left null).</summary>
CreateNew,
}
/// <summary>
/// Resolves one site referenced by an incoming bundle (M8 site/instance-scoped
/// transport). <paramref name="TargetSiteIdentifier"/> is required when
/// <paramref name="Action"/> is <see cref="MappingAction.MapToExisting"/> and null
/// when it is <see cref="MappingAction.CreateNew"/>.
/// </summary>
public sealed record SiteMapping(
string SourceSiteIdentifier,
MappingAction Action,
string? TargetSiteIdentifier);
/// <summary>
/// Resolves one data connection (scoped to a source site) referenced by an incoming
/// bundle. <paramref name="TargetConnectionName"/> is required when
/// <paramref name="Action"/> is <see cref="MappingAction.MapToExisting"/> and null
/// when it is <see cref="MappingAction.CreateNew"/>.
/// </summary>
public sealed record ConnectionMapping(
string SourceSiteIdentifier,
string SourceConnectionName,
MappingAction Action,
string? TargetConnectionName);
/// <summary>
/// The operator-supplied resolution of every source-environment site and connection
/// name an incoming bundle references, applied during import. Crosses the Central UI ⇆
/// ManagementActor boundary via System.Text.Json.
/// </summary>
public sealed record BundleNameMap(
IReadOnlyList<SiteMapping> Sites,
IReadOnlyList<ConnectionMapping> Connections)
{
/// <summary>An empty map (no site or connection mappings).</summary>
public static BundleNameMap Empty { get; } =
new(Array.Empty<SiteMapping>(), Array.Empty<ConnectionMapping>());
}
@@ -10,4 +10,9 @@ public sealed record BundleSummary(
int DbConnections,
int NotificationLists,
int SmtpConfigs,
int ApiMethods);
int ApiMethods,
// Additive (M8 A1): site/instance-scoped artifacts. Defaulted to 0 so manifests
// written by older exporters (which omit these JSON properties) deserialize fine.
int Sites = 0,
int DataConnections = 0,
int Instances = 0);
@@ -13,4 +13,15 @@ public sealed record ExportSelection(
IReadOnlyList<int> NotificationListIds,
IReadOnlyList<int> SmtpConfigurationIds,
IReadOnlyList<int> ApiMethodIds,
bool IncludeDependencies);
bool IncludeDependencies,
// Additive (M8 A1): site/instance-scoped export. Defaulted to empty so every
// existing positional caller keeps compiling; older callers select no sites/instances.
IReadOnlyList<int>? SiteIds = null,
IReadOnlyList<int>? InstanceIds = null)
{
/// <summary>Sites selected for site/instance-scoped export (M8). Never null.</summary>
public IReadOnlyList<int> SiteIds { get; init; } = SiteIds ?? Array.Empty<int>();
/// <summary>Instances selected for site/instance-scoped export (M8). Never null.</summary>
public IReadOnlyList<int> InstanceIds { get; init; } = InstanceIds ?? Array.Empty<int>();
}
@@ -11,6 +11,40 @@ public sealed record ImportPreviewItem(
string? FieldDiffJson,
string? BlockerReason);
/// <summary>
/// A site reference in an incoming bundle that the operator must resolve before import
/// (M8 A1). <paramref name="AutoMatchTargetIdentifier"/> is the destination site the
/// importer auto-matched by identifier, or null when no match was found.
/// </summary>
public sealed record RequiredSiteMapping(
string SourceSiteIdentifier,
string SourceSiteName,
string? AutoMatchTargetIdentifier);
/// <summary>
/// A connection reference (scoped to a source site) in an incoming bundle that the
/// operator must resolve before import (M8 A1). <paramref name="AutoMatchTargetName"/>
/// is the destination connection the importer auto-matched by name, or null when no
/// match was found.
/// </summary>
public sealed record RequiredConnectionMapping(
string SourceSiteIdentifier,
string SourceConnectionName,
string? AutoMatchTargetName);
public sealed record ImportPreview(
Guid SessionId,
IReadOnlyList<ImportPreviewItem> Items);
IReadOnlyList<ImportPreviewItem> Items,
// Additive (M8 A1): site/connection references the operator must resolve before
// applying. Defaulted to empty so every existing positional caller keeps compiling.
IReadOnlyList<RequiredSiteMapping>? RequiredSiteMappings = null,
IReadOnlyList<RequiredConnectionMapping>? RequiredConnectionMappings = null)
{
/// <summary>Site references the operator must resolve before import (M8). Never null.</summary>
public IReadOnlyList<RequiredSiteMapping> RequiredSiteMappings { get; init; } =
RequiredSiteMappings ?? Array.Empty<RequiredSiteMapping>();
/// <summary>Connection references the operator must resolve before import (M8). Never null.</summary>
public IReadOnlyList<RequiredConnectionMapping> RequiredConnectionMappings { get; init; } =
RequiredConnectionMappings ?? Array.Empty<RequiredConnectionMapping>();
}