|
| 1 | +namespace NeoReports.Abstractions; |
| 2 | + |
| 3 | +// Serializer-agnostic configuration model for the dynamic (config-driven) path. These are plain |
| 4 | +// records with no JSON coupling; a parser (e.g. the Core JSON parser) maps a document onto them, |
| 5 | +// and a compiler turns them into the same runnable report a fluent builder produces. The model |
| 6 | +// mirrors the fluent builder one-to-one. |
| 7 | + |
| 8 | +/// <summary> |
| 9 | +/// A complete report definition expressed as data (the dynamic path). A compiler turns this into |
| 10 | +/// the same runnable report that <c>ReportBuilder<ReportRecord></c> produces in code. |
| 11 | +/// </summary> |
| 12 | +/// <param name="Name">Unique report name.</param> |
| 13 | +/// <param name="Source">The source the rows are read from.</param> |
| 14 | +/// <param name="Columns">Output columns, in order; they define the positional schema.</param> |
| 15 | +/// <param name="Outputs">Output formats (at least one).</param> |
| 16 | +/// <param name="Destinations">Upload destinations; <c>null</c> or empty means none.</param> |
| 17 | +/// <param name="PageSize">Optional page size; the engine default is used when null.</param> |
| 18 | +/// <param name="Filter">Optional dynamic filter expression (JsonLogic); evaluated by a later epic.</param> |
| 19 | +public sealed record ReportConfig( |
| 20 | + string Name, |
| 21 | + SourceConfig Source, |
| 22 | + IReadOnlyList<ColumnConfig> Columns, |
| 23 | + IReadOnlyList<OutputConfig> Outputs, |
| 24 | + IReadOnlyList<DestinationConfig>? Destinations = null, |
| 25 | + int? PageSize = null, |
| 26 | + string? Filter = null); |
| 27 | + |
| 28 | +/// <summary>A source section: a stable type id plus a free-form property bag the provider reads.</summary> |
| 29 | +/// <param name="Type">Stable source type id (e.g. "sql"); resolved to an <see cref="IConfigSourceProvider"/>.</param> |
| 30 | +/// <param name="Properties">Provider-specific settings (e.g. connection string, query, key).</param> |
| 31 | +public sealed record SourceConfig( |
| 32 | + string Type, |
| 33 | + IReadOnlyDictionary<string, object?>? Properties = null); |
| 34 | + |
| 35 | +/// <summary> |
| 36 | +/// A single output column declared as data. Because a dynamic row is positional, the column's |
| 37 | +/// position is its index in <see cref="ReportConfig.Columns"/>; the rest mirrors <see cref="ReportColumn"/>. |
| 38 | +/// </summary> |
| 39 | +/// <param name="Name">Stable column key, unique within the report.</param> |
| 40 | +/// <param name="Type">Semantic column type used for formatting and projection.</param> |
| 41 | +/// <param name="DisplayName">Optional header label; defaults to <paramref name="Name"/>.</param> |
| 42 | +/// <param name="Format">Optional .NET format string for rendering.</param> |
| 43 | +/// <param name="Culture">Optional culture name (e.g. "pt-BR") for rendering.</param> |
| 44 | +/// <param name="Nullable">Whether the column may contain null values.</param> |
| 45 | +public sealed record ColumnConfig( |
| 46 | + string Name, |
| 47 | + ColumnType Type, |
| 48 | + string? DisplayName = null, |
| 49 | + string? Format = null, |
| 50 | + string? Culture = null, |
| 51 | + bool Nullable = true); |
| 52 | + |
| 53 | +/// <summary>An output section: a stable format id plus a free-form property bag the writer reads.</summary> |
| 54 | +/// <param name="Format">Stable format id (e.g. "csv", "xlsx"); resolved to an <see cref="IWriterFactory"/>.</param> |
| 55 | +/// <param name="Properties">Format-specific options.</param> |
| 56 | +public sealed record OutputConfig( |
| 57 | + string Format, |
| 58 | + IReadOnlyDictionary<string, object?>? Properties = null); |
| 59 | + |
| 60 | +/// <summary>A destination section: a stable type id plus a free-form property bag.</summary> |
| 61 | +/// <param name="Type">Stable destination type id (e.g. "local", "s3"); resolved to an <see cref="IDestinationFactory"/>.</param> |
| 62 | +/// <param name="Properties">Destination-specific options (e.g. path/key template, bucket).</param> |
| 63 | +public sealed record DestinationConfig( |
| 64 | + string Type, |
| 65 | + IReadOnlyDictionary<string, object?>? Properties = null); |
| 66 | + |
| 67 | +/// <summary>Parses a serialized report definition (e.g. JSON) into a <see cref="ReportConfig"/>.</summary> |
| 68 | +public interface IReportConfigParser |
| 69 | +{ |
| 70 | + /// <summary>Parses the given document into a report configuration.</summary> |
| 71 | + /// <param name="document">The serialized configuration (e.g. a JSON string).</param> |
| 72 | + /// <returns>The parsed configuration.</returns> |
| 73 | + /// <exception cref="ConfigurationException">Thrown when the document is missing or malformed.</exception> |
| 74 | + ReportConfig Parse(string document); |
| 75 | +} |
| 76 | + |
| 77 | +/// <summary> |
| 78 | +/// Builds a positional <see cref="ReportRecord"/> source from a <see cref="SourceConfig"/>. The |
| 79 | +/// dynamic equivalent of a typed source factory: providers are registered by <see cref="Type"/> and |
| 80 | +/// resolved by the config compiler. The output schema is supplied so the provider can align values |
| 81 | +/// to columns by name/position. |
| 82 | +/// </summary> |
| 83 | +public interface IConfigSourceProvider |
| 84 | +{ |
| 85 | + /// <summary>Stable source type id this provider handles (e.g. "sql"); matched case-insensitively.</summary> |
| 86 | + string Type { get; } |
| 87 | + |
| 88 | + /// <summary>Creates the batch source that yields positional records aligned to <paramref name="schema"/>.</summary> |
| 89 | + /// <param name="source">The source configuration section.</param> |
| 90 | + /// <param name="schema">The report's output schema (columns in order).</param> |
| 91 | + /// <param name="services">The service provider for resolving dependencies.</param> |
| 92 | + /// <returns>A batch source producing <see cref="ReportRecord"/> rows.</returns> |
| 93 | + IBatchSource<ReportRecord> Create(SourceConfig source, ReportSchema schema, IServiceProvider services); |
| 94 | +} |
0 commit comments