Fly.Sdk.Reporting 1.2.3

dotnet add package Fly.Sdk.Reporting --version 1.2.3
                    
NuGet\Install-Package Fly.Sdk.Reporting -Version 1.2.3
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Fly.Sdk.Reporting" Version="1.2.3" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Fly.Sdk.Reporting" Version="1.2.3" />
                    
Directory.Packages.props
<PackageReference Include="Fly.Sdk.Reporting" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Fly.Sdk.Reporting --version 1.2.3
                    
#r "nuget: Fly.Sdk.Reporting, 1.2.3"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Fly.Sdk.Reporting@1.2.3
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Fly.Sdk.Reporting&version=1.2.3
                    
Install as a Cake Addin
#tool nuget:?package=Fly.Sdk.Reporting&version=1.2.3
                    
Install as a Cake Tool

Fly.Sdk.Reporting

Shared wire contract + query executor for FlyOS dashboard reports.

Power-BI–style queryable datasets composable from the desktop shell's Reports Builder. The wire shape (DatasetSchema, DatasetQuery, RenderResponse) is identical on every backend that opts into the surface, so the same builder UI works against every app without per-app frontend code.

Breaking change in 1.0.0: ChartResponse/ChartSeriesPoint/ChartDataset/ ChartWarning/ChartResult/ChartTypes were renamed to RenderResponse/SeriesPoint/ SeriesDataset/RenderWarning/RenderResult/RenderTypes (and the ChartType property to RenderType) to drop "chart" terminology from the reports domain. There is no compat shim — external consumers of this package must update on upgrade.

What's in the box

Namespace What it gives you
Fly.Sdk.Reporting.Wire DatasetSchema, FieldSchema, DatasetQuery, DatasetFilter, DatasetDimension, DatasetMeasure, RenderResponse (+ typed factories: Bar / Pie / Doughnut / PolarArea / Radar / Line / Scatter / Table / MultiDataset / Gauge), RenderResult (the IActionResult wrapper), SeriesPoint, TableColumn, SeriesDataset, RenderWarning, plus the closed enum constants (FilterOp, Aggregation, TimeBucket, FieldRole, FieldType, RenderTypes). These are the only types you need to consume or produce a dataset query on the wire.
Fly.Sdk.Reporting.Execution QueryExecutor (validates + runs a DatasetQuery against your DbSet<T>), FieldBinding<TEntity, TValue> (declarative field-to-property mapping), DatasetBindings<TEntity> (per-dataset bundle), QueryValidationException (errors with machine-readable codes), RelativeTime (resolves now-30d-style tokens at execution time).

Quick start (business app side)

  1. Declare a dataset in your manifest.json under dashboardDatasets — see skills/dashboard-reports.md for the full schema.

  2. Declare bindings:

    public static DatasetBindings<Signal> Bindings() => new("signals", [
        new FieldBinding<Signal, string?>("source",    FieldType.String,   s => s.Source),
        new FieldBinding<Signal, string?>("pestle",    FieldType.String,   s => s.Pestle),
        new FieldBinding<Signal, double?>("confidence", FieldType.Number,  s => s.Confidence),
        new FieldBinding<Signal, DateTime>("createdAt", FieldType.Datetime, s => s.CreatedAt),
    ]);
    
  3. Add the query endpoint:

    [HttpPost("datasets/signals/query")]
    public async Task<IActionResult> Query([FromBody] DatasetQuery q, CancellationToken ct)
    {
        // Schema + bindings provided by DI; tenant filter already applied to DbSet via global filter.
        var result = await _executor.ExecuteAsync(q, _schema, SignalBindings.Bindings(), _db.Signals, ct);
        return result.ToActionResult();   // <-- sidesteps any inherited Ok<T> override
    }
    

    Why ToActionResult() and not Ok(result)? If your controller inherits from a base class that overrides Ok<T> to wrap the value in an envelope (e.g. ApiResponse<T>), return Ok(result) ships the wrapped shape. The Dashboard proxy forwards the body verbatim and the renderer reads resp.series directly, so an envelope-wrapped body silently breaks every report card with no exception logged. ToActionResult() returns a RenderResult (an IActionResult implementation) that the framework dispatches directly — no Ok() override can interpose.

  4. Or use the typed factories when you build the response by hand:

    return RenderResponse.Bar("status", series).ToActionResult();
    return RenderResponse.Line("month", points, truncated: true, warnings: warnings).ToActionResult();
    return RenderResponse.Table("worklist", columns, rows).ToActionResult();
    return RenderResponse.MultiDataset(RenderTypes.Bar, "status", datasets).ToActionResult();
    return RenderResponse.Scatter("conf-vs-time", xyPoints).ToActionResult();
    return RenderResponse.Gauge(42, "total").ToActionResult();
    

    The factory enforces shape at the call site — Scatter rejects points missing X, Table rejects empty columns — so wrong-shape envelopes never reach the renderer.

Design notes

  • Closed-by-default surface. Validators reject any field key not in the schema, any op not in FilterOp.All, any agg not in the field's declared Aggs list. There's no way to escape into a RawSql or Include.
  • In-memory aggregation, SQL filtering. Filters push down to EF Core; aggregation happens after the (RowCap-bounded) fetch. Pragmatic v1 trade-off — push-down optimisation for common shapes is a v1.1 follow-up.
  • Relative time tokens (now-30d) resolve at execution time, not save time. A saved "last 30 days" report re-evaluates the window on every render.
  • Tenant scoping is the caller's responsibility. Pass in your tenant-filtered IQueryable; the executor doesn't second-guess.
  • Cerbos authorization is the caller's responsibility. The schema's Permissions list is metadata for the builder UI, not enforced server-side.

See skills/dashboard-reports.md for full architecture, security, and rollout guidance.

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.2.3 88 8/4/2026