Skip to content

C# Analysis Service SDK

The DxWorks.ScriptBee.Analysis.Sdk NuGet package is the C# implementation of the Analysis Service SDK. It lets you build a fully-featured Analysis Service in .NET without writing any HTTP boilerplate.

Installation

bash
dotnet add package DxWorks.ScriptBee.Analysis.Sdk

Or directly in your .csproj:

xml
<PackageReference Include="DxWorks.ScriptBee.Analysis.Sdk" Version="1.0.0" />

What the SDK provides

LayerWhat's included
EndpointsAll REST routes pre-wired with correct HTTP verbs, paths, and status codes
ContractsWeb* request/response records matching the public REST API
ValidatorsFluentValidation rules for all request models
AbstractionsUse-case interfaces your service must implement
UtilitiesFileBundler for packaging file streams for loader plugins
RegistrationAddAnalysisEndpoints() extension to mount everything in one call

Implementing the use cases

Implement each interface from the DxWorks.ScriptBee.Analysis.Sdk namespace. The SDK resolves them from the DI container at runtime.

InterfaceResponsibility
IRunAnalysisUseCaseExecute a script against the loaded context
IGetContextUseCaseReturn current context slices
IGetContextGraphUseCaseReturn context as a graph (nodes + edges)
ILoadContextUseCaseLoad files into context via a loader plugin
ILinkContextUseCaseLink loaded context via a linker plugin
IClearContextUseCaseClear all loaded context
IGenerateClassesUseCaseStream generated model class files
IGetInstalledPluginsUseCaseList installed plugins
IInstallPluginUseCaseInstall a plugin by id
IUninstallPluginUseCaseUninstall a plugin by id

Supporting SDK interfaces

The SDK also exposes a small set of helper interfaces for context, scripts, model files, and results. These are injected into the service layer and provide the low-level persistence and retrieval operations that the higher-level use cases rely on.

IModelFileLoader

csharp
public interface IModelFileLoader
{
    Task<Stream> LoadModelFileStreamAsync(FileId fileId, CancellationToken cancellationToken);
}

Loads a model file stream identified by a FileId so the service can read or process the raw model file.

IScriptLoader

csharp
public interface IScriptLoader
{
    Task<OneOf<Script, ScriptDoesNotExistsError>> Get(
        ScriptId scriptId,
        CancellationToken cancellationToken
    );

    Task<OneOf<string, ScriptDoesNotExistsError>> GetScriptContent(
        ProjectId projectId,
        string path,
        CancellationToken cancellationToken
    );
}

Retrieves a script definition by ScriptId, and optionally resolves the script source text from a project path.

IAnalysisState

csharp
public interface IAnalysisState
{
    Task<AnalysisInfo> CreateAsync(AnalysisInfo analysisInfo, CancellationToken cancellationToken);

    Task UpdateAsync(AnalysisInfo analysisInfo, CancellationToken cancellationToken);
}

Creates or updates persisted analysis metadata so the service can track the current analysis state.

IScriptResultsStore

The current interface name is IScriptResultsStore. Older release notes and documentation may refer to this as IScriptResults.

csharp
public interface IScriptResultsStore
{
    Task UploadFileAsync<TMetadata>(
        FileId fileId,
        Stream fileStream,
        TMetadata? metadata = null,
        CancellationToken cancellationToken = default
    )
        where TMetadata : class;
}

Uploads a script result file and optional metadata for persistence under the provided FileId. The SDK deliberately does not provide an in-memory or built-in results store; storage is something that the concrete implementer offers by implementing IScriptResultsStore (backed by the host's file system, blob storage, database, etc.).

Example

csharp
public sealed class Neo4jRunAnalysisService : IRunAnalysisUseCase
{
    private readonly INeo4jSession _session;

    public Neo4jRunAnalysisService(INeo4jSession session)
    {
        _session = session;
    }

    public async Task<WebRunAnalysisResponse> RunAsync(
        WebRunAnalysisCommand command,
        CancellationToken cancellationToken)
    {
        // store results in Neo4j, return response
        return new WebRunAnalysisResponse(...);
    }
}

Registration

In your Program.cs, register each implementation and call the SDK extension method:

csharp
builder.Services.AddScoped<IRunAnalysisUseCase, Neo4jRunAnalysisService>();
builder.Services.AddScoped<IGetContextUseCase, Neo4jGetContextService>();
// ... all other use cases

var app = builder.Build();
app.AddAnalysisEndpoints();
app.Run();

AddAnalysisEndpoints() registers all FluentValidation validators and maps every endpoint to IEndpointRouteBuilder automatically.

IAnalysisResultService

The high-level result service lets your analysis logic emit typed results (files, console output, errors, or custom types) without dealing with FileIds, GUIDs, or stream management directly.

csharp
public interface IAnalysisResultService
{
    Task<ResultId> AddFileAsync(
        string name, Stream content,
        string resultType = RunResultTypes.File,
        CancellationToken cancellationToken = default);

    Task<ResultId> AddFileAsync(
        string name, string content,
        string resultType = RunResultTypes.File,
        CancellationToken cancellationToken = default);

    Task<ResultId> AddConsoleAsync(
        string content, string name = "ConsoleOutput",
        CancellationToken cancellationToken = default);

    Task<ResultId> AddErrorAsync(
        string message, string name = "RunError",
        CancellationToken cancellationToken = default);

    Task<ResultId> AddResultAsync(
        string name, string resultType, Stream content,
        CancellationToken cancellationToken = default);
}

Inject IAnalysisResultService into your use-case implementations and use the ergonomic helpers:

csharp
public sealed class MyRunAnalysisUseCase(IAnalysisResultService results) : IRunAnalysisUseCase
{
    public async Task RunAsync(CancellationToken cancellationToken)
    {
        await results.AddConsoleAsync("Analysis started", cancellationToken: cancellationToken);

        await results.AddFileAsync(
            "summary.json",
            """{"count": 42}""",
            cancellationToken: cancellationToken
        );

        await using var csvStream = BuildCsvReport();
        await results.AddFileAsync("report.csv", csvStream, cancellationToken: cancellationToken);
    }
}

The well-known type constants are available on RunResultTypes:

ConstantValue
RunResultTypes.File"File"
RunResultTypes.Console"Console"
RunResultTypes.RunError"RunError"

You can also pass any custom string as resultType when calling AddFileAsync or AddResultAsync to define your own result categories.

Versioning & Changelog

The SDK follows Semantic Versioning. Releases are tagged analysis-sdk@<version> in the monorepo and published automatically to NuGet.

See CHANGELOG.md for the full release history.

Released under the MIT License.