├── src
└── InfinityFlow.Aspire.Temporal
│ ├── assets
│ ├── LICENSE
│ ├── README.md
│ └── packageIcon.png
│ ├── TemporalServerExecutableResource.cs
│ ├── Enums.cs
│ ├── InfinityFlow.Aspire.Temporal.csproj
│ ├── TemporalServerExecutableBuilderExtensions.cs
│ ├── TemporalServerContainerBuilderExtensions.cs
│ ├── TemporalServerResourceBuilder.cs
│ └── TemporalServerResourceArguments.cs
├── docs
├── aspire-dashboard-exe.png
├── aspire-dashboard-temporal-metrics.png
└── aspire-dashboard-temporal-tracing.png
├── sample
├── Worker
│ ├── appsettings.json
│ ├── Properties
│ │ └── launchSettings.json
│ ├── Worker.csproj
│ └── Program.cs
├── Api
│ ├── appsettings.json
│ ├── Api.csproj
│ ├── Properties
│ │ └── launchSettings.json
│ └── Program.cs
├── AppHost
│ ├── appsettings.json
│ ├── Properties
│ │ └── launchSettings.json
│ ├── AppHost.csproj
│ └── Program.cs
└── ServiceDefaults
│ ├── ServiceDefaults.csproj
│ └── Extensions.cs
├── .claude
└── settings.json
├── .github
├── workflows
│ ├── releasedrafter.yml
│ ├── dotnet.yml
│ └── publish.yaml
├── release-drafter.yml
└── dependabot.yml
├── scripts
└── install-dotnet.sh
├── LICENSE
├── InfinityFlow.Aspire.Temporal.sln
├── README.md
├── CLAUDE.md
├── .gitignore
└── .editorconfig
/src/InfinityFlow.Aspire.Temporal/assets/LICENSE:
--------------------------------------------------------------------------------
1 | ../../../LICENSE
--------------------------------------------------------------------------------
/src/InfinityFlow.Aspire.Temporal/assets/README.md:
--------------------------------------------------------------------------------
1 | ../../../README.md
--------------------------------------------------------------------------------
/docs/aspire-dashboard-exe.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/InfinityFlowApp/aspire-temporal/HEAD/docs/aspire-dashboard-exe.png
--------------------------------------------------------------------------------
/docs/aspire-dashboard-temporal-metrics.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/InfinityFlowApp/aspire-temporal/HEAD/docs/aspire-dashboard-temporal-metrics.png
--------------------------------------------------------------------------------
/docs/aspire-dashboard-temporal-tracing.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/InfinityFlowApp/aspire-temporal/HEAD/docs/aspire-dashboard-temporal-tracing.png
--------------------------------------------------------------------------------
/src/InfinityFlow.Aspire.Temporal/assets/packageIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/InfinityFlowApp/aspire-temporal/HEAD/src/InfinityFlow.Aspire.Temporal/assets/packageIcon.png
--------------------------------------------------------------------------------
/sample/Worker/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft.Hosting.Lifetime": "Information"
6 | }
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/sample/Api/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft.AspNetCore": "Warning"
6 | }
7 | },
8 | "AllowedHosts": "*"
9 | }
10 |
--------------------------------------------------------------------------------
/sample/AppHost/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft.AspNetCore": "Warning",
6 | "Aspire.Hosting.Dcp": "Warning"
7 | }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/.claude/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "hooks": {
3 | "SessionStart": [
4 | {
5 | "matcher": "startup",
6 | "hooks": [
7 | {
8 | "type": "command",
9 | "command": "\"$CLAUDE_PROJECT_DIR\"/scripts/install-dotnet.sh"
10 | }
11 | ]
12 | }
13 | ]
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/sample/Worker/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://json.schemastore.org/launchsettings.json",
3 | "profiles": {
4 | "Worker": {
5 | "commandName": "Project",
6 | "dotnetRunMessages": true,
7 | "environmentVariables": {
8 | "DOTNET_ENVIRONMENT": "Development"
9 | }
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/sample/Api/Api.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net10.0
5 | enable
6 | enable
7 | true
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/sample/AppHost/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://json.schemastore.org/launchsettings.json",
3 | "profiles": {
4 | "https": {
5 | "commandName": "Project",
6 | "dotnetRunMessages": true,
7 | "launchBrowser": true,
8 | "applicationUrl": "https://localhost:15264",
9 | "environmentVariables": {
10 | "ASPNETCORE_ENVIRONMENT": "Development",
11 | "DOTNET_ENVIRONMENT": "Development",
12 | "DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "https://localhost:16224",
13 | "DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "https://localhost:17037",
14 | "DOTNET_ASPIRE_SHOW_DASHBOARD_RESOURCES": "true"
15 | }
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/sample/Worker/Worker.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net10.0
5 | enable
6 | enable
7 | dotnet-Worker-0059691c-eb4b-48c3-980f-e2478ee155e9
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/sample/AppHost/AppHost.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net10.0
6 | enable
7 | enable
8 | true
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/.github/workflows/releasedrafter.yml:
--------------------------------------------------------------------------------
1 | name: Release Drafter
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 | pull_request_target:
8 | types:
9 | - edited
10 | - opened
11 | - reopened
12 | - synchronize
13 | workflow_dispatch:
14 | concurrency:
15 | group: ${{ github.event_name == 'pull_request' && format('pr-{0}', github.event.number) || github.ref }}
16 | cancel-in-progress: ${{ github.ref != 'refs/heads/main' && github.ref_type != 'tag' }}
17 |
18 |
19 | jobs:
20 | update_release_draft:
21 | permissions:
22 | contents: write
23 | pull-requests: write
24 | runs-on: ubuntu-latest
25 | steps:
26 | - name: "Draft Release"
27 | uses: release-drafter/release-drafter@v6.1.0
28 | env:
29 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
30 |
--------------------------------------------------------------------------------
/scripts/install-dotnet.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Only run in remote environments
4 | if [ "$CLAUDE_CODE_REMOTE" != "true" ]; then
5 | exit 0
6 | fi
7 |
8 | echo "Installing .NET SDK in remote environment..."
9 |
10 | # Install .NET SDK using official Microsoft script
11 | # This installs the latest .NET SDK
12 | curl -sSL https://dot.net/v1/dotnet-install.sh -o dotnet-install.sh
13 | bash dotnet-install.sh --channel 10.0
14 | rm dotnet-install.sh
15 |
16 | # Add dotnet to PATH for current session
17 | export DOTNET_ROOT=$HOME/.dotnet
18 | export PATH=$PATH:$DOTNET_ROOT:$DOTNET_ROOT/tools
19 |
20 | # Persist environment variables for subsequent bash commands
21 | if [ -n "$CLAUDE_ENV_FILE" ]; then
22 | echo "export DOTNET_ROOT=$HOME/.dotnet" >> "$CLAUDE_ENV_FILE"
23 | echo "export PATH=\$PATH:\$DOTNET_ROOT:\$DOTNET_ROOT/tools" >> "$CLAUDE_ENV_FILE"
24 | fi
25 |
26 | echo ".NET SDK installation complete"
27 | dotnet --version
28 |
29 | exit 0
30 |
--------------------------------------------------------------------------------
/.github/workflows/dotnet.yml:
--------------------------------------------------------------------------------
1 | # This workflow will build a .NET project
2 | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-net
3 |
4 | name: .NET
5 |
6 | on:
7 | push:
8 | branches: [ "main" ]
9 | pull_request:
10 | branches: [ "main" ]
11 | concurrency:
12 | group: ${{ github.event_name == 'pull_request' && format('pr-{0}', github.event.number) || github.ref }}
13 | cancel-in-progress: ${{ github.ref != 'refs/heads/main' && github.ref_type != 'tag' }}
14 |
15 |
16 | jobs:
17 | build:
18 |
19 | runs-on: ubuntu-latest
20 |
21 | steps:
22 | - uses: actions/checkout@v6
23 | - name: Setup .NET
24 | uses: actions/setup-dotnet@v5
25 | with:
26 | dotnet-version: 10.0.x
27 | - name: Restore dependencies
28 | run: dotnet restore
29 | - name: Build
30 | run: dotnet build --no-restore
31 | - name: Test
32 | run: dotnet test --no-build --verbosity normal
33 |
--------------------------------------------------------------------------------
/sample/AppHost/Program.cs:
--------------------------------------------------------------------------------
1 | using InfinityFlow.Aspire.Temporal;
2 |
3 | var builder = DistributedApplication.CreateBuilder(args);
4 |
5 | var temporal = builder.AddTemporalServerContainer("temporal", x => x
6 | .WithLogFormat(LogFormat.Json)
7 | .WithLogLevel(LogLevel.Info)
8 | .WithNamespace("test1", "test2")
9 | .WithDynamicConfigValue("frontend.enableUpdateWorkflowExecution", true)
10 | );
11 |
12 | var temporalWithPorts = builder.AddTemporalServerContainer("temporalWithPorts", x => x
13 | .WithPort(12345)
14 | .WithUiPort(23456)
15 | .WithLogFormat(LogFormat.Json)
16 | .WithLogLevel(LogLevel.Info)
17 | .WithNamespace("test1", "test2")
18 | .WithDynamicConfigValue("frontend.enableUpdateWorkflowExecution", true)
19 | );
20 |
21 | builder.AddProject("api")
22 | .WithReference(temporal);
23 |
24 | builder.AddProject("worker")
25 | .WithReference(temporal);
26 |
27 |
28 | builder.Build().Run();
29 |
--------------------------------------------------------------------------------
/.github/release-drafter.yml:
--------------------------------------------------------------------------------
1 | name-template: "InfinityFlow.Aspire.Temporal $RESOLVED_VERSION"
2 | tag-template: "$RESOLVED_VERSION"
3 | change-template: "- $TITLE by @$AUTHOR (#$NUMBER)"
4 | no-changes-template: "- No changes"
5 | categories:
6 | - title: "📚 Documentation"
7 | labels:
8 | - "documentation"
9 | - title: "🚀 New Features"
10 | labels:
11 | - "enhancement"
12 | - title: "🐛 Bug Fixes"
13 | labels:
14 | - "bug"
15 | - title: "☸️ Deployment Resources"
16 | labels:
17 | - "deployment-resources"
18 | version-resolver:
19 | major:
20 | labels:
21 | - "major"
22 | minor:
23 | labels:
24 | - "minor"
25 | patch:
26 | labels:
27 | - "patch"
28 | default: patch
29 | template: |
30 | $CHANGES
31 |
32 | ## 👨🏼💻 Contributors
33 |
34 | $CONTRIBUTORS
35 | autolabeler:
36 | - label: "documentation"
37 | files:
38 | - "docs/**/*"
39 | - label: "maintenance"
40 | files:
41 | - ".github/**/*"
42 | - ".devcontainer/**/*"
43 | - "test/**/*"
44 |
--------------------------------------------------------------------------------
/src/InfinityFlow.Aspire.Temporal/TemporalServerExecutableResource.cs:
--------------------------------------------------------------------------------
1 | using InfinityFlow.Aspire.Temporal;
2 | using Aspire.Hosting.ApplicationModel;
3 |
4 |
5 | namespace Aspire.Hosting;
6 |
7 | public class TemporalServerExecutableResource(string name, TemporalServerResourceArguments arguments) : ExecutableResource(name, command: "temporal", workingDirectory: ""), IResourceWithConnectionString
8 | {
9 | public ReferenceExpression ConnectionStringExpression => ReferenceExpression.Create($"{this.GetEndpoint("server").Property(EndpointProperty.HostAndPort)}");
10 | }
11 |
12 | public class TemporalServerContainerResource(string name, TemporalServerResourceArguments arguments) : ContainerResource(name,entrypoint: "/temporal"), IResourceWithConnectionString, IResourceWithEnvironment
13 | {
14 | public ReferenceExpression ConnectionStringExpression => ReferenceExpression.Create($"{this.GetEndpoint("server").Property(EndpointProperty.HostAndPort)}");
15 |
16 | public TemporalServerResourceArguments Arguments { get; } = arguments;
17 | }
18 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 sains1, InfinityFlow
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | # To get started with Dependabot version updates, you'll need to specify which
2 | # package ecosystems to update and where the package manifests are located.
3 | # Please see the documentation for all configuration options:
4 | # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
5 |
6 | version: 2
7 | updates:
8 | - package-ecosystem: "github-actions"
9 | directory: "/"
10 | schedule:
11 | interval: daily
12 | - package-ecosystem: "nuget" # See documentation for possible values
13 | directory: "/" # Location of package manifests
14 | schedule:
15 | interval: "daily"
16 | labels:
17 | - "dependencies"
18 | open-pull-requests-limit: 10
19 | groups:
20 | dotnet:
21 | patterns:
22 | - "Microsoft.*"
23 | - "System.*"
24 | - "Aspire"
25 | - "Aspire.*"
26 | OpenTelemetry:
27 | patterns:
28 | - "OpenTelemetry.*"
29 | - package-ecosystem: "devcontainers"
30 | directory: "/.devcontainer" # Location of package manifests
31 | schedule:
32 | interval: "daily"
33 | labels:
34 | - "dependencies"
35 |
36 |
--------------------------------------------------------------------------------
/sample/Api/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://json.schemastore.org/launchsettings.json",
3 | "iisSettings": {
4 | "windowsAuthentication": false,
5 | "anonymousAuthentication": true,
6 | "iisExpress": {
7 | "applicationUrl": "https://localhost:53494",
8 | "sslPort": 44374
9 | }
10 | },
11 | "profiles": {
12 | "http": {
13 | "commandName": "Project",
14 | "dotnetRunMessages": true,
15 | "launchBrowser": true,
16 | "launchUrl": "say-hello",
17 | "applicationUrl": "https://localhost:5195",
18 | "environmentVariables": {
19 | "ASPNETCORE_ENVIRONMENT": "Development"
20 | }
21 | },
22 | "https": {
23 | "commandName": "Project",
24 | "dotnetRunMessages": true,
25 | "launchBrowser": true,
26 | "launchUrl": "say-hello",
27 | "applicationUrl": "https://localhost:7244;http://localhost:5195",
28 | "environmentVariables": {
29 | "ASPNETCORE_ENVIRONMENT": "Development"
30 | }
31 | },
32 | "IIS Express": {
33 | "commandName": "IISExpress",
34 | "launchBrowser": true,
35 | "launchUrl": "say-hello",
36 | "environmentVariables": {
37 | "ASPNETCORE_ENVIRONMENT": "Development"
38 | }
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/InfinityFlow.Aspire.Temporal/Enums.cs:
--------------------------------------------------------------------------------
1 | namespace InfinityFlow.Aspire.Temporal;
2 |
3 | public enum LogFormat
4 | {
5 | Json,
6 | Pretty
7 | }
8 |
9 | public enum LogLevel
10 | {
11 | Debug,
12 | Info,
13 | Warn,
14 | Error,
15 | Fatal
16 | }
17 |
18 | public enum SQLitePragma
19 | {
20 | JournalMode,
21 | Synchronous
22 | }
23 |
24 | public static class EnumHelpers
25 | {
26 | public static string LogFormatToString(LogFormat logFormat) => logFormat switch
27 | {
28 | LogFormat.Pretty => "pretty",
29 | LogFormat.Json => "json",
30 | _ => throw new ArgumentOutOfRangeException(nameof(logFormat), logFormat, null),
31 | };
32 |
33 | public static string LogLevelToString(LogLevel level) => level switch
34 | {
35 | LogLevel.Debug => "debug",
36 | LogLevel.Info => "info",
37 | LogLevel.Warn => "warn",
38 | LogLevel.Error => "error",
39 | LogLevel.Fatal => "fatal",
40 | _ => throw new ArgumentOutOfRangeException(nameof(level), level, null),
41 | };
42 |
43 | public static string SQLitePragmaToString(SQLitePragma pragma) => pragma switch
44 | {
45 | SQLitePragma.JournalMode => "journal_mode",
46 | SQLitePragma.Synchronous => "synchronous",
47 | _ => throw new ArgumentOutOfRangeException(nameof(pragma), pragma, null),
48 | };
49 | }
--------------------------------------------------------------------------------
/sample/ServiceDefaults/ServiceDefaults.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library
5 | net10.0
6 | enable
7 | enable
8 | true
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/sample/Api/Program.cs:
--------------------------------------------------------------------------------
1 | using System.Diagnostics.Metrics;
2 |
3 | using Microsoft.AspNetCore.Http.HttpResults;
4 | using Microsoft.AspNetCore.Mvc;
5 |
6 | using Temporalio.Client;
7 | using Temporalio.Extensions.DiagnosticSource;
8 | using Temporalio.Extensions.OpenTelemetry;
9 | using Temporalio.Runtime;
10 |
11 | var builder = WebApplication.CreateBuilder(args);
12 |
13 | using var meter = new Meter("Temporal.Client");
14 |
15 | var runtime = new TemporalRuntime(new()
16 | {
17 | Telemetry = new()
18 | {
19 | Metrics = new() { CustomMetricMeter = new CustomMetricMeter(meter) },
20 | },
21 | });
22 |
23 | builder.AddServiceDefaults();
24 |
25 | builder.Services.AddTemporalClient(opts =>
26 | {
27 | opts.TargetHost = builder.Configuration["ConnectionStrings:temporal"];
28 | opts.Namespace = Constants.Namespace;
29 | opts.Interceptors = [new TracingInterceptor()];
30 | opts.Runtime = runtime;
31 | });
32 |
33 | var app = builder.Build();
34 |
35 | app.MapDefaultEndpoints();
36 | app.UseHttpsRedirection();
37 |
38 | app.MapGet("/say-hello", async Task, BadRequest>> (
39 | HttpContext ctx,
40 | [FromQuery] string? name,
41 | [FromServices] ITemporalClient client) =>
42 | {
43 | if (name is null or { Length: > 1000 })
44 | {
45 | return TypedResults.BadRequest($"Pass a name using query param {nameof(name)}");
46 | }
47 |
48 | var result = await client.ExecuteWorkflowAsync(x => x.RunAsync(name),
49 | new WorkflowOptions
50 | {
51 | Id = name,
52 | TaskQueue = Constants.TaskQueueName
53 | });
54 |
55 | return TypedResults.Ok(result);
56 | });
57 |
58 | app.Run();
--------------------------------------------------------------------------------
/sample/Worker/Program.cs:
--------------------------------------------------------------------------------
1 | using System.Diagnostics.Metrics;
2 |
3 | using Temporalio.Activities;
4 | using Temporalio.Extensions.DiagnosticSource;
5 | using Temporalio.Extensions.Hosting;
6 | using Temporalio.Extensions.OpenTelemetry;
7 | using Temporalio.Runtime;
8 | using Temporalio.Workflows;
9 |
10 | var builder = Host.CreateApplicationBuilder(args);
11 |
12 | using var meter = new Meter("Temporal.Client");
13 |
14 | var runtime = new TemporalRuntime(new()
15 | {
16 | Telemetry = new()
17 | {
18 | Metrics = new() { CustomMetricMeter = new CustomMetricMeter(meter) },
19 | },
20 | });
21 |
22 | builder.AddServiceDefaults();
23 |
24 | builder.Services
25 | .AddTemporalClient(opts =>
26 | {
27 | opts.TargetHost = builder.Configuration.GetConnectionString("temporal");
28 | opts.Namespace = Constants.Namespace;
29 | opts.Interceptors = new[] { new TracingInterceptor() };
30 | opts.Runtime = runtime;
31 | })
32 | .AddHostedTemporalWorker(Constants.TaskQueueName)
33 | .AddScopedActivities()
34 | .AddWorkflow();
35 |
36 | var host = builder.Build();
37 | host.Run();
38 |
39 | public static class Constants
40 | {
41 | public const string TaskQueueName = "aspire-worker-task-queue";
42 | public const string Namespace = "test1";
43 | }
44 |
45 | [Workflow]
46 | public class HelloWorkflow
47 | {
48 | [WorkflowRun]
49 | public async Task RunAsync(string name)
50 | {
51 | return await Workflow.ExecuteActivityAsync((HelloActivities act) => act.SayHello(name),
52 | new() { ScheduleToCloseTimeout = TimeSpan.FromMinutes(5) });
53 | }
54 | }
55 |
56 | public class HelloActivities
57 | {
58 | [Activity]
59 | public Task SayHello(string name)
60 | {
61 | return Task.FromResult("Hello " + name);
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/InfinityFlow.Aspire.Temporal/InfinityFlow.Aspire.Temporal.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net10.0
4 | enable
5 | enable
6 | packageIcon.png
7 | true
8 | true
9 | InfinityFlow.Aspire.Temporal
10 | 0.5.2
11 | true
12 | README.md
13 | LICENSE
14 | true
15 | dotnet;aspire;temporal
16 | Aspire extension to start the temporal cli dev server as an container or executable resource. Only container is well-supported currently.
17 | https://github.com/InfinityFlowApp/aspire-temporal-server
18 | InfinityFlow
19 | Copyright ©️ InfinityFlow
20 | $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb
21 | true
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/.github/workflows/publish.yaml:
--------------------------------------------------------------------------------
1 | # yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json
2 |
3 | name: publish
4 | on:
5 | workflow_dispatch: # Allow running the workflow manually from the GitHub UI
6 | push:
7 | branches:
8 | - "main" # Run the workflow when pushing to the main branch
9 | release:
10 | types:
11 | - published # Run the workflow when a new GitHub release is published
12 |
13 | env:
14 | DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1
15 | DOTNET_NOLOGO: true
16 | NuGetDirectory: ${{ github.workspace}}/nuget
17 | TargetProject: "./src/InfinityFlow.Aspire.Temporal/InfinityFlow.Aspire.Temporal.csproj"
18 |
19 | defaults:
20 | run:
21 | shell: pwsh
22 |
23 | jobs:
24 | create_nuget:
25 | runs-on: ubuntu-latest
26 | steps:
27 | - name: checkout
28 | uses: actions/checkout@v6
29 | with:
30 | fetch-depth: 0
31 |
32 | - name: install dotnet
33 | uses: actions/setup-dotnet@v5
34 | with:
35 | dotnet-version: 10.0.x
36 | - name: dotnet pack
37 | if: ${{ github.event_name != 'release' }}
38 | run: dotnet pack ${{ env.TargetProject }} --configuration Release --output ${{ env.NuGetDirectory }}
39 |
40 | - name: dotnet pack (release)
41 | if: ${{ github.event_name == 'release' && github.ref_type == 'tag' || github.event.release.tag_name }}
42 | run: dotnet pack ${{ env.TargetProject }} --configuration Release -p:PackageVersion="${{ github.event.release.tag_name || github.ref_name }}" --output ${{ env.NuGetDirectory }}
43 |
44 |
45 | - name: store artifact
46 | uses: actions/upload-artifact@v5
47 | with:
48 | name: nuget
49 | if-no-files-found: error
50 | retention-days: 7
51 | path: ${{ env.NuGetDirectory }}/*.nupkg # used in the following jobs
52 |
53 | deploy:
54 | if: github.event_name == 'release'
55 | runs-on: ubuntu-latest
56 | needs: [create_nuget]
57 | steps:
58 | - name: download artifact
59 | uses: actions/download-artifact@v6
60 | with:
61 | name: nuget
62 | path: ${{ env.NuGetDirectory }}
63 |
64 | - name: install dotnet
65 | uses: actions/setup-dotnet@v5
66 |
67 | - name: nuget push
68 | run: |
69 | foreach($file in (Get-ChildItem "${{ env.NuGetDirectory }}" -Recurse -Include *.nupkg)) {
70 | dotnet nuget push $file --api-key "${{ secrets.NUGET_APIKEY }}" --source https://api.nuget.org/v3/index.json
71 | }
72 |
--------------------------------------------------------------------------------
/src/InfinityFlow.Aspire.Temporal/TemporalServerExecutableBuilderExtensions.cs:
--------------------------------------------------------------------------------
1 | using Aspire.Hosting.ApplicationModel;
2 |
3 | using InfinityFlow.Aspire.Temporal;
4 |
5 | namespace Aspire.Hosting;
6 | public static class TemporalServerExecutableBuilderExtensions
7 | {
8 | ///
9 | /// Adds a temporal server resource instance to the Aspire host. Requires the Temporal executable location to be in your path.
10 | ///
11 | ///
12 | ///
13 | ///
14 | ///
15 | public static IResourceBuilder AddTemporalServerExecutable(this IDistributedApplicationBuilder builder, string name,
16 | Action callback)
17 | {
18 | var rb = new TemporalServerResourceBuilder();
19 | callback(rb);
20 | var args = rb.Build();
21 |
22 | return builder.AddTemporalServerExecutable(name, args);
23 | }
24 |
25 | ///
26 | /// Adds a temporal server resource instance to the Aspire host. Requires the Temporal executable location to be in your path.
27 | ///
28 | ///
29 | ///
30 | ///
31 | public static IResourceBuilder AddTemporalServerExecutable(this IDistributedApplicationBuilder builder, string name)
32 | {
33 | return builder.AddTemporalServerExecutable(name, new TemporalServerResourceArguments());
34 | }
35 |
36 | private static IResourceBuilder AddTemporalServerExecutable(this IDistributedApplicationBuilder builder, string name,
37 | TemporalServerResourceArguments args)
38 | {
39 | var resourceBuilder = builder.AddResource(new TemporalServerExecutableResource(name, args));
40 |
41 | resourceBuilder.WithHttpEndpoint(port: args.Port, name: "server").AsHttp2Service();
42 |
43 | if (args.Headless is not true)
44 | {
45 | resourceBuilder.WithHttpEndpoint(port: args.UiPort ?? args.Port + 1000, name: "ui");
46 | }
47 |
48 | if (args.MetricsPort is not null)
49 | {
50 | resourceBuilder.WithHttpEndpoint(port: args.MetricsPort?? 9000, name: "metrics");
51 | }
52 |
53 | if (args.HttpPort is not null)
54 | {
55 | resourceBuilder.WithHttpEndpoint(port: args.HttpPort ?? 8080, name: "http");
56 | }
57 |
58 | return resourceBuilder;
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/InfinityFlow.Aspire.Temporal/TemporalServerContainerBuilderExtensions.cs:
--------------------------------------------------------------------------------
1 | using Aspire.Hosting.ApplicationModel;
2 |
3 | using InfinityFlow.Aspire.Temporal;
4 |
5 | namespace Aspire.Hosting;
6 | public static class TemporalServerContainerBuilderExtensions
7 | {
8 | ///
9 | /// Adds a temporal server resource instance to the Aspire host. Requires the Temporal Container location to be in your path.
10 | ///
11 | ///
12 | ///
13 | ///
14 | ///
15 | public static IResourceBuilder AddTemporalServerContainer(this IDistributedApplicationBuilder builder, string name,
16 | Action callback)
17 | {
18 | var rb = new TemporalServerResourceBuilder();
19 | callback(rb);
20 | var args = rb.Build();
21 |
22 | return builder.AddTemporalServerContainer(name, args);
23 | }
24 |
25 | ///
26 | /// Adds a temporal server resource instance to the Aspire host. Requires the Temporal Container location to be in your path.
27 | ///
28 | ///
29 | ///
30 | ///
31 | public static IResourceBuilder AddTemporalServerContainer(this IDistributedApplicationBuilder builder, string name)
32 | {
33 | return builder.AddTemporalServerContainer(name, new TemporalServerResourceArguments());
34 | }
35 | private static IResourceBuilder AddTemporalServerContainer(this IDistributedApplicationBuilder builder, string name, TemporalServerResourceArguments args)
36 | {
37 | var container = new TemporalServerContainerResource(name, args);
38 |
39 | var resourceBuilder = builder.AddResource(container)
40 | .WithAnnotation(new ContainerImageAnnotation() { Image = "temporalio/admin-tools", Tag = "latest" })
41 | .WithArgs(args.GetArgs())
42 | .WithEntrypoint("temporal")
43 | .WithHttpsEndpoint(name: "server", port: args.Port, targetPort: args.Port).AsHttp2Service(); // Internal port is always 7233
44 |
45 | if (args.Headless is not true)
46 | {
47 | resourceBuilder.WithHttpEndpoint(name: "ui", port: args.UiPort, targetPort: args.UiPort); // Internal port is always 8233
48 | }
49 |
50 | if (args.MetricsPort is not null)
51 | {
52 | resourceBuilder.WithHttpEndpoint(name: "metrics", port: args.MetricsPort, targetPort: args.MetricsPort); // Internal port is always 7235
53 | }
54 |
55 | if (args.HttpPort is not null)
56 | {
57 | resourceBuilder.WithHttpEndpoint(name: "http", port: args.HttpPort, targetPort: args.HttpPort); // Internal port is always 7234
58 | }
59 |
60 | return resourceBuilder;
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/InfinityFlow.Aspire.Temporal.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.0.31903.59
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AppHost", "sample\AppHost\AppHost.csproj", "{52057B80-B01E-46C3-96F5-228D0B3BCB48}"
7 | EndProject
8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ServiceDefaults", "sample\ServiceDefaults\ServiceDefaults.csproj", "{4B893ACC-7DDF-43CE-95A6-104CA8AEAB04}"
9 | EndProject
10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "sample", "sample", "{0815F1E4-424A-4A05-A12E-B2BDAF2AA142}"
11 | EndProject
12 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{70F8209F-4A68-4F27-AF37-3A76C8EA0642}"
13 | EndProject
14 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "InfinityFlow.Aspire.Temporal", "src\InfinityFlow.Aspire.Temporal\InfinityFlow.Aspire.Temporal.csproj", "{88EE3FBD-5AF8-4F75-A0C7-BC593EC8F90F}"
15 | EndProject
16 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Api", "sample\Api\Api.csproj", "{1FFA9DCE-3368-4AFA-960A-0AD2C501CA1B}"
17 | EndProject
18 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Worker", "sample\Worker\Worker.csproj", "{8B68A40A-674D-4989-B366-1EE0A633F0D9}"
19 | EndProject
20 | Global
21 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
22 | Debug|Any CPU = Debug|Any CPU
23 | Release|Any CPU = Release|Any CPU
24 | EndGlobalSection
25 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
26 | {52057B80-B01E-46C3-96F5-228D0B3BCB48}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
27 | {52057B80-B01E-46C3-96F5-228D0B3BCB48}.Debug|Any CPU.Build.0 = Debug|Any CPU
28 | {52057B80-B01E-46C3-96F5-228D0B3BCB48}.Release|Any CPU.ActiveCfg = Release|Any CPU
29 | {52057B80-B01E-46C3-96F5-228D0B3BCB48}.Release|Any CPU.Build.0 = Release|Any CPU
30 | {4B893ACC-7DDF-43CE-95A6-104CA8AEAB04}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
31 | {4B893ACC-7DDF-43CE-95A6-104CA8AEAB04}.Debug|Any CPU.Build.0 = Debug|Any CPU
32 | {4B893ACC-7DDF-43CE-95A6-104CA8AEAB04}.Release|Any CPU.ActiveCfg = Release|Any CPU
33 | {4B893ACC-7DDF-43CE-95A6-104CA8AEAB04}.Release|Any CPU.Build.0 = Release|Any CPU
34 | {88EE3FBD-5AF8-4F75-A0C7-BC593EC8F90F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
35 | {88EE3FBD-5AF8-4F75-A0C7-BC593EC8F90F}.Debug|Any CPU.Build.0 = Debug|Any CPU
36 | {88EE3FBD-5AF8-4F75-A0C7-BC593EC8F90F}.Release|Any CPU.ActiveCfg = Release|Any CPU
37 | {88EE3FBD-5AF8-4F75-A0C7-BC593EC8F90F}.Release|Any CPU.Build.0 = Release|Any CPU
38 | {1FFA9DCE-3368-4AFA-960A-0AD2C501CA1B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
39 | {1FFA9DCE-3368-4AFA-960A-0AD2C501CA1B}.Debug|Any CPU.Build.0 = Debug|Any CPU
40 | {1FFA9DCE-3368-4AFA-960A-0AD2C501CA1B}.Release|Any CPU.ActiveCfg = Release|Any CPU
41 | {1FFA9DCE-3368-4AFA-960A-0AD2C501CA1B}.Release|Any CPU.Build.0 = Release|Any CPU
42 | {8B68A40A-674D-4989-B366-1EE0A633F0D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
43 | {8B68A40A-674D-4989-B366-1EE0A633F0D9}.Debug|Any CPU.Build.0 = Debug|Any CPU
44 | {8B68A40A-674D-4989-B366-1EE0A633F0D9}.Release|Any CPU.ActiveCfg = Release|Any CPU
45 | {8B68A40A-674D-4989-B366-1EE0A633F0D9}.Release|Any CPU.Build.0 = Release|Any CPU
46 | EndGlobalSection
47 | GlobalSection(SolutionProperties) = preSolution
48 | HideSolutionNode = FALSE
49 | EndGlobalSection
50 | GlobalSection(NestedProjects) = preSolution
51 | {52057B80-B01E-46C3-96F5-228D0B3BCB48} = {0815F1E4-424A-4A05-A12E-B2BDAF2AA142}
52 | {4B893ACC-7DDF-43CE-95A6-104CA8AEAB04} = {0815F1E4-424A-4A05-A12E-B2BDAF2AA142}
53 | {88EE3FBD-5AF8-4F75-A0C7-BC593EC8F90F} = {70F8209F-4A68-4F27-AF37-3A76C8EA0642}
54 | {1FFA9DCE-3368-4AFA-960A-0AD2C501CA1B} = {0815F1E4-424A-4A05-A12E-B2BDAF2AA142}
55 | {8B68A40A-674D-4989-B366-1EE0A633F0D9} = {0815F1E4-424A-4A05-A12E-B2BDAF2AA142}
56 | EndGlobalSection
57 | GlobalSection(ExtensibilityGlobals) = postSolution
58 | SolutionGuid = {C4C2C7A9-980A-4B6D-A624-60A0FBD99DE0}
59 | EndGlobalSection
60 | EndGlobal
61 |
--------------------------------------------------------------------------------
/sample/ServiceDefaults/Extensions.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Builder;
2 | using Microsoft.AspNetCore.Diagnostics.HealthChecks;
3 | using Microsoft.Extensions.DependencyInjection;
4 | using Microsoft.Extensions.Diagnostics.HealthChecks;
5 | using Microsoft.Extensions.Logging;
6 |
7 | using OpenTelemetry.Logs;
8 | using OpenTelemetry.Metrics;
9 | using OpenTelemetry.Trace;
10 |
11 | using Temporalio.Extensions.OpenTelemetry;
12 |
13 | namespace Microsoft.Extensions.Hosting;
14 |
15 | public static class Extensions
16 | {
17 | public static IHostApplicationBuilder AddServiceDefaults(this IHostApplicationBuilder builder)
18 | {
19 | builder.ConfigureOpenTelemetry();
20 |
21 | builder.AddDefaultHealthChecks();
22 |
23 | builder.Services.AddServiceDiscovery();
24 |
25 | builder.Services.ConfigureHttpClientDefaults(http =>
26 | {
27 | // Turn on resilience by default
28 | http.AddStandardResilienceHandler();
29 |
30 | // Turn on service discovery by default
31 | http.AddServiceDiscovery();
32 | });
33 |
34 | return builder;
35 | }
36 |
37 | public static IHostApplicationBuilder ConfigureOpenTelemetry(this IHostApplicationBuilder builder)
38 | {
39 | builder.Logging.AddOpenTelemetry(logging =>
40 | {
41 | logging.IncludeFormattedMessage = true;
42 | logging.IncludeScopes = true;
43 | });
44 |
45 | builder.Services.AddOpenTelemetry()
46 | .WithMetrics(metrics => metrics.AddRuntimeInstrumentation()
47 | .AddBuiltInMeters()
48 | .AddMeter("Temporal.Client"))
49 | .WithTracing(tracing =>
50 | {
51 | if (builder.Environment.IsDevelopment())
52 | {
53 | // We want to view all traces in development
54 | tracing.SetSampler(new AlwaysOnSampler());
55 | }
56 |
57 | tracing.AddAspNetCoreInstrumentation()
58 | .AddGrpcClientInstrumentation()
59 | .AddHttpClientInstrumentation()
60 | .AddSource(
61 | TracingInterceptor.ClientSource.Name,
62 | TracingInterceptor.WorkflowsSource.Name,
63 | TracingInterceptor.ActivitiesSource.Name);
64 | });
65 |
66 | builder.AddOpenTelemetryExporters();
67 |
68 | return builder;
69 | }
70 |
71 | private static IHostApplicationBuilder AddOpenTelemetryExporters(this IHostApplicationBuilder builder)
72 | {
73 | var useOtlpExporter = !string.IsNullOrWhiteSpace(builder.Configuration["OTEL_EXPORTER_OTLP_ENDPOINT"]);
74 |
75 | if (useOtlpExporter)
76 | {
77 | builder.Services.Configure(logging => logging.AddOtlpExporter());
78 | builder.Services.ConfigureOpenTelemetryMeterProvider(metrics => metrics.AddOtlpExporter());
79 | builder.Services.ConfigureOpenTelemetryTracerProvider(tracing => tracing.AddOtlpExporter());
80 | }
81 |
82 | // Uncomment the following lines to enable the Prometheus exporter (requires the OpenTelemetry.Exporter.Prometheus.AspNetCore package)
83 | // builder.Services.AddOpenTelemetry()
84 | // .WithMetrics(metrics => metrics.AddPrometheusExporter());
85 |
86 | // Uncomment the following lines to enable the Azure Monitor exporter (requires the Azure.Monitor.OpenTelemetry.Exporter package)
87 | // builder.Services.AddOpenTelemetry()
88 | // .UseAzureMonitor();
89 |
90 | return builder;
91 | }
92 |
93 | public static IHostApplicationBuilder AddDefaultHealthChecks(this IHostApplicationBuilder builder)
94 | {
95 | builder.Services.AddHealthChecks()
96 | // Add a default liveness check to ensure app is responsive
97 | .AddCheck("self", () => HealthCheckResult.Healthy(), ["live"]);
98 |
99 | return builder;
100 | }
101 |
102 | public static WebApplication MapDefaultEndpoints(this WebApplication app)
103 | {
104 | // Uncomment the following line to enable the Prometheus endpoint (requires the OpenTelemetry.Exporter.Prometheus.AspNetCore package)
105 | // app.MapPrometheusScrapingEndpoint();
106 |
107 | // All health checks must pass for app to be considered ready to accept traffic after starting
108 | app.MapHealthChecks("/health");
109 |
110 | // Only health checks tagged with the "live" tag must pass for app to be considered alive
111 | app.MapHealthChecks("/alive", new HealthCheckOptions
112 | {
113 | Predicate = r => r.Tags.Contains("live")
114 | });
115 |
116 | return app;
117 | }
118 |
119 | private static MeterProviderBuilder AddBuiltInMeters(this MeterProviderBuilder meterProviderBuilder) =>
120 | meterProviderBuilder.AddMeter(
121 | "Microsoft.AspNetCore.Hosting",
122 | "Microsoft.AspNetCore.Server.Kestrel",
123 | "System.Net.Http");
124 | }
125 |
--------------------------------------------------------------------------------
/src/InfinityFlow.Aspire.Temporal/TemporalServerResourceBuilder.cs:
--------------------------------------------------------------------------------
1 | using InfinityFlow.Aspire.Temporal;
2 |
3 | namespace Aspire.Hosting;
4 |
5 | public class TemporalServerResourceBuilder
6 | {
7 | private TemporalServerResourceArguments Args { get; } = new();
8 |
9 | ///
10 | /// Command to execute (default: "temporal")
11 | ///
12 | ///
13 | ///
14 | public TemporalServerResourceBuilder WithCommand(string command = "temporal")
15 | {
16 | Args.Command = command;
17 | return this;
18 | }
19 |
20 | ///
21 | /// File in which to persist Temporal state (by default, Workflows are lost when the process dies)
22 | ///
23 | ///
24 | public TemporalServerResourceBuilder WithDbFileName(string dbFileName)
25 | {
26 | Args.DbFileName = dbFileName;
27 | return this;
28 | }
29 |
30 | ///
31 | /// Port for the frontend gRPC service (default: 7233)
32 | ///
33 | ///
34 | ///
35 | public TemporalServerResourceBuilder WithPort(int port)
36 | {
37 | Args.Port = port;
38 | return this;
39 | }
40 |
41 | ///
42 | /// Port for the frontend HTTP service (default: disabled)
43 | ///
44 | ///
45 | ///
46 | public TemporalServerResourceBuilder WithHttpPort(int httpPort)
47 | {
48 | Args.HttpPort = httpPort;
49 | return this;
50 | }
51 |
52 | ///
53 | /// Port for /metrics (default: disabled)
54 | ///
55 | ///
56 | ///
57 | public TemporalServerResourceBuilder WithMetricsPort(int metricsPort)
58 | {
59 | Args.MetricsPort = metricsPort;
60 | return this;
61 | }
62 |
63 | ///
64 | /// Port for the Web UI (default: --port + 1000, e.g. 8233)
65 | ///
66 | ///
67 | ///
68 | public TemporalServerResourceBuilder WithUiPort(int uiPort)
69 | {
70 | Args.UiPort = uiPort;
71 | return this;
72 | }
73 |
74 | ///
75 | /// Disable the Web UI(default: false)
76 | ///
77 | ///
78 | ///
79 | public TemporalServerResourceBuilder WithHeadlessUi(bool headless)
80 | {
81 | Args.Headless = headless;
82 | return this;
83 | }
84 |
85 | ///
86 | /// IPv4 address to bind the frontend service to (default: "127.0.0.1")
87 | ///
88 | ///
89 | ///
90 | public TemporalServerResourceBuilder WithIp(string ip)
91 | {
92 | Args.Ip = ip;
93 | return this;
94 | }
95 |
96 | ///
97 | /// IPv4 address to bind the Web UI to (default: same as --ip)
98 | ///
99 | ///
100 | ///
101 | public TemporalServerResourceBuilder WithUiIp(string uiIp)
102 | {
103 | Args.UiIp = uiIp;
104 | return this;
105 | }
106 |
107 | ///
108 | /// UI custom assets path
109 | ///
110 | ///
111 | ///
112 | public TemporalServerResourceBuilder WithUiAssetsPath(string assetsPath)
113 | {
114 | Args.UiAssetPath = assetsPath;
115 | return this;
116 | }
117 |
118 | ///
119 | /// UI remote codec HTTP endpoint
120 | ///
121 | ///
122 | ///
123 | public TemporalServerResourceBuilder WithUiCodecEndpoint(string codecEndpoint)
124 | {
125 | Args.UiCodecEndpoint = codecEndpoint;
126 | return this;
127 | }
128 |
129 | ///
130 | /// Set the log formatting. Options: ["json", "pretty"]. (default: "json")
131 | ///
132 | ///
133 | ///
134 | public TemporalServerResourceBuilder WithLogFormat(LogFormat format)
135 | {
136 | Args.LogFormat = format;
137 | return this;
138 | }
139 |
140 | ///
141 | /// Set the log level. Options: ["debug" "info" "warn" "error" "fatal"]. (default: "info")
142 | ///
143 | ///
144 | ///
145 | public TemporalServerResourceBuilder WithLogLevel(LogLevel level)
146 | {
147 | Args.LogLevel = level;
148 | return this;
149 | }
150 |
151 | ///
152 | /// Specify SQLite pragma statements in pragma=value format. Pragma options: ["journal_mode" "synchronous"]
153 | ///
154 | ///
155 | ///
156 | public TemporalServerResourceBuilder WithSQLitePragma(SQLitePragma pragma)
157 | {
158 | Args.SQLitePragma = pragma;
159 | return this;
160 | }
161 |
162 | ///
163 | /// Specify namespaces that should be pre-created (namespace "default" is always created)
164 | ///
165 | ///
166 | ///
167 | public TemporalServerResourceBuilder WithNamespace(params string[] namespaces)
168 | {
169 | Args.Namespaces.AddRange(namespaces);
170 | return this;
171 | }
172 |
173 | public TemporalServerResourceArguments Build() => Args;
174 |
175 | ///
176 | /// Specify dynamic config values that should be configured.
177 | ///
178 | ///
179 | ///
180 | ///
181 | public TemporalServerResourceBuilder WithDynamicConfigValue(string key, object value)
182 | {
183 | Args.DynamicConfigValues.Add(key, value);
184 | return this;
185 | }
186 | }
187 |
--------------------------------------------------------------------------------
/src/InfinityFlow.Aspire.Temporal/TemporalServerResourceArguments.cs:
--------------------------------------------------------------------------------
1 | namespace InfinityFlow.Aspire.Temporal;
2 |
3 | ///
4 | /// Represents the arguments required to configure and start a Temporal server.
5 | ///
6 | public class TemporalServerResourceArguments
7 | {
8 | ///
9 | /// Gets or sets the command to execute. Default is "temporal".
10 | ///
11 | public string Command { get; set; } = "temporal";
12 |
13 | ///
14 | /// Gets or sets the file name where the Temporal state will be persisted. If not set, workflows are lost when the process dies.
15 | ///
16 | public string? DbFileName { get; set; }
17 |
18 | ///
19 | /// Gets or sets the port for the frontend gRPC service. Default is 7233.
20 | ///
21 | public int Port { get; set; } = 7233;
22 |
23 | ///
24 | /// Gets or sets the port for the frontend HTTP service. If not set, the service is disabled.
25 | ///
26 | public int? HttpPort { get; set; }
27 |
28 | ///
29 | /// Gets or sets the port for metrics. If not set, metrics are disabled.
30 | ///
31 | public int? MetricsPort { get; set; }
32 |
33 | ///
34 | /// Gets or sets the port for the Web UI. Default is 8233.
35 | ///
36 | public int? UiPort { get; set; } = 8233;
37 |
38 | ///
39 | /// Gets or sets a value indicating whether the Web UI is headless. If not set, defaults to false.
40 | ///
41 | public bool? Headless { get; set; }
42 |
43 | ///
44 | /// Gets or sets the IPv4 address to bind the frontend service to. Default is 0.0.0.0.
45 | ///
46 | public string? Ip { get; set; } = "0.0.0.0";
47 |
48 | ///
49 | /// Gets or sets the IPv4 address to bind the Web UI to. Default is null, which means it uses the same as --ip.
50 | ///
51 | public string? UiIp { get; set; }
52 |
53 | ///
54 | /// Gets or sets the path to the UI custom assets.
55 | ///
56 | public string? UiAssetPath { get; set; }
57 |
58 | ///
59 | /// Gets or sets the UI remote codec HTTP endpoint.
60 | ///
61 | public string? UiCodecEndpoint { get; set; }
62 |
63 | ///
64 | /// Gets or sets the log format. Options are "json" and "pretty". Default is null.
65 | ///
66 | public LogFormat? LogFormat { get; set; }
67 |
68 | ///
69 | /// Gets or sets the log level. Options are "debug", "info", "warn", "error", and "fatal". Default is null.
70 | ///
71 | public LogLevel? LogLevel { get; set; }
72 |
73 | ///
74 | /// Gets or sets the SQLite pragma. Options are "journal_mode" and "synchronous". Default is null.
75 | ///
76 | public SQLitePragma? SQLitePragma { get; set; }
77 |
78 | ///
79 | /// Gets the list of namespaces that should be pre-created. The "default" namespace is always created.
80 | ///
81 | public List Namespaces { get; set; } = [];
82 |
83 | ///
84 | /// Gets the list of dynamic config values.
85 | ///
86 | public Dictionary DynamicConfigValues { get; set; } = [];
87 |
88 | ///
89 | /// Converts the current instance's properties to an array of command-line arguments for starting the Temporal server.
90 | ///
91 | /// An array of strings representing the command-line arguments.
92 | public string[] GetArgs()
93 | {
94 | var result = new List
95 | {
96 | "server",
97 | "start-dev"
98 | };
99 |
100 | AddIfNotNull(result, "--db-filename", DbFileName);
101 | AddAlways(result, "--port", Port.ToString());
102 |
103 | AddIfNotNull(result, "--http-port", HttpPort?.ToString());
104 | AddIfNotNull(result, "--metrics-port", MetricsPort?.ToString());
105 | AddIfNotNull(result, "--ui-port", UiPort?.ToString());
106 | AddIfNotNull(result, "--headless", Headless?.ToString().ToLowerInvariant());
107 | AddIfNotNull(result, "--ip", Ip);
108 | AddIfNotNull(result, "--ui-ip", UiIp);
109 | AddIfNotNull(result, "--ui-asset-path", UiAssetPath);
110 | AddIfNotNull(result, "--ui-codec-endpoint", UiCodecEndpoint);
111 |
112 | if (LogFormat.HasValue)
113 | {
114 | result.Add("--log-format");
115 | result.Add(EnumHelpers.LogFormatToString(LogFormat.Value));
116 | }
117 |
118 | if (LogLevel.HasValue)
119 | {
120 | result.Add("--log-level");
121 | result.Add(EnumHelpers.LogLevelToString(LogLevel.Value));
122 | }
123 |
124 | if (SQLitePragma.HasValue)
125 | {
126 | result.Add("--sqlite-pragma");
127 | result.Add(EnumHelpers.SQLitePragmaToString(SQLitePragma.Value));
128 | }
129 |
130 | foreach (var name in Namespaces)
131 | {
132 | result.Add("--namespace");
133 | result.Add(name);
134 | }
135 |
136 | foreach (var (k, v) in DynamicConfigValues)
137 | {
138 | result.Add("--dynamic-config-value");
139 |
140 | result.Add($"{k}={v switch
141 | {
142 | string s => $""" "{v}" """,
143 | bool b => b.ToString().ToLowerInvariant(),
144 | int i => i.ToString(),
145 | float f => f.ToString("F"),
146 | double d => d.ToString("F"),
147 | long l => l.ToString(),
148 | _ => null,
149 | }}");
150 | }
151 |
152 | return [.. result];
153 | }
154 |
155 | private static void AddIfNotNull(List list, string argument, string? value)
156 | {
157 | if (value is not null)
158 | {
159 | list.Add(argument);
160 | list.Add(value);
161 | }
162 | }
163 |
164 | private static void AddAlways(List list, string argument, string value)
165 | {
166 | list.Add(argument);
167 | list.Add(value);
168 | }
169 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # InfinityFlow.Aspire.Temporal
2 |
3 | [](https://www.nuget.org/packages/InfinityFlow.Aspire.Temporal)
4 |
5 | [](https://discord.gg/PXJFbP7PKk)
6 |
7 | Aspire extension to start the temporal cli dev server as an container or executable resource.
8 | **Note: Only container works as expected. See https://github.com/dotnet/aspire/issues/1637 and https://github.com/temporalio/cli/issues/316**
9 |
10 |
11 | ## Contents:
12 | - [Pre-Requisites](#pre-requisites)
13 | - [Getting Started](#getting-started)
14 | - [Observability](#observability)
15 | - [Configuration](#configuration)
16 |
17 | ## Pre-requisites
18 |
19 | - [Temporal CLI](https://github.com/temporalio/cli) (ensure the binary is in your PATH)
20 | - An Aspire project. See [Aspire docs](https://learn.microsoft.com/en-us/dotnet/aspire/get-started/aspire-overview) to get started.
21 |
22 | ## Getting Started
23 |
24 | ### 1. Install the nuget package
25 |
26 | ```sh
27 | dotnet add package InfinityFlow.Aspire.Temporal
28 | ```
29 |
30 | ### 2. Add Temporal dev server to your Aspire AppHost Program.cs
31 |
32 | ```csharp
33 | // AppHost/Program.cs
34 | using Aspire.Temporal.Server;
35 |
36 | var builder = DistributedApplication.CreateBuilder(args);
37 |
38 | // Use the default server options
39 | var temporal = await builder.AddTemporalServerContainer("temporal")
40 |
41 | // OR customise server options with builder
42 | // see config section for details
43 | var temporal = await builder.AddTemporalServerContainer("temporal", x => x
44 | .WithLogFormat(LogFormat.Json)
45 | .WithLogLevel(LogLevel.Info)
46 | .WithNamespace("test1", "test2"));
47 | ```
48 |
49 | ### 3. Run the Aspire application
50 |
51 | You should see Temporal running under the Executables tab.
52 |
53 | Temporal will be available on its default ports:
54 | - Server: http://localhost:7233
55 | - UI: http://localhost:8233
56 |
57 | 
58 |
59 | ### 4. Configure Client/Worker Applications
60 |
61 | The Temporal client can then be added to a .NET project as normal using the instructions from the [temporal dotnet sdk repo](https://github.com/temporalio/sdk-dotnet/)
62 |
63 | It can be included in Aspire orchestration like below and can optionally take a reference to the Temporal resource.
64 |
65 | ```csharp
66 | // ./samples/AppHost/Program.cs
67 |
68 | // ...
69 |
70 | var temporal = builder.AddTemporalServerExecutable("temporal");
71 |
72 | builder.AddProject("worker") // my custom project
73 | .WithReference(temporal);
74 |
75 | // ...
76 | ```
77 |
78 | If using [Temporalio.Extensions.Hosting](https://github.com/temporalio/sdk-dotnet/blob/main/src/Temporalio.Extensions.Hosting/README.md) the client registration might look something like below. If we took the reference to the Temporal Aspire resource, then the TargetHost property is automatically injected under the key `ConnectionStrings:`. (e.g., this will be `builder.Configuration["ConnectionStrings:temporal"]` for a resource named "temporal" as above)
79 |
80 | ```csharp
81 | // register a client - ./samples/Api/Program.cs
82 | builder.Services
83 | .AddTemporalClient(opts =>
84 | {
85 | opts.TargetHost = builder.Configuration["ConnectionStrings:temporal"]; // or just self-configure localhost:7233
86 | opts.Namespace = "default";
87 | })
88 |
89 | // or
90 |
91 | // register a worker - ./samples/Worker/Program.cs
92 | builder.Services
93 | .AddTemporalClient(opts =>
94 | {
95 | opts.TargetHost = builder.Configuration["ConnectionStrings:temporal"]; // or just self-configure localhost:7233
96 | opts.Namespace = "default";
97 | })
98 | .AddHostedTemporalWorker("my-task-queue")
99 | .AddScopedActivities()
100 | .AddWorkflow();
101 | ```
102 |
103 | ## Observability
104 |
105 | The extension doesn't provide any setup for observability, but you can follow [Temporalio.Extensions.DiagnosticSource](https://github.com/temporalio/sdk-dotnet/blob/main/src/Temporalio.Extensions.DiagnosticSource/README.md) and [Temporalio.Extensions.Hosting](https://github.com/temporalio/sdk-dotnet/blob/main/src/Temporalio.Extensions.Hosting/TemporalHostingServiceCollectionExtensions.cs) to configure this on the temporal client. If using the Aspire Service Defaults, you'll need to configure the metrics and tracing accordingly.
106 |
107 | The sample folder has an example for configuring this with the Aspire Dashboard
108 |
109 | - [sample/Api/Program.cs](./sample/Api/Program.cs) for an example client
110 | - [sample/Worker/Program.cs](./sample/Worker/Program.cs) for an example worker
111 | - [sample/ServiceDefaults/Extensions.cs](./sample/ServiceDefaults/Extensions.cs) for an example of adding the custom meter and tracing sources to the service defaults.
112 |
113 | If done correctly, you should tracing and metrics on the Aspire dashboard:
114 |
115 | #### Tracing
116 |
117 | 
118 |
119 | #### Metrics
120 |
121 | 
122 |
123 |
124 | ## Configuration
125 |
126 | The dev server can be configured with a fluent builder
127 |
128 | ```csharp
129 | await builder.AddTemporalServerContainer("temporal", builder => builder.WithPort(1234))
130 | ```
131 |
132 | You can run `temporal server start-dev --help` to get more information about the CLI flags on the dev server. All available flags are mapped to a method on the builder.
133 |
134 | Available methods:
135 |
136 | ```csharp
137 | builder
138 | .WithDbFileName("/location/of/persistent/file") // --db-filename
139 | .WithNamespace("namespace-name", ...) // --namespace
140 | .WithPort(7233) // --port
141 | .WithHttpPort(7234) // --http-port
142 | .WithMetricsPort(7235) // --metrics-port
143 | .UiPort(8233) // --ui-port
144 | .WithHeadlessUi(true) // --headless
145 | .WithIp("127.0.0.1") // --ip
146 | .WithUiIp("127.0.0.1") // --ui-ip
147 | .WithUiAssetPath("/location/of/custom/assets") // --ui-asset-path
148 | .WithUiCodecEndpoint("http://localhost:8080") // --ui-codec-endpoint
149 | .WithLogFormat(LogFormat.Pretty) // --log-format
150 | .WithLogLevel(LogLevel.Info) // --log-level
151 | .WithSQLitePragma(SQLitePragma.JournalMode) // --sqlite-pragma
152 | ```
153 |
--------------------------------------------------------------------------------
/CLAUDE.md:
--------------------------------------------------------------------------------
1 | # CLAUDE.md
2 |
3 | This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4 |
5 | ## Project Overview
6 |
7 | InfinityFlow.Aspire.Temporal is a .NET Aspire extension that enables running the Temporal CLI dev server as either a container or executable resource. The library provides integration between .NET Aspire and Temporal workflow orchestration.
8 |
9 | **Note:** Container deployment is the recommended and well-supported approach. Executable deployment has known limitations (see https://github.com/dotnet/aspire/issues/1637 and https://github.com/temporalio/cli/issues/316).
10 |
11 | ## Build and Development Commands
12 |
13 | ### Build the solution
14 | ```bash
15 | dotnet build InfinityFlow.Aspire.Temporal.sln
16 | ```
17 |
18 | ### Build specific project
19 | ```bash
20 | dotnet build src/InfinityFlow.Aspire.Temporal/InfinityFlow.Aspire.Temporal.csproj
21 | ```
22 |
23 | ### Pack NuGet package
24 | ```bash
25 | dotnet pack src/InfinityFlow.Aspire.Temporal/InfinityFlow.Aspire.Temporal.csproj
26 | ```
27 |
28 | ### Run sample application
29 | ```bash
30 | dotnet run --project sample/AppHost/AppHost.csproj
31 | ```
32 |
33 | ### Manage package references
34 | ```bash
35 | # Add package reference
36 | dotnet add package
37 |
38 | # Update package reference
39 | dotnet add package
40 |
41 | # Remove package reference
42 | dotnet remove package
43 | ```
44 |
45 | ## Architecture
46 |
47 | ### Core Components
48 |
49 | The library consists of two main integration patterns:
50 |
51 | 1. **Container Resource** (`TemporalServerContainerResource`) - Uses the `temporalio/admin-tools:latest` Docker image
52 | 2. **Executable Resource** (`TemporalServerExecutableResource`) - Runs the Temporal CLI binary directly
53 |
54 | Both resources share the same configuration model through `TemporalServerResourceArguments`.
55 |
56 | ### Key Classes
57 |
58 | - **TemporalServerResourceBuilder** (src/InfinityFlow.Aspire.Temporal/TemporalServerResourceBuilder.cs:5)
59 | - Fluent builder for configuring Temporal server options
60 | - Provides methods for all CLI flags (ports, namespaces, logging, UI settings, etc.)
61 | - Returns `TemporalServerResourceArguments` via `Build()`
62 |
63 | - **TemporalServerResourceArguments** (src/InfinityFlow.Aspire.Temporal/TemporalServerResourceArguments.cs:6)
64 | - Holds all configuration properties (ports, log settings, namespaces, dynamic config)
65 | - `GetArgs()` method converts properties to CLI arguments for `temporal server start-dev`
66 | - Supports dynamic config values via `DynamicConfigValues` dictionary
67 |
68 | - **TemporalServerContainerBuilderExtensions** (src/InfinityFlow.Aspire.Temporal/TemporalServerContainerBuilderExtensions.cs:6)
69 | - `AddTemporalServerContainer()` extension methods for `IDistributedApplicationBuilder`
70 | - Configures container with proper endpoints (server:7233 gRPC, ui:8233 HTTP, optional metrics/http)
71 | - Server endpoint is marked as HTTP/2 service via `.AsHttp2Service()`
72 |
73 | - **TemporalServerExecutableBuilderExtensions** (src/InfinityFlow.Aspire.Temporal/TemporalServerExecutableBuilderExtensions.cs:6)
74 | - `AddTemporalServerExecutable()` extension methods
75 | - Configures endpoints with defaults (UI defaults to port+1000, metrics to 9000)
76 |
77 | - **Resource Classes** (src/InfinityFlow.Aspire.Temporal/TemporalServerExecutableResource.cs)
78 | - Both inherit from Aspire base classes (`ExecutableResource`, `ContainerResource`)
79 | - Implement `IResourceWithConnectionString` - connection string is the server endpoint host:port
80 | - Container resource also implements `IResourceWithEnvironment`
81 |
82 | ### Configuration Pattern
83 |
84 | The library uses a fluent builder pattern:
85 | ```csharp
86 | builder.AddTemporalServerContainer("temporal", x => x
87 | .WithLogFormat(LogFormat.Json)
88 | .WithLogLevel(LogLevel.Info)
89 | .WithNamespace("ns1", "ns2")
90 | .WithDynamicConfigValue("key", value));
91 | ```
92 |
93 | All `temporal server start-dev` CLI flags map to builder methods (src/InfinityFlow.Aspire.Temporal/TemporalServerResourceBuilder.cs).
94 |
95 | ### Enums
96 |
97 | Three enums define Temporal CLI options (src/InfinityFlow.Aspire.Temporal/Enums.cs):
98 | - `LogFormat`: Json, Pretty
99 | - `LogLevel`: Debug, Info, Warn, Error, Fatal
100 | - `SQLitePragma`: JournalMode, Synchronous
101 |
102 | `EnumHelpers` class converts enums to CLI string values.
103 |
104 | ## Project Structure
105 |
106 | - **src/InfinityFlow.Aspire.Temporal/** - Main library code
107 | - Target framework: net9.0
108 | - NuGet package ID: InfinityFlow.Aspire.Temporal
109 | - Dependencies: Aspire.Hosting.AppHost 9.5.0
110 |
111 | - **sample/** - Example Aspire application demonstrating usage
112 | - **AppHost/** - Aspire orchestration project showing both container and executable resources
113 | - **Worker/** - Example Temporal worker with workflow and activity implementations
114 | - **Api/** - Example API client
115 | - **ServiceDefaults/** - Shared service configuration (includes Temporal observability setup)
116 |
117 | ## Temporal Integration
118 |
119 | ### Connection String
120 |
121 | Both resources implement `IResourceWithConnectionString`. The connection string is automatically injected as `ConnectionStrings:` in referenced projects.
122 |
123 | Example: A resource named "temporal" exposes `builder.Configuration["ConnectionStrings:temporal"]` which resolves to the gRPC server endpoint (e.g., "localhost:7233").
124 |
125 | ### Observability
126 |
127 | The sample demonstrates Temporal observability integration (sample/Worker/Program.cs, sample/ServiceDefaults/Extensions.cs):
128 | - Uses `Temporalio.Extensions.DiagnosticSource` for tracing (`TracingInterceptor`)
129 | - Uses `Temporalio.Extensions.OpenTelemetry` for metrics (`CustomMetricMeter`)
130 | - Custom meter and tracing sources must be added to Aspire service defaults
131 |
132 | ### Endpoints
133 |
134 | Container resource endpoints:
135 | - **server**: gRPC endpoint (default 7233) - HTTP/2 service
136 | - **ui**: Web UI (default 8233) - HTTP service
137 | - **metrics**: Optional metrics endpoint
138 | - **http**: Optional HTTP API endpoint
139 |
140 | Executable resource endpoints have similar structure but with different default handling.
141 |
142 | ## Package Management
143 |
144 | This is a packable library project (IsPackable=true) with package validation enabled. When modifying:
145 | - Update `PackageVersion` in src/InfinityFlow.Aspire.Temporal/InfinityFlow.Aspire.Temporal.csproj:10
146 | - Include package assets from assets/ folder (packageIcon.png, README.md, LICENSE)
147 | - Documentation XML is generated automatically
148 | - SourceLink is configured for GitHub
149 |
150 | ## Important Notes
151 |
152 | - Container resource uses `0.0.0.0` as default IP binding (src/InfinityFlow.Aspire.Temporal/TemporalServerResourceArguments.cs:46)
153 | - Port defaults: server=7233, UI=8233
154 | - The "default" namespace is always created by Temporal
155 | - Dynamic config values support string, bool, int, float, double, long types (src/InfinityFlow.Aspire.Temporal/TemporalServerResourceArguments.cs:140-149)
156 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from `dotnet new gitignore`
5 |
6 | # dotenv files
7 | .env
8 |
9 | # User-specific files
10 | *.rsuser
11 | *.suo
12 | *.user
13 | *.userosscache
14 | *.sln.docstates
15 |
16 | # User-specific files (MonoDevelop/Xamarin Studio)
17 | *.userprefs
18 |
19 | # Mono auto generated files
20 | mono_crash.*
21 |
22 | # Build results
23 | [Dd]ebug/
24 | [Dd]ebugPublic/
25 | [Rr]elease/
26 | [Rr]eleases/
27 | x64/
28 | x86/
29 | [Ww][Ii][Nn]32/
30 | [Aa][Rr][Mm]/
31 | [Aa][Rr][Mm]64/
32 | bld/
33 | [Bb]in/
34 | [Oo]bj/
35 | [Ll]og/
36 | [Ll]ogs/
37 |
38 | # Visual Studio 2015/2017 cache/options directory
39 | .vs/
40 | # Uncomment if you have tasks that create the project's static files in wwwroot
41 | #wwwroot/
42 |
43 | # Visual Studio 2017 auto generated files
44 | Generated\ Files/
45 |
46 | # MSTest test Results
47 | [Tt]est[Rr]esult*/
48 | [Bb]uild[Ll]og.*
49 |
50 | # NUnit
51 | *.VisualState.xml
52 | TestResult.xml
53 | nunit-*.xml
54 |
55 | # Build Results of an ATL Project
56 | [Dd]ebugPS/
57 | [Rr]eleasePS/
58 | dlldata.c
59 |
60 | # Benchmark Results
61 | BenchmarkDotNet.Artifacts/
62 |
63 | # .NET
64 | project.lock.json
65 | project.fragment.lock.json
66 | artifacts/
67 |
68 | # Tye
69 | .tye/
70 |
71 | # ASP.NET Scaffolding
72 | ScaffoldingReadMe.txt
73 |
74 | # StyleCop
75 | StyleCopReport.xml
76 |
77 | # Files built by Visual Studio
78 | *_i.c
79 | *_p.c
80 | *_h.h
81 | *.ilk
82 | *.meta
83 | *.obj
84 | *.iobj
85 | *.pch
86 | *.pdb
87 | *.ipdb
88 | *.pgc
89 | *.pgd
90 | *.rsp
91 | *.sbr
92 | *.tlb
93 | *.tli
94 | *.tlh
95 | *.tmp
96 | *.tmp_proj
97 | *_wpftmp.csproj
98 | *.log
99 | *.tlog
100 | *.vspscc
101 | *.vssscc
102 | .builds
103 | *.pidb
104 | *.svclog
105 | *.scc
106 |
107 | # Chutzpah Test files
108 | _Chutzpah*
109 |
110 | # Visual C++ cache files
111 | ipch/
112 | *.aps
113 | *.ncb
114 | *.opendb
115 | *.opensdf
116 | *.sdf
117 | *.cachefile
118 | *.VC.db
119 | *.VC.VC.opendb
120 |
121 | # Visual Studio profiler
122 | *.psess
123 | *.vsp
124 | *.vspx
125 | *.sap
126 |
127 | # Visual Studio Trace Files
128 | *.e2e
129 |
130 | # TFS 2012 Local Workspace
131 | $tf/
132 |
133 | # Guidance Automation Toolkit
134 | *.gpState
135 |
136 | # ReSharper is a .NET coding add-in
137 | _ReSharper*/
138 | *.[Rr]e[Ss]harper
139 | *.DotSettings.user
140 |
141 | # TeamCity is a build add-in
142 | _TeamCity*
143 |
144 | # DotCover is a Code Coverage Tool
145 | *.dotCover
146 |
147 | # AxoCover is a Code Coverage Tool
148 | .axoCover/*
149 | !.axoCover/settings.json
150 |
151 | # Coverlet is a free, cross platform Code Coverage Tool
152 | coverage*.json
153 | coverage*.xml
154 | coverage*.info
155 |
156 | # Visual Studio code coverage results
157 | *.coverage
158 | *.coveragexml
159 |
160 | # NCrunch
161 | _NCrunch_*
162 | .*crunch*.local.xml
163 | nCrunchTemp_*
164 |
165 | # MightyMoose
166 | *.mm.*
167 | AutoTest.Net/
168 |
169 | # Web workbench (sass)
170 | .sass-cache/
171 |
172 | # Installshield output folder
173 | [Ee]xpress/
174 |
175 | # DocProject is a documentation generator add-in
176 | DocProject/buildhelp/
177 | DocProject/Help/*.HxT
178 | DocProject/Help/*.HxC
179 | DocProject/Help/*.hhc
180 | DocProject/Help/*.hhk
181 | DocProject/Help/*.hhp
182 | DocProject/Help/Html2
183 | DocProject/Help/html
184 |
185 | # Click-Once directory
186 | publish/
187 |
188 | # Publish Web Output
189 | *.[Pp]ublish.xml
190 | *.azurePubxml
191 | # Note: Comment the next line if you want to checkin your web deploy settings,
192 | # but database connection strings (with potential passwords) will be unencrypted
193 | *.pubxml
194 | *.publishproj
195 |
196 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
197 | # checkin your Azure Web App publish settings, but sensitive information contained
198 | # in these scripts will be unencrypted
199 | PublishScripts/
200 |
201 | # NuGet Packages
202 | *.nupkg
203 | # NuGet Symbol Packages
204 | *.snupkg
205 | # The packages folder can be ignored because of Package Restore
206 | **/[Pp]ackages/*
207 | # except build/, which is used as an MSBuild target.
208 | !**/[Pp]ackages/build/
209 | # Uncomment if necessary however generally it will be regenerated when needed
210 | #!**/[Pp]ackages/repositories.config
211 | # NuGet v3's project.json files produces more ignorable files
212 | *.nuget.props
213 | *.nuget.targets
214 |
215 | # Microsoft Azure Build Output
216 | csx/
217 | *.build.csdef
218 |
219 | # Microsoft Azure Emulator
220 | ecf/
221 | rcf/
222 |
223 | # Windows Store app package directories and files
224 | AppPackages/
225 | BundleArtifacts/
226 | Package.StoreAssociation.xml
227 | _pkginfo.txt
228 | *.appx
229 | *.appxbundle
230 | *.appxupload
231 |
232 | # Visual Studio cache files
233 | # files ending in .cache can be ignored
234 | *.[Cc]ache
235 | # but keep track of directories ending in .cache
236 | !?*.[Cc]ache/
237 |
238 | # Others
239 | ClientBin/
240 | ~$*
241 | *~
242 | *.dbmdl
243 | *.dbproj.schemaview
244 | *.jfm
245 | *.pfx
246 | *.publishsettings
247 | orleans.codegen.cs
248 |
249 | # Including strong name files can present a security risk
250 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
251 | #*.snk
252 |
253 | # Since there are multiple workflows, uncomment next line to ignore bower_components
254 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
255 | #bower_components/
256 |
257 | # RIA/Silverlight projects
258 | Generated_Code/
259 |
260 | # Backup & report files from converting an old project file
261 | # to a newer Visual Studio version. Backup files are not needed,
262 | # because we have git ;-)
263 | _UpgradeReport_Files/
264 | Backup*/
265 | UpgradeLog*.XML
266 | UpgradeLog*.htm
267 | ServiceFabricBackup/
268 | *.rptproj.bak
269 |
270 | # SQL Server files
271 | *.mdf
272 | *.ldf
273 | *.ndf
274 |
275 | # Business Intelligence projects
276 | *.rdl.data
277 | *.bim.layout
278 | *.bim_*.settings
279 | *.rptproj.rsuser
280 | *- [Bb]ackup.rdl
281 | *- [Bb]ackup ([0-9]).rdl
282 | *- [Bb]ackup ([0-9][0-9]).rdl
283 |
284 | # Microsoft Fakes
285 | FakesAssemblies/
286 |
287 | # GhostDoc plugin setting file
288 | *.GhostDoc.xml
289 |
290 | # Node.js Tools for Visual Studio
291 | .ntvs_analysis.dat
292 | node_modules/
293 |
294 | # Visual Studio 6 build log
295 | *.plg
296 |
297 | # Visual Studio 6 workspace options file
298 | *.opt
299 |
300 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
301 | *.vbw
302 |
303 | # Visual Studio 6 auto-generated project file (contains which files were open etc.)
304 | *.vbp
305 |
306 | # Visual Studio 6 workspace and project file (working project files containing files to include in project)
307 | *.dsw
308 | *.dsp
309 |
310 | # Visual Studio 6 technical files
311 | *.ncb
312 | *.aps
313 |
314 | # Visual Studio LightSwitch build output
315 | **/*.HTMLClient/GeneratedArtifacts
316 | **/*.DesktopClient/GeneratedArtifacts
317 | **/*.DesktopClient/ModelManifest.xml
318 | **/*.Server/GeneratedArtifacts
319 | **/*.Server/ModelManifest.xml
320 | _Pvt_Extensions
321 |
322 | # Paket dependency manager
323 | .paket/paket.exe
324 | paket-files/
325 |
326 | # FAKE - F# Make
327 | .fake/
328 |
329 | # CodeRush personal settings
330 | .cr/personal
331 |
332 | # Python Tools for Visual Studio (PTVS)
333 | __pycache__/
334 | *.pyc
335 |
336 | # Cake - Uncomment if you are using it
337 | # tools/**
338 | # !tools/packages.config
339 |
340 | # Tabs Studio
341 | *.tss
342 |
343 | # Telerik's JustMock configuration file
344 | *.jmconfig
345 |
346 | # BizTalk build output
347 | *.btp.cs
348 | *.btm.cs
349 | *.odx.cs
350 | *.xsd.cs
351 |
352 | # OpenCover UI analysis results
353 | OpenCover/
354 |
355 | # Azure Stream Analytics local run output
356 | ASALocalRun/
357 |
358 | # MSBuild Binary and Structured Log
359 | *.binlog
360 |
361 | # NVidia Nsight GPU debugger configuration file
362 | *.nvuser
363 |
364 | # MFractors (Xamarin productivity tool) working folder
365 | .mfractor/
366 |
367 | # Local History for Visual Studio
368 | .localhistory/
369 |
370 | # Visual Studio History (VSHistory) files
371 | .vshistory/
372 |
373 | # BeatPulse healthcheck temp database
374 | healthchecksdb
375 |
376 | # Backup folder for Package Reference Convert tool in Visual Studio 2017
377 | MigrationBackup/
378 |
379 | # Ionide (cross platform F# VS Code tools) working folder
380 | .ionide/
381 |
382 | # Fody - auto-generated XML schema
383 | FodyWeavers.xsd
384 |
385 | # VS Code files for those working on multiple tools
386 | .vscode/*
387 | !.vscode/settings.json
388 | !.vscode/tasks.json
389 | !.vscode/launch.json
390 | !.vscode/extensions.json
391 | *.code-workspace
392 |
393 | # Local History for Visual Studio Code
394 | .history/
395 |
396 | # Windows Installer files from build outputs
397 | *.cab
398 | *.msi
399 | *.msix
400 | *.msm
401 | *.msp
402 |
403 | # JetBrains Rider
404 | *.sln.iml
405 | .idea
406 |
407 | ##
408 | ## Visual studio for Mac
409 | ##
410 |
411 |
412 | # globs
413 | Makefile.in
414 | *.userprefs
415 | *.usertasks
416 | config.make
417 | config.status
418 | aclocal.m4
419 | install-sh
420 | autom4te.cache/
421 | *.tar.gz
422 | tarballs/
423 | test-results/
424 |
425 | # Mac bundle stuff
426 | *.dmg
427 | *.app
428 |
429 | # content below from: https://github.com/github/gitignore/blob/master/Global/macOS.gitignore
430 | # General
431 | .DS_Store
432 | .AppleDouble
433 | .LSOverride
434 |
435 | # Icon must end with two \r
436 | Icon
437 |
438 |
439 | # Thumbnails
440 | ._*
441 |
442 | # Files that might appear in the root of a volume
443 | .DocumentRevisions-V100
444 | .fseventsd
445 | .Spotlight-V100
446 | .TemporaryItems
447 | .Trashes
448 | .VolumeIcon.icns
449 | .com.apple.timemachine.donotpresent
450 |
451 | # Directories potentially created on remote AFP share
452 | .AppleDB
453 | .AppleDesktop
454 | Network Trash Folder
455 | Temporary Items
456 | .apdisk
457 |
458 | # content below from: https://github.com/github/gitignore/blob/master/Global/Windows.gitignore
459 | # Windows thumbnail cache files
460 | Thumbs.db
461 | ehthumbs.db
462 | ehthumbs_vista.db
463 |
464 | # Dump file
465 | *.stackdump
466 |
467 | # Folder config file
468 | [Dd]esktop.ini
469 |
470 | # Recycle Bin used on file shares
471 | $RECYCLE.BIN/
472 |
473 | # Windows Installer files
474 | *.cab
475 | *.msi
476 | *.msix
477 | *.msm
478 | *.msp
479 |
480 | # Windows shortcuts
481 | *.lnk
482 |
483 | # Vim temporary swap files
484 | *.swp
485 |
486 | appsettings.Development.json
487 | temporal.sqlite
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | # All files
4 | [*]
5 | indent_style = space
6 |
7 | # Xml files
8 | [*.xml]
9 | indent_size = 2
10 |
11 | # C# files
12 | [*.cs]
13 |
14 | #### Core EditorConfig Options ####
15 |
16 | # Indentation and spacing
17 | indent_size = 4
18 | tab_width = 4
19 |
20 | # New line preferences
21 | end_of_line = crlf
22 | insert_final_newline = false
23 |
24 | #### .NET Coding Conventions ####
25 | [*.{cs,vb}]
26 |
27 | # Organize usings
28 | dotnet_separate_import_directive_groups = true
29 | dotnet_sort_system_directives_first = true
30 | file_header_template = unset
31 |
32 | # this. and Me. preferences
33 | dotnet_style_qualification_for_event = false:silent
34 | dotnet_style_qualification_for_field = false:silent
35 | dotnet_style_qualification_for_method = false:silent
36 | dotnet_style_qualification_for_property = false:silent
37 |
38 | # Language keywords vs BCL types preferences
39 | dotnet_style_predefined_type_for_locals_parameters_members = true:silent
40 | dotnet_style_predefined_type_for_member_access = true:silent
41 |
42 | # Parentheses preferences
43 | dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent
44 | dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent
45 | dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent
46 | dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent
47 |
48 | # Modifier preferences
49 | dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent
50 |
51 | # Expression-level preferences
52 | dotnet_style_coalesce_expression = true:suggestion
53 | dotnet_style_collection_initializer = true:suggestion
54 | dotnet_style_explicit_tuple_names = true:suggestion
55 | dotnet_style_null_propagation = true:suggestion
56 | dotnet_style_object_initializer = true:suggestion
57 | dotnet_style_operator_placement_when_wrapping = beginning_of_line
58 | dotnet_style_prefer_auto_properties = true:suggestion
59 | dotnet_style_prefer_compound_assignment = true:suggestion
60 | dotnet_style_prefer_conditional_expression_over_assignment = true:suggestion
61 | dotnet_style_prefer_conditional_expression_over_return = true:suggestion
62 | dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
63 | dotnet_style_prefer_inferred_tuple_names = true:suggestion
64 | dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion
65 | dotnet_style_prefer_simplified_boolean_expressions = true:suggestion
66 | dotnet_style_prefer_simplified_interpolation = true:suggestion
67 |
68 | # Field preferences
69 | dotnet_style_readonly_field = true:warning
70 |
71 | # Parameter preferences
72 | dotnet_code_quality_unused_parameters = all:suggestion
73 |
74 | # Suppression preferences
75 | dotnet_remove_unnecessary_suppression_exclusions = none
76 |
77 | #### C# Coding Conventions ####
78 | [*.cs]
79 |
80 | # var preferences
81 | csharp_style_var_elsewhere = false:silent
82 | csharp_style_var_for_built_in_types = false:silent
83 | csharp_style_var_when_type_is_apparent = false:silent
84 |
85 | # Expression-bodied members
86 | csharp_style_expression_bodied_accessors = true:silent
87 | csharp_style_expression_bodied_constructors = false:silent
88 | csharp_style_expression_bodied_indexers = true:silent
89 | csharp_style_expression_bodied_lambdas = true:suggestion
90 | csharp_style_expression_bodied_local_functions = false:silent
91 | csharp_style_expression_bodied_methods = false:silent
92 | csharp_style_expression_bodied_operators = false:silent
93 | csharp_style_expression_bodied_properties = true:silent
94 |
95 | # Pattern matching preferences
96 | csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
97 | csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
98 | csharp_style_prefer_not_pattern = true:suggestion
99 | csharp_style_prefer_pattern_matching = true:silent
100 | csharp_style_prefer_switch_expression = true:suggestion
101 |
102 | # Null-checking preferences
103 | csharp_style_conditional_delegate_call = true:suggestion
104 |
105 | # Modifier preferences
106 | csharp_prefer_static_local_function = true:warning
107 | csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:silent
108 |
109 | # Code-block preferences
110 | csharp_prefer_braces = true:silent
111 | csharp_prefer_simple_using_statement = true:suggestion
112 |
113 | # Expression-level preferences
114 | csharp_prefer_simple_default_expression = true:suggestion
115 | csharp_style_deconstructed_variable_declaration = true:suggestion
116 | csharp_style_inlined_variable_declaration = true:suggestion
117 | csharp_style_pattern_local_over_anonymous_function = true:suggestion
118 | csharp_style_prefer_index_operator = true:suggestion
119 | csharp_style_prefer_range_operator = true:suggestion
120 | csharp_style_throw_expression = true:suggestion
121 | csharp_style_unused_value_assignment_preference = discard_variable:suggestion
122 | csharp_style_unused_value_expression_statement_preference = discard_variable:silent
123 |
124 | # 'using' directive preferences
125 | csharp_using_directive_placement = outside_namespace:silent
126 |
127 | #### C# Formatting Rules ####
128 |
129 | # New line preferences
130 | csharp_new_line_before_catch = true
131 | csharp_new_line_before_else = true
132 | csharp_new_line_before_finally = true
133 | csharp_new_line_before_members_in_anonymous_types = true
134 | csharp_new_line_before_members_in_object_initializers = true
135 | csharp_new_line_before_open_brace = all
136 | csharp_new_line_between_query_expression_clauses = true
137 |
138 | # Indentation preferences
139 | csharp_indent_block_contents = true
140 | csharp_indent_braces = false
141 | csharp_indent_case_contents = true
142 | csharp_indent_case_contents_when_block = true
143 | csharp_indent_labels = one_less_than_current
144 | csharp_indent_switch_labels = true
145 |
146 | # Space preferences
147 | csharp_space_after_cast = false
148 | csharp_space_after_colon_in_inheritance_clause = true
149 | csharp_space_after_comma = true
150 | csharp_space_after_dot = false
151 | csharp_space_after_keywords_in_control_flow_statements = true
152 | csharp_space_after_semicolon_in_for_statement = true
153 | csharp_space_around_binary_operators = before_and_after
154 | csharp_space_around_declaration_statements = false
155 | csharp_space_before_colon_in_inheritance_clause = true
156 | csharp_space_before_comma = false
157 | csharp_space_before_dot = false
158 | csharp_space_before_open_square_brackets = false
159 | csharp_space_before_semicolon_in_for_statement = false
160 | csharp_space_between_empty_square_brackets = false
161 | csharp_space_between_method_call_empty_parameter_list_parentheses = false
162 | csharp_space_between_method_call_name_and_opening_parenthesis = false
163 | csharp_space_between_method_call_parameter_list_parentheses = false
164 | csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
165 | csharp_space_between_method_declaration_name_and_open_parenthesis = false
166 | csharp_space_between_method_declaration_parameter_list_parentheses = false
167 | csharp_space_between_parentheses = false
168 | csharp_space_between_square_brackets = false
169 |
170 | # Wrapping preferences
171 | csharp_preserve_single_line_blocks = true
172 | csharp_preserve_single_line_statements = true
173 |
174 | #### Naming styles ####
175 | [*.{cs,vb}]
176 |
177 | # Naming rules
178 |
179 | dotnet_naming_rule.types_and_namespaces_should_be_pascalcase.severity = suggestion
180 | dotnet_naming_rule.types_and_namespaces_should_be_pascalcase.symbols = types_and_namespaces
181 | dotnet_naming_rule.types_and_namespaces_should_be_pascalcase.style = pascalcase
182 |
183 | dotnet_naming_rule.interfaces_should_be_ipascalcase.severity = suggestion
184 | dotnet_naming_rule.interfaces_should_be_ipascalcase.symbols = interfaces
185 | dotnet_naming_rule.interfaces_should_be_ipascalcase.style = ipascalcase
186 |
187 | dotnet_naming_rule.type_parameters_should_be_tpascalcase.severity = suggestion
188 | dotnet_naming_rule.type_parameters_should_be_tpascalcase.symbols = type_parameters
189 | dotnet_naming_rule.type_parameters_should_be_tpascalcase.style = tpascalcase
190 |
191 | dotnet_naming_rule.methods_should_be_pascalcase.severity = suggestion
192 | dotnet_naming_rule.methods_should_be_pascalcase.symbols = methods
193 | dotnet_naming_rule.methods_should_be_pascalcase.style = pascalcase
194 |
195 | dotnet_naming_rule.properties_should_be_pascalcase.severity = suggestion
196 | dotnet_naming_rule.properties_should_be_pascalcase.symbols = properties
197 | dotnet_naming_rule.properties_should_be_pascalcase.style = pascalcase
198 |
199 | dotnet_naming_rule.events_should_be_pascalcase.severity = suggestion
200 | dotnet_naming_rule.events_should_be_pascalcase.symbols = events
201 | dotnet_naming_rule.events_should_be_pascalcase.style = pascalcase
202 |
203 | dotnet_naming_rule.local_variables_should_be_camelcase.severity = suggestion
204 | dotnet_naming_rule.local_variables_should_be_camelcase.symbols = local_variables
205 | dotnet_naming_rule.local_variables_should_be_camelcase.style = camelcase
206 |
207 | dotnet_naming_rule.local_constants_should_be_camelcase.severity = suggestion
208 | dotnet_naming_rule.local_constants_should_be_camelcase.symbols = local_constants
209 | dotnet_naming_rule.local_constants_should_be_camelcase.style = camelcase
210 |
211 | dotnet_naming_rule.parameters_should_be_camelcase.severity = suggestion
212 | dotnet_naming_rule.parameters_should_be_camelcase.symbols = parameters
213 | dotnet_naming_rule.parameters_should_be_camelcase.style = camelcase
214 |
215 | dotnet_naming_rule.public_fields_should_be_pascalcase.severity = suggestion
216 | dotnet_naming_rule.public_fields_should_be_pascalcase.symbols = public_fields
217 | dotnet_naming_rule.public_fields_should_be_pascalcase.style = pascalcase
218 |
219 | dotnet_naming_rule.private_fields_should_be__camelcase.severity = suggestion
220 | dotnet_naming_rule.private_fields_should_be__camelcase.symbols = private_fields
221 | dotnet_naming_rule.private_fields_should_be__camelcase.style = _camelcase
222 |
223 | dotnet_naming_rule.private_static_fields_should_be_s_camelcase.severity = suggestion
224 | dotnet_naming_rule.private_static_fields_should_be_s_camelcase.symbols = private_static_fields
225 | dotnet_naming_rule.private_static_fields_should_be_s_camelcase.style = s_camelcase
226 |
227 | dotnet_naming_rule.public_constant_fields_should_be_pascalcase.severity = suggestion
228 | dotnet_naming_rule.public_constant_fields_should_be_pascalcase.symbols = public_constant_fields
229 | dotnet_naming_rule.public_constant_fields_should_be_pascalcase.style = pascalcase
230 |
231 | dotnet_naming_rule.private_constant_fields_should_be_pascalcase.severity = suggestion
232 | dotnet_naming_rule.private_constant_fields_should_be_pascalcase.symbols = private_constant_fields
233 | dotnet_naming_rule.private_constant_fields_should_be_pascalcase.style = pascalcase
234 |
235 | dotnet_naming_rule.public_static_readonly_fields_should_be_pascalcase.severity = suggestion
236 | dotnet_naming_rule.public_static_readonly_fields_should_be_pascalcase.symbols = public_static_readonly_fields
237 | dotnet_naming_rule.public_static_readonly_fields_should_be_pascalcase.style = pascalcase
238 |
239 | dotnet_naming_rule.private_static_readonly_fields_should_be_pascalcase.severity = suggestion
240 | dotnet_naming_rule.private_static_readonly_fields_should_be_pascalcase.symbols = private_static_readonly_fields
241 | dotnet_naming_rule.private_static_readonly_fields_should_be_pascalcase.style = pascalcase
242 |
243 | dotnet_naming_rule.enums_should_be_pascalcase.severity = suggestion
244 | dotnet_naming_rule.enums_should_be_pascalcase.symbols = enums
245 | dotnet_naming_rule.enums_should_be_pascalcase.style = pascalcase
246 |
247 | dotnet_naming_rule.local_functions_should_be_pascalcase.severity = suggestion
248 | dotnet_naming_rule.local_functions_should_be_pascalcase.symbols = local_functions
249 | dotnet_naming_rule.local_functions_should_be_pascalcase.style = pascalcase
250 |
251 | dotnet_naming_rule.non_field_members_should_be_pascalcase.severity = suggestion
252 | dotnet_naming_rule.non_field_members_should_be_pascalcase.symbols = non_field_members
253 | dotnet_naming_rule.non_field_members_should_be_pascalcase.style = pascalcase
254 |
255 | # Symbol specifications
256 |
257 | dotnet_naming_symbols.interfaces.applicable_kinds = interface
258 | dotnet_naming_symbols.interfaces.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
259 | dotnet_naming_symbols.interfaces.required_modifiers =
260 |
261 | dotnet_naming_symbols.enums.applicable_kinds = enum
262 | dotnet_naming_symbols.enums.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
263 | dotnet_naming_symbols.enums.required_modifiers =
264 |
265 | dotnet_naming_symbols.events.applicable_kinds = event
266 | dotnet_naming_symbols.events.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
267 | dotnet_naming_symbols.events.required_modifiers =
268 |
269 | dotnet_naming_symbols.methods.applicable_kinds = method
270 | dotnet_naming_symbols.methods.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
271 | dotnet_naming_symbols.methods.required_modifiers =
272 |
273 | dotnet_naming_symbols.properties.applicable_kinds = property
274 | dotnet_naming_symbols.properties.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
275 | dotnet_naming_symbols.properties.required_modifiers =
276 |
277 | dotnet_naming_symbols.public_fields.applicable_kinds = field
278 | dotnet_naming_symbols.public_fields.applicable_accessibilities = public, internal
279 | dotnet_naming_symbols.public_fields.required_modifiers =
280 |
281 | dotnet_naming_symbols.private_fields.applicable_kinds = field
282 | dotnet_naming_symbols.private_fields.applicable_accessibilities = private, protected, protected_internal, private_protected
283 | dotnet_naming_symbols.private_fields.required_modifiers =
284 |
285 | dotnet_naming_symbols.private_static_fields.applicable_kinds = field
286 | dotnet_naming_symbols.private_static_fields.applicable_accessibilities = private, protected, protected_internal, private_protected
287 | dotnet_naming_symbols.private_static_fields.required_modifiers = static
288 |
289 | dotnet_naming_symbols.types_and_namespaces.applicable_kinds = namespace, class, struct, interface, enum
290 | dotnet_naming_symbols.types_and_namespaces.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
291 | dotnet_naming_symbols.types_and_namespaces.required_modifiers =
292 |
293 | dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
294 | dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
295 | dotnet_naming_symbols.non_field_members.required_modifiers =
296 |
297 | dotnet_naming_symbols.type_parameters.applicable_kinds = namespace
298 | dotnet_naming_symbols.type_parameters.applicable_accessibilities = *
299 | dotnet_naming_symbols.type_parameters.required_modifiers =
300 |
301 | dotnet_naming_symbols.private_constant_fields.applicable_kinds = field
302 | dotnet_naming_symbols.private_constant_fields.applicable_accessibilities = private, protected, protected_internal, private_protected
303 | dotnet_naming_symbols.private_constant_fields.required_modifiers = const
304 |
305 | dotnet_naming_symbols.local_variables.applicable_kinds = local
306 | dotnet_naming_symbols.local_variables.applicable_accessibilities = local
307 | dotnet_naming_symbols.local_variables.required_modifiers =
308 |
309 | dotnet_naming_symbols.local_constants.applicable_kinds = local
310 | dotnet_naming_symbols.local_constants.applicable_accessibilities = local
311 | dotnet_naming_symbols.local_constants.required_modifiers = const
312 |
313 | dotnet_naming_symbols.parameters.applicable_kinds = parameter
314 | dotnet_naming_symbols.parameters.applicable_accessibilities = *
315 | dotnet_naming_symbols.parameters.required_modifiers =
316 |
317 | dotnet_naming_symbols.public_constant_fields.applicable_kinds = field
318 | dotnet_naming_symbols.public_constant_fields.applicable_accessibilities = public, internal
319 | dotnet_naming_symbols.public_constant_fields.required_modifiers = const
320 |
321 | dotnet_naming_symbols.public_static_readonly_fields.applicable_kinds = field
322 | dotnet_naming_symbols.public_static_readonly_fields.applicable_accessibilities = public, internal
323 | dotnet_naming_symbols.public_static_readonly_fields.required_modifiers = readonly, static
324 |
325 | dotnet_naming_symbols.private_static_readonly_fields.applicable_kinds = field
326 | dotnet_naming_symbols.private_static_readonly_fields.applicable_accessibilities = private, protected, protected_internal, private_protected
327 | dotnet_naming_symbols.private_static_readonly_fields.required_modifiers = readonly, static
328 |
329 | dotnet_naming_symbols.local_functions.applicable_kinds = local_function
330 | dotnet_naming_symbols.local_functions.applicable_accessibilities = *
331 | dotnet_naming_symbols.local_functions.required_modifiers =
332 |
333 | # Naming styles
334 |
335 | dotnet_naming_style.pascalcase.required_prefix =
336 | dotnet_naming_style.pascalcase.required_suffix =
337 | dotnet_naming_style.pascalcase.word_separator =
338 | dotnet_naming_style.pascalcase.capitalization = pascal_case
339 |
340 | dotnet_naming_style.ipascalcase.required_prefix = I
341 | dotnet_naming_style.ipascalcase.required_suffix =
342 | dotnet_naming_style.ipascalcase.word_separator =
343 | dotnet_naming_style.ipascalcase.capitalization = pascal_case
344 |
345 | dotnet_naming_style.tpascalcase.required_prefix = T
346 | dotnet_naming_style.tpascalcase.required_suffix =
347 | dotnet_naming_style.tpascalcase.word_separator =
348 | dotnet_naming_style.tpascalcase.capitalization = pascal_case
349 |
350 | dotnet_naming_style._camelcase.required_prefix = _
351 | dotnet_naming_style._camelcase.required_suffix =
352 | dotnet_naming_style._camelcase.word_separator =
353 | dotnet_naming_style._camelcase.capitalization = camel_case
354 |
355 | dotnet_naming_style.camelcase.required_prefix =
356 | dotnet_naming_style.camelcase.required_suffix =
357 | dotnet_naming_style.camelcase.word_separator =
358 | dotnet_naming_style.camelcase.capitalization = camel_case
359 |
360 | dotnet_naming_style.s_camelcase.required_prefix = s_
361 | dotnet_naming_style.s_camelcase.required_suffix =
362 | dotnet_naming_style.s_camelcase.word_separator =
363 | dotnet_naming_style.s_camelcase.capitalization = camel_case
364 |
365 |
--------------------------------------------------------------------------------