295150751f
The Test Run sandbox and Monaco analysis modelled a script API that had drifted from the site runtime's ScriptGlobals, so real scripts failed to compile in Test Run. Realign both to the runtime surface (Instance/Scripts/ExternalSystem/Attributes/Children/Parent) and drop the duplicate ScriptHost stub so the two cannot diverge again. - Script calls (Scripts.CallShared, Instance.CallScript, Route.To().Call) accept an anonymous object instead of a hand-built dictionary, via a shared ScriptArgs normalizer; existing dictionary calls still compile. - Test Run can optionally bind to a deployed instance, so Instance/ Attributes/CallScript route to it cross-site; adds site-side RouteToGetAttributes/RouteToSetAttributes handlers. - Adds Test Run panels to the API method and template script editors. - Fixes the TestDatabaseQuery seed script, which queried a table that never existed. Also commits unrelated in-progress work already in the tree: the health monitoring report loop, site streaming changes, and the Admin/Design data-connection and SMTP page reorganization.
119 lines
4.3 KiB
C#
119 lines
4.3 KiB
C#
using System.Data.Common;
|
|
using ScadaLink.Commons.Interfaces.Services;
|
|
|
|
namespace ScadaLink.CentralUI.ScriptAnalysis;
|
|
|
|
/// <summary>
|
|
/// User-facing surface for <c>ExternalSystem.Call</c> /
|
|
/// <c>ExternalSystem.CachedCall</c> 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
|
|
/// <see cref="ScriptSandboxException"/>; with a real client wired in (a Test
|
|
/// Run) calls hit the live HTTP path.
|
|
/// </summary>
|
|
public class SandboxExternalHelper
|
|
{
|
|
private readonly IExternalSystemClient? _client;
|
|
private readonly string _instanceName;
|
|
|
|
public SandboxExternalHelper(IExternalSystemClient? client, string instanceName)
|
|
{
|
|
_client = client;
|
|
_instanceName = instanceName;
|
|
}
|
|
|
|
public Task<ExternalCallResult> Call(
|
|
string systemName,
|
|
string methodName,
|
|
IReadOnlyDictionary<string, object?>? 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<ExternalCallResult> CachedCall(
|
|
string systemName,
|
|
string methodName,
|
|
IReadOnlyDictionary<string, object?>? 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<DbConnection> 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<string, object?>? 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<NotificationResult> 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);
|
|
}
|
|
}
|