using System.Data.Common; using ScadaLink.Commons.Interfaces.Services; namespace ScadaLink.CentralUI.ScriptAnalysis; /// /// User-facing surface for ExternalSystem.Call / /// ExternalSystem.CachedCall inside a Test Run. Mirrors /// ExternalSystemHelper in ScadaLink.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; public SandboxExternalHelper(IExternalSystemClient? client, string instanceName) { _client = client; _instanceName = instanceName; } 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); } 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); } } public class SandboxDatabaseHelper { private readonly IDatabaseGateway? _gateway; private readonly string _instanceName; public SandboxDatabaseHelper(IDatabaseGateway? gateway, string instanceName) { _gateway = gateway; _instanceName = instanceName; } 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); } 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); } } public class SandboxNotifyHelper { private readonly INotificationDeliveryService? _service; private readonly string _instanceName; public SandboxNotifyHelper(INotificationDeliveryService? service, string instanceName) { _service = service; _instanceName = instanceName; } public SandboxNotifyTarget To(string listName) => new(listName, _service, _instanceName); } public class SandboxNotifyTarget { private readonly string _listName; private readonly INotificationDeliveryService? _service; private readonly string _instanceName; internal SandboxNotifyTarget(string listName, INotificationDeliveryService? service, string instanceName) { _listName = listName; _service = service; _instanceName = instanceName; } public Task Send(string subject, string message, CancellationToken cancellationToken = default) { if (_service == null) throw new ScriptSandboxException( $"Notify.To(\"{_listName}\").Send(...) — notification service not configured for Test Run."); return _service.SendAsync(_listName, subject, message, _instanceName, cancellationToken); } }