using System.Data.Common; using ZB.MOM.WW.ScadaBridge.Commons.Interfaces.Services; using ZB.MOM.WW.ScadaBridge.Commons.Messages.Notification; namespace ZB.MOM.WW.ScadaBridge.CentralUI.ScriptAnalysis; /// /// User-facing surface for ExternalSystem.Call / /// ExternalSystem.CachedCall inside a Test Run. Mirrors /// ExternalSystemHelper in ZB.MOM.WW.ScadaBridge.SiteRuntime.Scripts.ScriptRuntimeContext /// so the same user code compiles against both. When constructed with a null /// client (the editor's metadata-only analysis pass) every call throws /// ; with a real client wired in (a Test /// Run) calls hit the live HTTP path. /// public class SandboxExternalHelper { private readonly IExternalSystemClient? _client; private readonly string _instanceName; /// Initializes a new instance of the SandboxExternalHelper class. /// Optional external system client for test runs. /// The instance name context. public SandboxExternalHelper(IExternalSystemClient? client, string instanceName) { _client = client; _instanceName = instanceName; } /// Invokes a synchronous external system call. /// The external system name. /// The method name to invoke. /// Optional method parameters. /// Cancellation token. /// A task that resolves to the from the external system. public Task Call( string systemName, string methodName, IReadOnlyDictionary? parameters = null, CancellationToken cancellationToken = default) { if (_client == null) throw new ScriptSandboxException( $"External.Call(\"{systemName}\", \"{methodName}\") — external system client not configured for Test Run."); return _client.CallAsync(systemName, methodName, parameters, cancellationToken); } /// Invokes a cached external system call. /// The external system name. /// The method name to invoke. /// Optional method parameters. /// Cancellation token. /// A task that resolves to the from the external system. public Task CachedCall( string systemName, string methodName, IReadOnlyDictionary? parameters = null, CancellationToken cancellationToken = default) { if (_client == null) throw new ScriptSandboxException( $"External.CachedCall(\"{systemName}\", \"{methodName}\") — external system client not configured for Test Run."); return _client.CachedCallAsync(systemName, methodName, parameters, _instanceName, cancellationToken); } } /// Sandbox database helper for script analysis. public class SandboxDatabaseHelper { private readonly IDatabaseGateway? _gateway; private readonly string _instanceName; /// Initializes a new instance of the SandboxDatabaseHelper class. /// Optional database gateway for test runs. /// The instance name context. public SandboxDatabaseHelper(IDatabaseGateway? gateway, string instanceName) { _gateway = gateway; _instanceName = instanceName; } /// Gets a database connection by name. /// The database connection name. /// Cancellation token. /// A task that resolves to the open for the named database. public Task Connection(string name, CancellationToken cancellationToken = default) { if (_gateway == null) throw new ScriptSandboxException( $"Database.Connection(\"{name}\") — database gateway not configured for Test Run."); return _gateway.GetConnectionAsync(name, cancellationToken); } /// Executes a cached database write operation. /// The database connection name. /// The SQL statement to execute. /// Optional SQL parameters. /// Cancellation token. /// A task that represents the asynchronous operation. public Task CachedWrite( string name, string sql, IReadOnlyDictionary? parameters = null, CancellationToken cancellationToken = default) { if (_gateway == null) throw new ScriptSandboxException( $"Database.CachedWrite(\"{name}\") — database gateway not configured for Test Run."); return _gateway.CachedWriteAsync(name, sql, parameters, _instanceName, cancellationToken); } } /// /// Sandbox mirror of ZB.MOM.WW.ScadaBridge.SiteRuntime.Scripts.NotifyHelper — the /// Notify global. Signature-faithful to production so the same user code /// (Notify.To(...).Send(...) / Notify.Status(...)) compiles /// identically against both surfaces. /// /// In the Notification Outbox design production no longer delivers notification /// email inline — Notify.Send enqueues into the site Store-and-Forward /// Engine and returns a NotificationId. The sandbox has no S&F engine /// and no central, so it is a pure no-op fake: Send returns a generated /// fake id and Status returns a placeholder . /// Nothing is delivered. /// public class SandboxNotifyHelper { /// Selects the notification list to send to. /// The notification list name. /// A for the specified list. public SandboxNotifyTarget To(string listName) => new(); /// /// Queries the delivery status of a previously-sent notification. The /// sandbox never delivers, so this always reports the placeholder /// Unknown status — it exists for signature fidelity with /// NotifyHelper.Status. /// /// The notification ID to check status for. /// A task that resolves to a placeholder with status "Unknown". public Task Status(string notificationId) => Task.FromResult(new NotificationDeliveryStatus("Unknown", 0, null, null)); } /// /// Sandbox mirror of ZB.MOM.WW.ScadaBridge.SiteRuntime.Scripts.NotifyTarget — the /// target of Notify.To("listName"). /// public class SandboxNotifyTarget { /// Initializes a new instance of the SandboxNotifyTarget class. internal SandboxNotifyTarget() { } /// /// Mirrors NotifyTarget.Send — returns a NotificationId. In /// the sandbox nothing is enqueued or delivered; a fake id is returned so /// the call type-checks identically to production. /// /// The notification subject. /// The notification message. /// Cancellation token. /// A task that resolves to a fake notification ID string (a random GUID). public Task Send(string subject, string message, CancellationToken cancellationToken = default) => Task.FromResult(Guid.NewGuid().ToString("N")); }