From be09534d10e7320eae831ae5a0f47388b8d0e167 Mon Sep 17 00:00:00 2001 From: Theaux Masquelier <43664045+Theauxm@users.noreply.github.com> Date: Tue, 17 Mar 2026 10:16:14 -0600 Subject: [PATCH 1/2] feat: add Hub template, switch all templates to in-memory default Add Trax.Samples.Hub combining API + Scheduler + Dashboard in one process. Switch Api and Scheduler templates from Postgres to UseInMemory() so they run without external dependencies. Add third-party license credits to all template Program.cs headers. --- .gitignore | 3 +- .../.template.config/template.json | 9 --- templates/content/Trax.Samples.Api/Program.cs | 27 +++---- .../Junctions/LogGreetingJunction.cs | 3 +- .../Lookup/Junctions/FetchDataJunction.cs | 3 +- .../Trax.Samples.Api/Trax.Samples.Api.csproj | 3 +- .../content/Trax.Samples.Api/appsettings.json | 3 - .../.template.config/template.json | 14 ++++ templates/content/Trax.Samples.Hub/Program.cs | 78 +++++++++++++++++++ .../Properties/launchSettings.json | 15 ++++ .../Trains/HelloWorld/HelloWorldInput.cs | 11 +++ .../Trains/HelloWorld/HelloWorldTrain.cs | 17 ++++ .../Trains/HelloWorld/IHelloWorldTrain.cs | 6 ++ .../Junctions/LogGreetingJunction.cs | 26 +++++++ .../Trains/Lookup/ILookupTrain.cs | 5 ++ .../Lookup/Junctions/FetchDataJunction.cs | 23 ++++++ .../Trains/Lookup/LookupInput.cs | 9 +++ .../Trains/Lookup/LookupOutput.cs | 8 ++ .../Trains/Lookup/LookupTrain.cs | 17 ++++ .../Trax.Samples.Hub/Trax.Samples.Hub.csproj | 23 ++++++ .../content/Trax.Samples.Hub/appsettings.json | 15 ++++ .../.template.config/template.json | 9 --- .../content/Trax.Samples.Scheduler/Program.cs | 37 ++++----- .../Junctions/LogGreetingJunction.cs | 3 +- .../Trax.Samples.Scheduler.csproj | 2 +- .../Trax.Samples.Scheduler/appsettings.json | 3 - 26 files changed, 309 insertions(+), 63 deletions(-) create mode 100644 templates/content/Trax.Samples.Hub/.template.config/template.json create mode 100644 templates/content/Trax.Samples.Hub/Program.cs create mode 100644 templates/content/Trax.Samples.Hub/Properties/launchSettings.json create mode 100644 templates/content/Trax.Samples.Hub/Trains/HelloWorld/HelloWorldInput.cs create mode 100644 templates/content/Trax.Samples.Hub/Trains/HelloWorld/HelloWorldTrain.cs create mode 100644 templates/content/Trax.Samples.Hub/Trains/HelloWorld/IHelloWorldTrain.cs create mode 100644 templates/content/Trax.Samples.Hub/Trains/HelloWorld/Junctions/LogGreetingJunction.cs create mode 100644 templates/content/Trax.Samples.Hub/Trains/Lookup/ILookupTrain.cs create mode 100644 templates/content/Trax.Samples.Hub/Trains/Lookup/Junctions/FetchDataJunction.cs create mode 100644 templates/content/Trax.Samples.Hub/Trains/Lookup/LookupInput.cs create mode 100644 templates/content/Trax.Samples.Hub/Trains/Lookup/LookupOutput.cs create mode 100644 templates/content/Trax.Samples.Hub/Trains/Lookup/LookupTrain.cs create mode 100644 templates/content/Trax.Samples.Hub/Trax.Samples.Hub.csproj create mode 100644 templates/content/Trax.Samples.Hub/appsettings.json diff --git a/.gitignore b/.gitignore index ba93ac6..0559d2b 100644 --- a/.gitignore +++ b/.gitignore @@ -144,6 +144,7 @@ BenchmarkDotNet.Artifacts/ # Semantic Release version file .release-version -# Node.js (React chat client) +# Node.js (React clients) node_modules/ +dist/ tsconfig.tsbuildinfo diff --git a/templates/content/Trax.Samples.Api/.template.config/template.json b/templates/content/Trax.Samples.Api/.template.config/template.json index 9e1e78e..bbd09e8 100644 --- a/templates/content/Trax.Samples.Api/.template.config/template.json +++ b/templates/content/Trax.Samples.Api/.template.config/template.json @@ -10,14 +10,5 @@ "tags": { "language": "C#", "type": "project" - }, - "symbols": { - "ConnectionString": { - "type": "parameter", - "datatype": "string", - "defaultValue": "Host=localhost;Port=5432;Database=trax;Username=trax;Password=trax123", - "replaces": "HOST_CONNECTION_STRING", - "description": "The PostgreSQL connection string for Trax" - } } } diff --git a/templates/content/Trax.Samples.Api/Program.cs b/templates/content/Trax.Samples.Api/Program.cs index ef6f28f..af7dbcc 100644 --- a/templates/content/Trax.Samples.Api/Program.cs +++ b/templates/content/Trax.Samples.Api/Program.cs @@ -3,13 +3,14 @@ // // A GraphQL API powered by HotChocolate. Handles lightweight operations // directly via mutations and can queue heavy work for a separate scheduler -// process by passing mode: QUEUE. +// process by passing mode: QUEUE. Uses an in-memory data provider by default +// so you can run it immediately without any external dependencies. // -// Prerequisites: -// 1. Start PostgreSQL (e.g. docker compose up -d) -// 2. Run this project: dotnet run +// To switch to PostgreSQL, replace UseInMemory() with UsePostgres(connectionString) +// and swap the Trax.Effect.Data.InMemory package for Trax.Effect.Data.Postgres. // // Try it: +// dotnet run // Open http://localhost:5002/trax/graphql in a browser for Banana Cake Pop IDE // // # Query a train directly (typed query from [TraxQuery]) @@ -20,11 +21,16 @@ // // # Health check // curl http://localhost:5002/trax/health +// +// Third-party packages used by this project (via Trax dependencies): +// HotChocolate — GraphQL server (MIT, https://github.com/ChilliCream/graphql-platform) +// LanguageExt — Functional programming primitives (MIT, https://github.com/louthy/language-ext) +// EF Core InMemory — In-memory database provider (MIT, https://github.com/dotnet/efcore) // ───────────────────────────────────────────────────────────────────────────── using Trax.Api.Extensions; using Trax.Api.GraphQL.Extensions; -using Trax.Effect.Data.Postgres.Extensions; +using Trax.Effect.Data.InMemory.Extensions; using Trax.Effect.Extensions; using Trax.Effect.Provider.Json.Extensions; using Trax.Effect.Provider.Parameter.Extensions; @@ -32,21 +38,16 @@ var builder = WebApplication.CreateBuilder(args); -var connectionString = - builder.Configuration.GetConnectionString("TraxDatabase") - ?? throw new InvalidOperationException("Connection string 'TraxDatabase' not found."); - builder.Services.AddLogging(logging => logging.AddConsole()); // ── Register Trax Effect + Mediator ───────────────────────────────────── builder.Services.AddTrax(trax => - trax.AddEffects(effects => - effects.UsePostgres(connectionString).AddJson().SaveTrainParameters() - ) - .AddMediator(typeof(Program).Assembly) + trax.AddEffects(effects => effects.UseInMemory()) + .AddMediator(typeof(Program).Assembly) ); // ── Register GraphQL API ──────────────────────────────────────────────── +builder.Services.AddAuthorization(); builder.Services.AddTraxGraphQL(); builder.Services.AddHealthChecks().AddTraxHealthCheck(); diff --git a/templates/content/Trax.Samples.Api/Trains/HelloWorld/Junctions/LogGreetingJunction.cs b/templates/content/Trax.Samples.Api/Trains/HelloWorld/Junctions/LogGreetingJunction.cs index 7d5b382..688fa2d 100644 --- a/templates/content/Trax.Samples.Api/Trains/HelloWorld/Junctions/LogGreetingJunction.cs +++ b/templates/content/Trax.Samples.Api/Trains/HelloWorld/Junctions/LogGreetingJunction.cs @@ -1,5 +1,6 @@ using LanguageExt; -using Trax.Core.Models; +using Microsoft.Extensions.Logging; +using Trax.Core.Junction; namespace Trax.Samples.Api.Trains.HelloWorld.Junctions; diff --git a/templates/content/Trax.Samples.Api/Trains/Lookup/Junctions/FetchDataJunction.cs b/templates/content/Trax.Samples.Api/Trains/Lookup/Junctions/FetchDataJunction.cs index b144220..56b2b10 100644 --- a/templates/content/Trax.Samples.Api/Trains/Lookup/Junctions/FetchDataJunction.cs +++ b/templates/content/Trax.Samples.Api/Trains/Lookup/Junctions/FetchDataJunction.cs @@ -1,4 +1,5 @@ -using Trax.Core.Models; +using Microsoft.Extensions.Logging; +using Trax.Core.Junction; namespace Trax.Samples.Api.Trains.Lookup.Junctions; diff --git a/templates/content/Trax.Samples.Api/Trax.Samples.Api.csproj b/templates/content/Trax.Samples.Api/Trax.Samples.Api.csproj index 48fdda6..7622d99 100644 --- a/templates/content/Trax.Samples.Api/Trax.Samples.Api.csproj +++ b/templates/content/Trax.Samples.Api/Trax.Samples.Api.csproj @@ -4,11 +4,12 @@ net10.0 enable enable + true - + diff --git a/templates/content/Trax.Samples.Api/appsettings.json b/templates/content/Trax.Samples.Api/appsettings.json index 57480e9..a86dd58 100644 --- a/templates/content/Trax.Samples.Api/appsettings.json +++ b/templates/content/Trax.Samples.Api/appsettings.json @@ -1,7 +1,4 @@ { - "ConnectionStrings": { - "TraxDatabase": "HOST_CONNECTION_STRING" - }, "Kestrel": { "Endpoints": { "Http": { diff --git a/templates/content/Trax.Samples.Hub/.template.config/template.json b/templates/content/Trax.Samples.Hub/.template.config/template.json new file mode 100644 index 0000000..8819323 --- /dev/null +++ b/templates/content/Trax.Samples.Hub/.template.config/template.json @@ -0,0 +1,14 @@ +{ + "$schema": "http://json.schemastore.org/template", + "author": "Trax", + "classifications": ["Web", "Trax", "GraphQL", "Scheduler", "Dashboard"], + "identity": "Trax.Samples.Hub.CSharp", + "name": "Trax Hub (API + Scheduler + Dashboard)", + "shortName": "trax-hub", + "sourceName": "Trax.Samples.Hub", + "preferNameDirectory": true, + "tags": { + "language": "C#", + "type": "project" + } +} diff --git a/templates/content/Trax.Samples.Hub/Program.cs b/templates/content/Trax.Samples.Hub/Program.cs new file mode 100644 index 0000000..bf6b0d7 --- /dev/null +++ b/templates/content/Trax.Samples.Hub/Program.cs @@ -0,0 +1,78 @@ +// --------------------------------------------------------------------------- +// Trax Hub (API + Scheduler + Dashboard) +// +// A single process that serves a GraphQL API, runs scheduled trains, and +// hosts the Trax Dashboard. Uses an in-memory data provider by default so +// you can run it immediately without any external dependencies. +// +// To switch to PostgreSQL, replace UseInMemory() with UsePostgres(connectionString) +// and swap the Trax.Effect.Data.InMemory package for Trax.Effect.Data.Postgres. +// +// Try it: +// dotnet run +// Open http://localhost:5000/trax/graphql for the GraphQL IDE +// Open http://localhost:5000/trax for the Dashboard +// +// # Query a train directly +// query { discover { lookup(input: { id: "42" }) { id name createdAt } } } +// +// # Run a mutation +// mutation { dispatch { helloWorld(input: { name: "Trax" }) { externalId metadataId } } } +// +// # Health check +// curl http://localhost:5000/trax/health +// +// Third-party packages used by this project (via Trax dependencies): +// HotChocolate — GraphQL server (MIT, https://github.com/ChilliCream/graphql-platform) +// Radzen.Blazor — Dashboard UI components (MIT, https://github.com/radzenhq/radzen-blazor) +// LanguageExt — Functional programming primitives (MIT, https://github.com/louthy/language-ext) +// Cronos — Cron expression parser (MIT, https://github.com/HangfireIO/Cronos) +// EF Core InMemory — In-memory database provider (MIT, https://github.com/dotnet/efcore) +// --------------------------------------------------------------------------- + +using Trax.Api.Extensions; +using Trax.Api.GraphQL.Extensions; +using Trax.Dashboard.Extensions; +using Trax.Effect.Data.InMemory.Extensions; +using Trax.Effect.Extensions; +using Trax.Effect.JunctionProvider.Progress.Extensions; +using Trax.Effect.Provider.Json.Extensions; +using Trax.Effect.Provider.Parameter.Extensions; +using Trax.Mediator.Extensions; +using Trax.Samples.Hub.Trains.HelloWorld; +using Trax.Scheduler.Extensions; +using Trax.Scheduler.Services.Scheduling; + +var builder = WebApplication.CreateBuilder(args); + +builder.Services.AddLogging(logging => logging.AddConsole()); + +// -- Trax Effect + Mediator + Scheduler -------------------------------------- +builder.Services.AddTrax(trax => + trax.AddEffects(effects => effects.UseInMemory()) + .AddMediator(typeof(Program).Assembly) + .AddScheduler(scheduler => + scheduler.Schedule( + "hello-world", + new HelloWorldInput { Name = "Trax" }, + Every.Seconds(20) + ) + ) +); + +// -- Dashboard --------------------------------------------------------------- +builder.AddTraxDashboard(); + +// -- GraphQL API ------------------------------------------------------------- +builder.Services.AddAuthorization(); +builder.Services.AddTraxGraphQL(); +builder.Services.AddHealthChecks().AddTraxHealthCheck(); + +var app = builder.Build(); + +// -- Map endpoints ----------------------------------------------------------- +app.UseTraxDashboard(); +app.UseTraxGraphQL(); +app.MapHealthChecks("/trax/health"); + +app.Run(); diff --git a/templates/content/Trax.Samples.Hub/Properties/launchSettings.json b/templates/content/Trax.Samples.Hub/Properties/launchSettings.json new file mode 100644 index 0000000..584b530 --- /dev/null +++ b/templates/content/Trax.Samples.Hub/Properties/launchSettings.json @@ -0,0 +1,15 @@ +{ + "$schema": "https://json.schemastore.org/launchsettings.json", + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "trax/graphql", + "applicationUrl": "http://localhost:5000", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/templates/content/Trax.Samples.Hub/Trains/HelloWorld/HelloWorldInput.cs b/templates/content/Trax.Samples.Hub/Trains/HelloWorld/HelloWorldInput.cs new file mode 100644 index 0000000..5fac688 --- /dev/null +++ b/templates/content/Trax.Samples.Hub/Trains/HelloWorld/HelloWorldInput.cs @@ -0,0 +1,11 @@ +using Trax.Effect.Models.Manifest; + +namespace Trax.Samples.Hub.Trains.HelloWorld; + +public record HelloWorldInput : IManifestProperties +{ + /// + /// The name to greet in the train. + /// + public string Name { get; init; } = "World"; +} diff --git a/templates/content/Trax.Samples.Hub/Trains/HelloWorld/HelloWorldTrain.cs b/templates/content/Trax.Samples.Hub/Trains/HelloWorld/HelloWorldTrain.cs new file mode 100644 index 0000000..b3c3950 --- /dev/null +++ b/templates/content/Trax.Samples.Hub/Trains/HelloWorld/HelloWorldTrain.cs @@ -0,0 +1,17 @@ +using LanguageExt; +using Trax.Effect.Attributes; +using Trax.Effect.Services.ServiceTrain; +using Trax.Samples.Hub.Trains.HelloWorld.Junctions; + +namespace Trax.Samples.Hub.Trains.HelloWorld; + +/// +/// A mutation train that logs a greeting. Also scheduled to run every 20 seconds. +/// Exposed as a typed mutation field under mutation { dispatch { runHelloWorld(...) } }. +/// +[TraxMutation(GraphQLOperation.Run, Description = "Runs a hello world greeting")] +public class HelloWorldTrain : ServiceTrain, IHelloWorldTrain +{ + protected override async Task> RunInternal(HelloWorldInput input) => + Activate(input).Chain().Resolve(); +} diff --git a/templates/content/Trax.Samples.Hub/Trains/HelloWorld/IHelloWorldTrain.cs b/templates/content/Trax.Samples.Hub/Trains/HelloWorld/IHelloWorldTrain.cs new file mode 100644 index 0000000..79df32a --- /dev/null +++ b/templates/content/Trax.Samples.Hub/Trains/HelloWorld/IHelloWorldTrain.cs @@ -0,0 +1,6 @@ +using LanguageExt; +using Trax.Effect.Services.ServiceTrain; + +namespace Trax.Samples.Hub.Trains.HelloWorld; + +public interface IHelloWorldTrain : IServiceTrain; diff --git a/templates/content/Trax.Samples.Hub/Trains/HelloWorld/Junctions/LogGreetingJunction.cs b/templates/content/Trax.Samples.Hub/Trains/HelloWorld/Junctions/LogGreetingJunction.cs new file mode 100644 index 0000000..acabf05 --- /dev/null +++ b/templates/content/Trax.Samples.Hub/Trains/HelloWorld/Junctions/LogGreetingJunction.cs @@ -0,0 +1,26 @@ +using LanguageExt; +using Microsoft.Extensions.Logging; +using Trax.Core.Junction; + +namespace Trax.Samples.Hub.Trains.HelloWorld.Junctions; + +public class LogGreetingJunction(ILogger logger) + : Junction +{ + public override async Task Run(HelloWorldInput input) + { + var timestamp = DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss UTC"); + + logger.LogInformation( + "Hello, {Name}! This train ran at {Timestamp}", + input.Name, + timestamp + ); + + await Task.Delay(100); + + logger.LogInformation("HelloWorld train completed successfully for {Name}", input.Name); + + return Unit.Default; + } +} diff --git a/templates/content/Trax.Samples.Hub/Trains/Lookup/ILookupTrain.cs b/templates/content/Trax.Samples.Hub/Trains/Lookup/ILookupTrain.cs new file mode 100644 index 0000000..eacfbb0 --- /dev/null +++ b/templates/content/Trax.Samples.Hub/Trains/Lookup/ILookupTrain.cs @@ -0,0 +1,5 @@ +using Trax.Effect.Services.ServiceTrain; + +namespace Trax.Samples.Hub.Trains.Lookup; + +public interface ILookupTrain : IServiceTrain; diff --git a/templates/content/Trax.Samples.Hub/Trains/Lookup/Junctions/FetchDataJunction.cs b/templates/content/Trax.Samples.Hub/Trains/Lookup/Junctions/FetchDataJunction.cs new file mode 100644 index 0000000..1402eb8 --- /dev/null +++ b/templates/content/Trax.Samples.Hub/Trains/Lookup/Junctions/FetchDataJunction.cs @@ -0,0 +1,23 @@ +using Microsoft.Extensions.Logging; +using Trax.Core.Junction; + +namespace Trax.Samples.Hub.Trains.Lookup.Junctions; + +public class FetchDataJunction(ILogger logger) + : Junction +{ + public override async Task Run(LookupInput input) + { + logger.LogInformation("Looking up record {Id}", input.Id); + + // Replace this with your actual data access logic. + await Task.Delay(50); + + return new LookupOutput + { + Id = input.Id, + Name = $"Record {input.Id}", + CreatedAt = DateTime.UtcNow, + }; + } +} diff --git a/templates/content/Trax.Samples.Hub/Trains/Lookup/LookupInput.cs b/templates/content/Trax.Samples.Hub/Trains/Lookup/LookupInput.cs new file mode 100644 index 0000000..4927f63 --- /dev/null +++ b/templates/content/Trax.Samples.Hub/Trains/Lookup/LookupInput.cs @@ -0,0 +1,9 @@ +namespace Trax.Samples.Hub.Trains.Lookup; + +public record LookupInput +{ + /// + /// The ID of the record to look up. + /// + public required string Id { get; init; } +} diff --git a/templates/content/Trax.Samples.Hub/Trains/Lookup/LookupOutput.cs b/templates/content/Trax.Samples.Hub/Trains/Lookup/LookupOutput.cs new file mode 100644 index 0000000..6eb5192 --- /dev/null +++ b/templates/content/Trax.Samples.Hub/Trains/Lookup/LookupOutput.cs @@ -0,0 +1,8 @@ +namespace Trax.Samples.Hub.Trains.Lookup; + +public record LookupOutput +{ + public required string Id { get; init; } + public required string Name { get; init; } + public required DateTime CreatedAt { get; init; } +} diff --git a/templates/content/Trax.Samples.Hub/Trains/Lookup/LookupTrain.cs b/templates/content/Trax.Samples.Hub/Trains/Lookup/LookupTrain.cs new file mode 100644 index 0000000..3eb3edb --- /dev/null +++ b/templates/content/Trax.Samples.Hub/Trains/Lookup/LookupTrain.cs @@ -0,0 +1,17 @@ +using LanguageExt; +using Trax.Effect.Attributes; +using Trax.Effect.Services.ServiceTrain; +using Trax.Samples.Hub.Trains.Lookup.Junctions; + +namespace Trax.Samples.Hub.Trains.Lookup; + +/// +/// A query train that looks up a record by ID. +/// Exposed as a typed query field under query { discover { lookup(...) } }. +/// +[TraxQuery(Description = "Looks up a record by ID")] +public class LookupTrain : ServiceTrain, ILookupTrain +{ + protected override async Task> RunInternal(LookupInput input) => + Activate(input).Chain().Resolve(); +} diff --git a/templates/content/Trax.Samples.Hub/Trax.Samples.Hub.csproj b/templates/content/Trax.Samples.Hub/Trax.Samples.Hub.csproj new file mode 100644 index 0000000..76619a4 --- /dev/null +++ b/templates/content/Trax.Samples.Hub/Trax.Samples.Hub.csproj @@ -0,0 +1,23 @@ + + + Exe + net10.0 + enable + enable + true + true + + + + + + + + + + + + + + + diff --git a/templates/content/Trax.Samples.Hub/appsettings.json b/templates/content/Trax.Samples.Hub/appsettings.json new file mode 100644 index 0000000..830fe81 --- /dev/null +++ b/templates/content/Trax.Samples.Hub/appsettings.json @@ -0,0 +1,15 @@ +{ + "Kestrel": { + "Endpoints": { + "Http": { + "Url": "http://localhost:5000" + } + } + }, + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/templates/content/Trax.Samples.Scheduler/.template.config/template.json b/templates/content/Trax.Samples.Scheduler/.template.config/template.json index 45c8135..81e4d09 100644 --- a/templates/content/Trax.Samples.Scheduler/.template.config/template.json +++ b/templates/content/Trax.Samples.Scheduler/.template.config/template.json @@ -10,14 +10,5 @@ "tags": { "language": "C#", "type": "project" - }, - "symbols": { - "ConnectionString": { - "type": "parameter", - "datatype": "string", - "defaultValue": "Host=localhost;Port=5432;Database=trax;Username=trax;Password=trax123", - "replaces": "HOST_CONNECTION_STRING", - "description": "The PostgreSQL connection string for Trax" - } } } diff --git a/templates/content/Trax.Samples.Scheduler/Program.cs b/templates/content/Trax.Samples.Scheduler/Program.cs index cbd4c70..7ec1ac7 100644 --- a/templates/content/Trax.Samples.Scheduler/Program.cs +++ b/templates/content/Trax.Samples.Scheduler/Program.cs @@ -1,19 +1,26 @@ // ───────────────────────────────────────────────────────────────────────────── // Trax Scheduler with Dashboard // -// Runs scheduled trains on a configurable interval using PostgreSQL as the -// task server. Includes a Blazor dashboard for monitoring at /trax. +// Runs scheduled trains on a configurable interval. Includes a Blazor +// dashboard for monitoring at /trax. Uses an in-memory data provider by +// default so you can run it immediately without any external dependencies. // -// Prerequisites: -// 1. Start PostgreSQL (e.g. docker compose up -d) -// 2. Run this project: dotnet run +// To switch to PostgreSQL, replace UseInMemory() with UsePostgres(connectionString) +// and swap the Trax.Effect.Data.InMemory package for Trax.Effect.Data.Postgres. // // Try it: +// dotnet run // Open http://localhost:5001/trax in a browser for the Trax Dashboard +// +// Third-party packages used by this project (via Trax dependencies): +// Radzen.Blazor — Dashboard UI components (MIT, https://github.com/radzenhq/radzen-blazor) +// LanguageExt — Functional programming primitives (MIT, https://github.com/louthy/language-ext) +// Cronos — Cron expression parser (MIT, https://github.com/HangfireIO/Cronos) +// EF Core InMemory — In-memory database provider (MIT, https://github.com/dotnet/efcore) // ───────────────────────────────────────────────────────────────────────────── using Trax.Dashboard.Extensions; -using Trax.Effect.Data.Postgres.Extensions; +using Trax.Effect.Data.InMemory.Extensions; using Trax.Effect.Extensions; using Trax.Effect.JunctionProvider.Progress.Extensions; using Trax.Effect.Provider.Json.Extensions; @@ -25,24 +32,11 @@ var builder = WebApplication.CreateBuilder(args); -var connectionString = - builder.Configuration.GetConnectionString("TraxDatabase") - ?? throw new InvalidOperationException("Connection string 'TraxDatabase' not found."); - builder.Services.AddLogging(logging => logging.AddConsole()); -// ── Dashboard ─────────────────────────────────────────────────────────── -builder.AddTraxDashboard(); - // ── Register Trax Effect + Scheduler ──────────────────────────────────── builder.Services.AddTrax(trax => - trax.AddEffects(effects => - effects - .UsePostgres(connectionString) - .AddJson() - .SaveTrainParameters() - .AddJunctionProgress() - ) + trax.AddEffects(effects => effects.UseInMemory()) .AddMediator(typeof(Program).Assembly) .AddScheduler(scheduler => scheduler @@ -56,6 +50,9 @@ ) ); +// ── Dashboard ─────────────────────────────────────────────────────────── +builder.AddTraxDashboard(); + var app = builder.Build(); // ── Map dashboard ─────────────────────────────────────────────────────── diff --git a/templates/content/Trax.Samples.Scheduler/Trains/HelloWorld/Junctions/LogGreetingJunction.cs b/templates/content/Trax.Samples.Scheduler/Trains/HelloWorld/Junctions/LogGreetingJunction.cs index 4a05f2e..fbc4800 100644 --- a/templates/content/Trax.Samples.Scheduler/Trains/HelloWorld/Junctions/LogGreetingJunction.cs +++ b/templates/content/Trax.Samples.Scheduler/Trains/HelloWorld/Junctions/LogGreetingJunction.cs @@ -1,5 +1,6 @@ using LanguageExt; -using Trax.Core.Models; +using Microsoft.Extensions.Logging; +using Trax.Core.Junction; namespace Trax.Samples.Scheduler.Trains.HelloWorld.Junctions; diff --git a/templates/content/Trax.Samples.Scheduler/Trax.Samples.Scheduler.csproj b/templates/content/Trax.Samples.Scheduler/Trax.Samples.Scheduler.csproj index bb46387..81f01f8 100644 --- a/templates/content/Trax.Samples.Scheduler/Trax.Samples.Scheduler.csproj +++ b/templates/content/Trax.Samples.Scheduler/Trax.Samples.Scheduler.csproj @@ -9,7 +9,7 @@ - + diff --git a/templates/content/Trax.Samples.Scheduler/appsettings.json b/templates/content/Trax.Samples.Scheduler/appsettings.json index f2bdc73..abebe56 100644 --- a/templates/content/Trax.Samples.Scheduler/appsettings.json +++ b/templates/content/Trax.Samples.Scheduler/appsettings.json @@ -1,7 +1,4 @@ { - "ConnectionStrings": { - "TraxDatabase": "HOST_CONNECTION_STRING" - }, "Kestrel": { "Endpoints": { "Http": { From 9e0e1d15f9e94d9c3ca9c1de1bd0f0a5999c4261 Mon Sep 17 00:00:00 2001 From: Theaux Masquelier <43664045+Theauxm@users.noreply.github.com> Date: Tue, 17 Mar 2026 10:47:31 -0600 Subject: [PATCH 2/2] fix: format Api template Program.cs for csharpier --- templates/content/Trax.Samples.Api/Program.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/templates/content/Trax.Samples.Api/Program.cs b/templates/content/Trax.Samples.Api/Program.cs index af7dbcc..b9c58a6 100644 --- a/templates/content/Trax.Samples.Api/Program.cs +++ b/templates/content/Trax.Samples.Api/Program.cs @@ -42,8 +42,7 @@ // ── Register Trax Effect + Mediator ───────────────────────────────────── builder.Services.AddTrax(trax => - trax.AddEffects(effects => effects.UseInMemory()) - .AddMediator(typeof(Program).Assembly) + trax.AddEffects(effects => effects.UseInMemory()).AddMediator(typeof(Program).Assembly) ); // ── Register GraphQL API ────────────────────────────────────────────────