diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..cdf0b61
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,50 @@
+# Contributing
+
+Not all contributions are code! We welcome contributions from everyone. Please see our [contributing guide](#guide) for more information.
+
+## Guide
+
+All contributions to this repository should follow a few simple rules:
+
+1. All contributions must be licensed under the [MIT License](LICENSE)
+2. All contributions are subject to the [Code of Conduct](#code-of-conduct)
+3. All contributions must be made via pull request
+4. All contributions are subject to review by a maintainer of the repository, and may be rejected for any reason at any time, even after being merged to `main`
+5. Feature requests and bug reports should be made via [GitHub Issues](https://github.com/frankhaugen/Frank.PulseFlow/issues)
+6. No contribution is too small, but they can be too large. If you're not sure if your contribution is too large, split it into multiple pull requests, or ask a maintainer for guidance, (You can find a list of maintainers in the [MAINTAINERS](MAINTAINERS.md) file)
+ 6.1. You can have multiple pull requests open at the same time, and reference each other in the description of the pull request and the same issue, (this is called a "pull request chain" and please use X of Y in the title of the pull request to indicate that it is part of a chain)
+7. All contributions must be made in English (this includes comments, commit messages, pull request descriptions, etc.)
+8. All contributions must be made in a way that is consistent with the existing codebase, (e.g. use the same coding style, naming conventions, etc.), see [Coding Style](STYLE.md) for more information
+
+
+## Getting Started
+
+1. Fork the repository on GitHub
+2. Install the latest version of [.NET (Core)](https://dotnet.microsoft.com/download)
+3. Install the latest version of [Visual Studio](https://visualstudio.microsoft.com/downloads/) or [Visual Studio Code](https://code.visualstudio.com/download) (or your preferred editor)
+4. Clone the forked repository to your local machine
+5. Open the solution in Visual Studio or Visual Studio Code
+6. Create a branch for your changes
+7. Make your changes
+8. Build and test your changes
+9. Commit and push your changes to your forked repository
+10. Create a pull request to the `main` branch of the repository, and mention the issue number that you're addressing, (e.g. `#1234`) in the description of the pull request. Create a new issue if one does not already exist, describing the problem and how you solved it.
+11. Wait for a maintainer to review your pull request and either merge it or request changes
+
+## Building and Testing
+
+### Using command line
+
+1. Navigate to the root directory of the repository
+2. Run `dotnet build` to build the solution or `./build.ps1` on Windows or `pwsh ./build.ps1` on Linux/macOS
+3. Run `dotnet test` to run the tests or `./test.ps1` on Windows or `pwsh ./test.ps1` on Linux/macOS
+4. Run `dotnet pack` to create NuGet packages or `./pack.ps1` on Windows or `pwsh ./pack.ps1` on Linux/macOS
+5. Use the packages in the `artifacts/packages` directory in your application to test that they work as expected
+
+## Code of Conduct
+
+This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact the maintainers of this project (see below).
+
+## Maintainers
+
+Repository owners and maintainers are listed in the [MAINTAINERS](MAINTAINERS.md) file.
\ No newline at end of file
diff --git a/Frank.PulseFlow.Sample/.gitignore b/Frank.PulseFlow.Sample/.gitignore
new file mode 100644
index 0000000..8afdcb6
--- /dev/null
+++ b/Frank.PulseFlow.Sample/.gitignore
@@ -0,0 +1,454 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# Tye
+.tye/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*.json
+coverage*.xml
+coverage*.info
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# Fody - auto-generated XML schema
+FodyWeavers.xsd
+
+##
+## Visual studio for Mac
+##
+
+
+# globs
+Makefile.in
+*.userprefs
+*.usertasks
+config.make
+config.status
+aclocal.m4
+install-sh
+autom4te.cache/
+*.tar.gz
+tarballs/
+test-results/
+
+# Mac bundle stuff
+*.dmg
+*.app
+
+# content below from: https://github.com/github/gitignore/blob/master/Global/macOS.gitignore
+# General
+.DS_Store
+.AppleDouble
+.LSOverride
+
+# Icon must end with two \r
+Icon
+
+
+# Thumbnails
+._*
+
+# Files that might appear in the root of a volume
+.DocumentRevisions-V100
+.fseventsd
+.Spotlight-V100
+.TemporaryItems
+.Trashes
+.VolumeIcon.icns
+.com.apple.timemachine.donotpresent
+
+# Directories potentially created on remote AFP share
+.AppleDB
+.AppleDesktop
+Network Trash Folder
+Temporary Items
+.apdisk
+
+# content below from: https://github.com/github/gitignore/blob/master/Global/Windows.gitignore
+# Windows thumbnail cache files
+Thumbs.db
+ehthumbs.db
+ehthumbs_vista.db
+
+# Dump file
+*.stackdump
+
+# Folder config file
+[Dd]esktop.ini
+
+# Recycle Bin used on file shares
+$RECYCLE.BIN/
+
+# Windows Installer files
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# Windows shortcuts
+*.lnk
+
+# JetBrains Rider
+.idea/
+*.sln.iml
+
+##
+## Visual Studio Code
+##
+.vscode/*
+!.vscode/settings.json
+!.vscode/tasks.json
+!.vscode/launch.json
+!.vscode/extensions.json
diff --git a/Frank.PulseFlow.Sample/Directory.Build.props b/Frank.PulseFlow.Sample/Directory.Build.props
new file mode 100644
index 0000000..b7d1f09
--- /dev/null
+++ b/Frank.PulseFlow.Sample/Directory.Build.props
@@ -0,0 +1,6 @@
+
+
+ enable
+ 11.0.6
+
+
diff --git a/Frank.PulseFlow.Sample/Frank.PulseFlow.Sample.sln b/Frank.PulseFlow.Sample/Frank.PulseFlow.Sample.sln
new file mode 100644
index 0000000..b96b9e6
--- /dev/null
+++ b/Frank.PulseFlow.Sample/Frank.PulseFlow.Sample.sln
@@ -0,0 +1,54 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.3.32811.315
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Frank.PulseFlow.Sample", "Frank.PulseFlow.Sample\Frank.PulseFlow.Sample.csproj", "{EBFA8512-1EA5-4D8C-B4AC-AB5B48A6D568}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Frank.PulseFlow.Sample.Desktop", "Frank.PulseFlow.Sample.Desktop\Frank.PulseFlow.Sample.Desktop.csproj", "{ABC31E74-02FF-46EB-B3B2-4E6AE43B456C}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Frank.PulseFlow.Sample.Browser", "Frank.PulseFlow.Sample.Browser\Frank.PulseFlow.Sample.Browser.csproj", "{1C1A049E-235C-4CD0-B6FA-D53AC418F4DA}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Frank.PulseFlow.Sample.iOS", "Frank.PulseFlow.Sample.iOS\Frank.PulseFlow.Sample.iOS.csproj", "{EBD9022F-BC83-4846-9A11-6F7F3772DC64}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Frank.PulseFlow.Sample.Android", "Frank.PulseFlow.Sample.Android\Frank.PulseFlow.Sample.Android.csproj", "{7AD1DAC8-7FBE-49D5-8614-7321233DB82E}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{3DA99C4E-89E3-4049-9C22-0A7EC60D83D8}"
+ ProjectSection(SolutionItems) = preProject
+ Directory.Build.props = Directory.Build.props
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {EBFA8512-1EA5-4D8C-B4AC-AB5B48A6D568}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {EBFA8512-1EA5-4D8C-B4AC-AB5B48A6D568}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {EBFA8512-1EA5-4D8C-B4AC-AB5B48A6D568}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {EBFA8512-1EA5-4D8C-B4AC-AB5B48A6D568}.Release|Any CPU.Build.0 = Release|Any CPU
+ {ABC31E74-02FF-46EB-B3B2-4E6AE43B456C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {ABC31E74-02FF-46EB-B3B2-4E6AE43B456C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {ABC31E74-02FF-46EB-B3B2-4E6AE43B456C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {ABC31E74-02FF-46EB-B3B2-4E6AE43B456C}.Release|Any CPU.Build.0 = Release|Any CPU
+ {1C1A049E-235C-4CD0-B6FA-D53AC418F4DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {1C1A049E-235C-4CD0-B6FA-D53AC418F4DA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1C1A049E-235C-4CD0-B6FA-D53AC418F4DA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {1C1A049E-235C-4CD0-B6FA-D53AC418F4DA}.Release|Any CPU.Build.0 = Release|Any CPU
+ {EBD9022F-BC83-4846-9A11-6F7F3772DC64}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {EBD9022F-BC83-4846-9A11-6F7F3772DC64}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {EBD9022F-BC83-4846-9A11-6F7F3772DC64}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {EBD9022F-BC83-4846-9A11-6F7F3772DC64}.Release|Any CPU.Build.0 = Release|Any CPU
+ {7AD1DAC8-7FBE-49D5-8614-7321233DB82E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {7AD1DAC8-7FBE-49D5-8614-7321233DB82E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {7AD1DAC8-7FBE-49D5-8614-7321233DB82E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {7AD1DAC8-7FBE-49D5-8614-7321233DB82E}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {83CB65B8-011F-4ED7-BCD3-A6CFA935EF7E}
+ EndGlobalSection
+EndGlobal
diff --git a/Frank.PulseFlow.Tests.Cli/Program.cs b/Frank.PulseFlow.Tests.Cli/Program.cs
index cbb6caa..8c26639 100644
--- a/Frank.PulseFlow.Tests.Cli/Program.cs
+++ b/Frank.PulseFlow.Tests.Cli/Program.cs
@@ -1,6 +1,4 @@
-// See https://aka.ms/new-console-template for more information
-
-using Frank.PulseFlow;
+using Frank.PulseFlow;
using Frank.PulseFlow.Tests.Cli;
IHostBuilder builder = Host.CreateDefaultBuilder();
@@ -9,15 +7,11 @@
{
services.AddPulseFlow(messagingBuilder =>
{
- messagingBuilder.AddFlow();
+ messagingBuilder.AddFlow();
});
services.AddHostedService();
});
IHost app = builder.Build();
-
-await app.RunAsync();
-
-
-//Extension Method
\ No newline at end of file
+await app.RunAsync();
\ No newline at end of file
diff --git a/Frank.PulseFlow.Tests.Cli/TestingService.cs b/Frank.PulseFlow.Tests.Cli/TestingService.cs
index 136343b..6dd79b7 100644
--- a/Frank.PulseFlow.Tests.Cli/TestingService.cs
+++ b/Frank.PulseFlow.Tests.Cli/TestingService.cs
@@ -4,10 +4,7 @@ public class TestingService : BackgroundService
{
private readonly IConduit _messenger;
- public TestingService(IConduit messenger)
- {
- _messenger = messenger;
- }
+ public TestingService(IConduit messenger) => _messenger = messenger;
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
diff --git a/Frank.PulseFlow.Tests.Cli/TextPulseFlow.cs b/Frank.PulseFlow.Tests.Cli/TextFlow.cs
similarity index 68%
rename from Frank.PulseFlow.Tests.Cli/TextPulseFlow.cs
rename to Frank.PulseFlow.Tests.Cli/TextFlow.cs
index a0c8f5f..3737858 100644
--- a/Frank.PulseFlow.Tests.Cli/TextPulseFlow.cs
+++ b/Frank.PulseFlow.Tests.Cli/TextFlow.cs
@@ -1,13 +1,10 @@
namespace Frank.PulseFlow.Tests.Cli;
-public class TextPulseFlow : IFlow
+public class TextFlow : IFlow
{
- private readonly ILogger _logger;
+ private readonly ILogger _logger;
- public TextPulseFlow(ILogger logger)
- {
- _logger = logger;
- }
+ public TextFlow(ILogger logger) => _logger = logger;
public async Task HandleAsync(IPulse message, CancellationToken cancellationToken)
{
diff --git a/Frank.PulseFlow.sln b/Frank.PulseFlow.sln
index c91ccc6..38cc877 100644
--- a/Frank.PulseFlow.sln
+++ b/Frank.PulseFlow.sln
@@ -22,6 +22,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
restore.ps1 = restore.ps1
test.ps1 = test.ps1
pack.ps1 = pack.ps1
+ CONTRIBUTING.md = CONTRIBUTING.md
+ icon.png = icon.png
+ README.md = README.md
+ .github\workflows\main.yml = .github\workflows\main.yml
+ MAINTAINERS.md = MAINTAINERS.md
+ STYLE.md = STYLE.md
EndProjectSection
EndProject
Global
diff --git a/Frank.PulseFlow/Frank.PulseFlow.csproj b/Frank.PulseFlow/Frank.PulseFlow.csproj
index bb88563..0fc69b8 100644
--- a/Frank.PulseFlow/Frank.PulseFlow.csproj
+++ b/Frank.PulseFlow/Frank.PulseFlow.csproj
@@ -7,12 +7,6 @@
PulseFlow uses Channel -mechanism for internal messaging
Pulse,Flow,PulseFlow,Frank,Frank Haugen,Messaging,In-Memory
-
- 2023-12-14:
- 1.0 Initial release of PulseFlow
- 1.1 Added support for .NET 7.0 and .NET 8.0
-
-
true
$(NoWarn);1591
@@ -23,7 +17,7 @@
Frank R. Haugen
Frank R. Haugen
Copyright (c) 2023 Frank R. Haugen
- readme.md
+ README.md
icon.png
true
MIT
@@ -39,8 +33,8 @@
-
-
+
+
diff --git a/Frank.PulseFlow/IFlowBuilder.cs b/Frank.PulseFlow/IFlowBuilder.cs
index 53cb316..10b766a 100644
--- a/Frank.PulseFlow/IFlowBuilder.cs
+++ b/Frank.PulseFlow/IFlowBuilder.cs
@@ -1,5 +1,8 @@
namespace Frank.PulseFlow;
+///
+/// Represents a pulse flow builder that is used to simplify the registration of flows.
+///
public interface IFlowBuilder
{
///
diff --git a/Frank.PulseFlow/Internal/Channel.cs b/Frank.PulseFlow/Internal/Channel.cs
index 6e878b5..4278e74 100644
--- a/Frank.PulseFlow/Internal/Channel.cs
+++ b/Frank.PulseFlow/Internal/Channel.cs
@@ -2,6 +2,9 @@
namespace Frank.PulseFlow.Internal;
+///
+/// A wrapper around a that sends and receives objects.
+///
internal class Channel : IChannel
{
private readonly Channel _channel = System.Threading.Channels.Channel.CreateUnbounded();
diff --git a/Frank.PulseFlow/Internal/Conduit.cs b/Frank.PulseFlow/Internal/Conduit.cs
index 005a23f..1ecce12 100644
--- a/Frank.PulseFlow/Internal/Conduit.cs
+++ b/Frank.PulseFlow/Internal/Conduit.cs
@@ -1,5 +1,8 @@
namespace Frank.PulseFlow.Internal;
+///
+/// A wrapper around a that sends and receives objects.
+///
internal class Conduit : IConduit
{
private readonly IChannel _messageChannel;
diff --git a/Frank.PulseFlow/FlowBuilder.cs b/Frank.PulseFlow/Internal/FlowBuilder.cs
similarity index 74%
rename from Frank.PulseFlow/FlowBuilder.cs
rename to Frank.PulseFlow/Internal/FlowBuilder.cs
index 0980fcc..6d2c56e 100644
--- a/Frank.PulseFlow/FlowBuilder.cs
+++ b/Frank.PulseFlow/Internal/FlowBuilder.cs
@@ -1,15 +1,12 @@
using Microsoft.Extensions.DependencyInjection;
-namespace Frank.PulseFlow;
+namespace Frank.PulseFlow.Internal;
-public class FlowBuilder : IFlowBuilder
+internal class FlowBuilder : IFlowBuilder
{
private readonly IServiceCollection _services;
- public FlowBuilder(IServiceCollection services)
- {
- _services = services;
- }
+ public FlowBuilder(IServiceCollection services) => _services = services;
///
/// Adds a flow of type T to the pulse flow builder.
diff --git a/Frank.PulseFlow/Internal/IChannel.cs b/Frank.PulseFlow/Internal/IChannel.cs
index c15b0b9..f7fb445 100644
--- a/Frank.PulseFlow/Internal/IChannel.cs
+++ b/Frank.PulseFlow/Internal/IChannel.cs
@@ -1,5 +1,8 @@
namespace Frank.PulseFlow.Internal;
+///
+/// Represents a channel for sending and receiving pulses.
+///
internal interface IChannel
{
Task SendAsync(IPulse message);
diff --git a/Frank.PulseFlow/README.md b/Frank.PulseFlow/README.md
deleted file mode 100644
index 4deef0b..0000000
--- a/Frank.PulseFlow/README.md
+++ /dev/null
@@ -1,125 +0,0 @@
-# PulseFlow Local Messaging
-
-PulseFlow Local Messaging is a lightweight, high-performance messaging system that enables seamless communication
-
-## Table of Contents
-
-- [Overview](#overview)
- - [Key Features](#key-features)
- - [Illustration](#illustration)
- - [Use Cases](#use-cases)
-- [Getting Started](#getting-started)
- - [Installation](#installation)
-- [Concepts](#concepts)
- - [Nexus](#nexus)
- - [Conduit](#conduit)
- - [Pulse](#pulse)
- - [PulseFlow](#pulseflow)
-
-## Overview
-
-PulseFlow Local Messaging is a lightweight, high-performance messaging system that enables seamless communication
-between different parts of an application. It's designed to be simple, flexible, and scalable, allowing for easy
-integration into any system architecture.
-
-### Key Features
-
-- **Lightweight**: PulseFlow is a lightweight messaging system, with a small footprint and minimal resource
- requirements.
-- **High Performance**: It's designed for high performance and scalability, capable of handling a vast volume of
- messages simultaneously.
-- **Asynchronous Communication**: PulseFlow supports asynchronous data flow, allowing for non-blocking and concurrent
- message transmissions.
-- **Flexible and Adaptable**: It's flexible and adaptable, capable of handling various types of messages and adapting
- its processing logic based on the nature and requirements of each message.
-- **Simple and Easy to Use**: PulseFlow is simple and easy to use, with a straightforward API and minimal configuration
- requirements.
-
-### Illustration
-
-```mermaid
-graph TD
- Pulse[Pulse: Data/Messages] -->|transmitted via| Conduit[Conduit: Message Pathway]
- Conduit -->|delivered to| Nexus[Nexus: Processing Service]
- Nexus -->|processed by| PulseFlow[PulseFlow: Message Handler]
- PulseFlow -->|manipulates| Pulse
-```
-
-In this Mermaid diagram:
-- **Pulse** is shown as the starting point for data/messages.
-- **Conduit** is represented as the pathway for transmitting messages.
-- **Nexus** is the central processing service.
-- **PulseFlow** is depicted as handling and manipulating the messages.
-
-When you include this in a GitHub Markdown file, GitHub will render the Mermaid diagram as a visual graph. Remember to remove the extra backticks (```) in the beginning and end when adding this to your README.
-
-### Use Cases
-
-PulseFlow is a general-purpose messaging system that can be used in a wide variety of applications. It's particularly
-useful in scenarios where there's a need for asynchronous communication between different parts of the system.
-
-## Getting Started
-
-This section provides a quick guide on how to get started with PulseFlow Local Messaging.
-
-### Installation
-
-PulseFlow is available as a NuGet package, which can be installed using the following command:
-
-```bash
-dotnet add package Frank.PulseFlow
-```
-
-## Concepts
-
-This section provides an in-depth explanation of the key concepts and components within the system: Nexus, Conduit,
-Pulse, and PulseFlow. Understanding these concepts is crucial for grasping how the system operates and interacts with
-data.
-
-### Nexus
-
-The **Nexus** is the central hub of our messaging system, analogous to a neural network's core. It serves as the primary
-processing service, where all data messages, or 'Pulses', are received, interpreted, and routed to their respective
-destinations.
-
-- **Role**: Nexus acts as the orchestrator within the system, managing the flow of messages and ensuring that each one
- is processed according to predefined rules and logic.
-- **Functionality**: It handles various tasks like message validation, transformation, and decision-making on how and
- where messages should be directed post-processing.
-- **Scalability and Performance**: Designed for high performance and scalability, Nexus can handle a vast volume of
- messages simultaneously, ensuring minimal latency and high throughput in data processing.
-
-### Conduit
-
-The **Conduit** represents the pathway through which messages, or 'Pulses', are transmitted within the system. It's the
-messenger that ensures the delivery of data from one point to another.
-
-- **Mechanism**: Conduit facilitates the smooth and efficient transport of messages across different parts of the
- system.
-- **Reliability and Integrity**: Ensuring data integrity, Conduit maintains the fidelity of the messages as they
- traverse through various processes.
-- **Asynchronous Communication**: It supports asynchronous data flow, allowing for non-blocking and concurrent message
- transmissions, which is key for a responsive and efficient system.
-
-### Pulse
-
-**Pulse** is the term used to describe the individual units of data or messages that flow through the system.
-
-- **Data Encapsulation**: Each Pulse is a packet of information, encapsulating the necessary data in a well-defined
- format.
-- **Types and Variability**: Pulses can vary in type and structure, ranging from simple text messages to complex data
- structures, each tailored to carry specific information relevant to its intended process.
-- **Lifecycle**: The lifecycle of a Pulse includes its creation, transmission through the Conduit, processing in the
- Nexus, and final delivery or action as dictated by the system's logic.
-
-### PulseFlow
-
-**PulseFlow** is the sophisticated mechanism responsible for handling and manipulating the Pulses as they move through
-the system.
-
-- **Message Handling**: It's specifically designed to process each Pulse, applying necessary transformations, routing,
- and any other required operations.
-- **Flexibility and Adaptability**: PulseFlow is adept at handling various types of Pulses, capable of adapting its
- processing logic based on the nature and requirements of each message.
-- **Integration Point**: Acting as a key integration point within the system, it ensures that Pulses are managed
- efficiently and effectively, readying them for their next phase in the data journey.
diff --git a/Frank.PulseFlow/ServiceCollectionExtensions.cs b/Frank.PulseFlow/ServiceCollectionExtensions.cs
index bcc6e66..dadf142 100644
--- a/Frank.PulseFlow/ServiceCollectionExtensions.cs
+++ b/Frank.PulseFlow/ServiceCollectionExtensions.cs
@@ -4,11 +4,23 @@
namespace Frank.PulseFlow;
+///
+/// Provides extension methods for the interface.
+///
public static class ServiceCollectionExtensions
{
///
/// Adds the PulseFlow to the service collection.
///
+ ///
+ ///
+ /// services.AddPulseFlow(builder =>
+ /// {
+ /// builder.AddFlow[Flow]();
+ /// builder.AddFlow[AnotherFlow]();
+ /// });
+ ///
+ ///
/// The service collection to which the PulseFlow components will be added.
/// An action delegate to configure the PulseFlow builder.
/// The updated service collection.
diff --git a/MAINTAINERS.md b/MAINTAINERS.md
new file mode 100644
index 0000000..69effdc
--- /dev/null
+++ b/MAINTAINERS.md
@@ -0,0 +1,7 @@
+# Maintainers
+
+The maintainers of this repository are:
+
+| Name | GitHub | Role |
+| ---- | ------ |-------------|
+| Frank R. Haugen | [frankhaugen](https://github.com/frankhaugen) | Maintainer/Owner |
diff --git a/README.md b/README.md
index e43e652..f36f51f 100644
--- a/README.md
+++ b/README.md
@@ -1,17 +1,260 @@
-# Frank.PulseFlow
+# PulseFlow (Local Messaging)
-Frank.PulseFlow is an innovative C# library that wraps the Channel type, enhancing its DI friendliness and intuitive use in data-vent-driven architectures. It provides a streamlined approach for efficient message handling in various applications.
+PulseFlow Local Messaging is a lightweight, high-performance messaging system that enables seamless communication, and thread-safe data transfer between different parts of an application. It's designed to be simple, flexible, and scalable, allowing for easy integration into any system architecture.
-## Key Features
-- **Pulse**: Represents messages in the system.
-- **Conduit (IConduit)**: Acts as a message transmitter.
-- **PulseFlow (IPulseFlow)**: Serves as a message handler.
-- **Nexus**: A BackgroundService that processes all Pulses and routes them to the appropriate IPulseFlow handlers.
+___
+[![GitHub License](https://img.shields.io/github/license/frankhaugen/Frank.PulseFlow)](LICENSE)
+[![NuGet](https://img.shields.io/nuget/v/Frank.PulseFlow.svg)](https://www.nuget.org/packages/Frank.PulseFlow)
+[![NuGet](https://img.shields.io/nuget/dt/Frank.PulseFlow.svg)](https://www.nuget.org/packages/Frank.PulseFlow)
+
+![GitHub contributors](https://img.shields.io/github/contributors/frankhaugen/Frank.PulseFlow)
+![GitHub Release Date - Published_At](https://img.shields.io/github/release-date/frankhaugen/Frank.PulseFlow)
+![GitHub last commit](https://img.shields.io/github/last-commit/frankhaugen/Frank.PulseFlow)
+![GitHub commit activity](https://img.shields.io/github/commit-activity/m/frankhaugen/Frank.PulseFlow)
+![GitHub pull requests](https://img.shields.io/github/issues-pr/frankhaugen/Frank.PulseFlow)
+![GitHub issues](https://img.shields.io/github/issues/frankhaugen/Frank.PulseFlow)
+![GitHub closed issues](https://img.shields.io/github/issues-closed/frankhaugen/Frank.PulseFlow)
+___
+
+## Table of Contents
+
+- [Overview](#overview)
+ - [Key Features](#key-features)
+ - [Illustration](#illustration)
+ - [Use Cases](#use-cases)
+- [Getting Started](#getting-started)
+ - [Installation](#installation)
+- [Concepts](#concepts)
+ - [Nexus](#nexus)
+ - [Conduit](#conduit)
+ - [Pulse](#pulse)
+ - [Flow](#flow)
+___
+
+## Acknowledgements
+
+This is a very thin abstraction layer on top of [System.Threading.Channels](https://www.nuget.org/packages/System.Threading.Channels), which is a NuGet package that gets shipped along with every release of .NET.
+The reason for this abstraction layer is to make it easier to use `System.Threading.Channels` in a Dependency Injection scenario, and to make it easier to use `System.Threading.Channels` in a thread-safe manner.
+Thanks to the .NET team for making `System.Threading.Channels`, and in particular [Stephen Toub](https://github.com/stephentoub) for his [blog post](https://devblogs.microsoft.com/dotnet/an-introduction-to-system-threading-channels/) on `System.Threading.Channels`, and as part of the rest of the team.
+
+## Overview
+
+PulseFlow Local Messaging is a lightweight, high-performance messaging system that enables seamless communication
+between different parts of an application. It's designed to be simple, flexible, and scalable, allowing for easy
+integration into any system architecture.
+
+### Key Features
+
+- **Lightweight**: PulseFlow is a lightweight messaging system, with a small footprint and minimal resource
+ requirements.
+- **High Performance**: It's designed for high performance and scalability, capable of handling a vast volume of
+ messages simultaneously.
+- **Asynchronous Communication**: PulseFlow supports asynchronous data flow, allowing for non-blocking and concurrent
+ message transmissions.
+- **Flexible and Adaptable**: It's flexible and adaptable, capable of handling various types of messages and adapting
+ its processing logic based on the nature and requirements of each message.
+- **Simple and Easy to Use**: PulseFlow is simple and easy to use, with a straightforward API and minimal configuration
+ requirements. This is assuming Dependency Injection is used. If not, then it's a bit more complicated, and not supported at this time.
+- **Thread-Safe**: It's thread-safe, ensuring that messages are processed in a safe and reliable manner.
+- **Open Source**: PulseFlow is open-source, with the source code available on GitHub.
+- **Cross-Platform**: It's cross-platform, supporting multiple operating systems and platforms.
+- **Supports multiple consumers**: PulseFlow supports multiple consumers, thereby allowing for parallel processing of
+ messages. This is particularly useful in scenarios where there's a need to save messages to some form of audit trail or log.
+
+### Illustration
+
+```mermaid
+graph TB
+ subgraph "Transmission"
+ EmailPulse[Email : IPulse] -->|transmitted via| Conduit[IConduit]
+ FtpPulse[FTP : IPulse] -->|transmitted via| Conduit[IConduit]
+ ApiPulse[API : IPulse] -->|transmitted via| Conduit[IConduit]
+ end
+ subgraph "Delivery"
+ Conduit -->|delivered to| IChannel[IChannel]
+ end
+ subgraph "Consumption and Routing"
+ IChannel -->|consumed and routed by| Nexus[Nexus]
+ Nexus -->|typeof==Email| EmailFlow[EmailFlow : IFlow]
+ Nexus -->|typeof==API| Flow[FtpAndApiFlow : IFlow]
+ Nexus -->|typeof==FTP| Flow[FtpAndApiFlow : IFlow]
+ Nexus -->|typeof==?| AuditFlow[AuditFlow : IFlow]
+ AuditFlow -->|audit trail by| ILogger[ILogger]
+ end
+```
+
+In this Mermaid diagram:
+- **IPulse** is the interface for the Pulse.
+- **IConduit** is the interface for the Conduit, which is the pathway through which messages are transmitted.
+- **IChannel** is the interface for the Channel, which is a wrapper around the `System.Threading.Channels.Channel` class, which is a thread-safe data structure for passing data between producers and consumers located in different threads.
+- **Nexus** is the central processing service, which handles the pulse messages.
+- **IFlow** is the interface for the a flow, which is the mechanism that handles/consumes the pulse messages.
+- **ILogger** is the interface for the generic logger in dotnet.
+
+When you include this in a GitHub Markdown file, GitHub will render the Mermaid diagram as a visual graph. Remember to remove the extra backticks (```) in the beginning and end when adding this to your README.
+
+### Use Cases
+
+PulseFlow is a general-purpose messaging system that can be used in a wide variety of applications. It's particularly
+useful in scenarios where there's a need for asynchronous communication between different parts of the system.
+
+Another use case is when you need multiple threads to do some non-multiple-thread-safe work, like saving to a log-file. Example: You have a web API and you want to save a all requests' route, method and user to a log-file. You can use PulseFlow to do this in a thread-safe manner, because PulseFlow's `IConduit` and `IChannel` are thread-safe. You can have multiple threads saving to the same log-file, and PulseFlow will ensure that the log-file is not written to by multiple threads at the same time, and that the writing happens in the order the messages are received.
+
+#### Example
+
+```mermaid
+graph TB
+ subgraph Transmission
+ ApiPulse1[ApiMessage : IPulse] -->|transmitted via| Conduit[IConduit]
+ ApiPulse2[ApiMessage : IPulse] -->|transmitted via| Conduit[IConduit]
+ ApiPulse3[ApiMessage : IPulse] -->|transmitted via| Conduit[IConduit]
+ ApiPulse4[ApiMessage : IPulse] -->|transmitted via| Conduit[IConduit]
+ ApiPulse5[ApiMessage : IPulse] -->|transmitted via| Conduit[IConduit]
+ ApiPulse6[ApiMessage : IPulse] -->|transmitted via| Conduit[IConduit]
+ end
+ subgraph Delivery
+ Conduit -->|delivered to| IChannel[IChannel]
+ end
+ subgraph Consumption and Routing
+ IChannel -->|consumed and routed by| Nexus[Nexus]
+ Nexus -->|typeof==API| Flow[FileLoggerFlow : IFlow]
+ end
+```
## Getting Started
-To integrate Frank.PulseFlow, add it as a NuGet package and use `.AddPulseFlow()` on `IServiceCollection`.
-## Usage
-Implement the `IPulseFlow` interface in your classes and register these implementations with the `AddPulseFlow` method in your service collection.
+This section provides a quick guide on how to get started with PulseFlow Local Messaging.
+
+### Installation
+
+PulseFlow is available as a NuGet package, which can be installed using the following command:
+
+```bash
+dotnet add package Frank.PulseFlow
+```
+
+Once installed, you can start using PulseFlow by adding the following using statement to your code:
+
+```csharp
+using Frank.PulseFlow;
+```
+
+### Basic Usage
+
+The following code snippet shows a basic example of how to use PulseFlow:
+
+```csharp
+IHostBuilder builder = Host.CreateDefaultBuilder();
+
+builder.ConfigureServices((context, services) =>
+{
+ services.AddPulseFlow(messagingBuilder =>
+ {
+ messagingBuilder.AddFlow();
+ });
+ services.AddHostedService();
+});
+
+IHost app = builder.Build();
+
+await app.RunAsync();
+
+public class TextFlow : IFlow
+{
+ private readonly ILogger _logger;
+
+ public TextFlow(ILogger logger) => _logger = logger;
+
+ public async Task HandleAsync(IPulse message, CancellationToken cancellationToken)
+ {
+ if (message is TextPulse textMessage)
+ _logger.LogInformation("Received text message: {Text}", textMessage.Text);
+ await Task.CompletedTask;
+ }
+
+ public bool CanHandle(Type pulseType) => pulseType == typeof(TextPulse);
+}
+
+public class TestingService : BackgroundService
+{
+ private readonly IConduit _messenger;
+
+ public TestingService(IConduit messenger) => _messenger = messenger;
+
+ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
+ {
+ await Task.Delay(2000, stoppingToken);
+ while (!stoppingToken.IsCancellationRequested)
+ {
+ await _messenger.SendAsync(new TextPulse { Id = Guid.NewGuid(), Text = "Hello World" });
+ await Task.Delay(1000, stoppingToken);
+ }
+ }
+}
+public class TextPulse : BasePulse
+{
+ public string Text { get; set; }
+}
+```
+
+## Concepts
+
+This section provides an in-depth explanation of the key concepts and components within the system: Nexus, Conduit,
+Pulse, and PulseFlow. Understanding these concepts is crucial for grasping how the system operates and interacts with
+data.
+
+### Nexus
+
+The **Nexus** is the central hub of our messaging system, analogous to a neural network's core. It serves as the primary
+processing service, where all data messages, or 'Pulses', are received, interpreted, and routed to their respective
+destinations.
+
+- **Role**: Nexus acts as the orchestrator within the system, managing the flow of messages and ensuring that each one
+ is processed according to predefined rules and logic.
+- **Functionality**: It handles various tasks like message validation, transformation, and decision-making on how and
+ where messages should be directed post-processing.
+- **Scalability and Performance**: Designed for high performance and scalability, Nexus can handle a vast volume of
+ messages simultaneously, ensuring minimal latency and high throughput in data processing.
+
+### Conduit
+
+The **Conduit** represents the pathway through which messages, or 'Pulses', are transmitted within the system. It's the
+messenger that ensures the delivery of data from one point to another.
+
+- **Mechanism**: Conduit facilitates the smooth and efficient transport of messages across different parts of the
+ system.
+- **Reliability and Integrity**: Ensuring data integrity, Conduit maintains the fidelity of the messages as they
+ traverse through various processes.
+- **Asynchronous Communication**: It supports asynchronous data flow, allowing for non-blocking and concurrent message
+ transmissions, which is key for a responsive and efficient system.
+
+### Pulse
+
+**Pulse** is the term used to describe the individual units of data or messages that flow through the system.
+
+- **Data Encapsulation**: Each Pulse is a packet of information, encapsulating the necessary data in a well-defined
+ format.
+- **Types and Variability**: Pulses can vary in type and structure, ranging from simple text messages to complex data
+ structures, each tailored to carry specific information relevant to its intended process.
+- **Lifecycle**: The lifecycle of a Pulse includes its creation, transmission through the Conduit, processing in the
+ Nexus, and final delivery or action as dictated by the system's logic.
+
+### Flow
+
+**Flow** is the sophisticated mechanism responsible for handling and manipulating the Pulses as they move through
+the system.
+
+- **Message Handling**: It's specifically designed to process each Pulse, applying necessary transformations, routing,
+ and any other required operations.
+- **Flexibility and Adaptability**: PulseFlow is adept at handling various types of Pulses, capable of adapting its
+ processing logic based on the nature and requirements of each message.
+- **Integration Point**: Acting as a key integration point within the system, it ensures that Pulses are managed
+ efficiently and effectively, readying them for their next phase in the data journey.
+
+## License
+
+This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
+
+## Contributing
-Frank.PulseFlow simplifies message handling, making your .NET applications more efficient and modular.
+Contributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for more details.
\ No newline at end of file
diff --git a/STYLE.md b/STYLE.md
new file mode 100644
index 0000000..3902824
--- /dev/null
+++ b/STYLE.md
@@ -0,0 +1,114 @@
+# Style Guide
+
+## Introduction
+
+This document describes the coding style used in this repository. It is based on SOLID principles, and should emphasize Dependency Injections, and the Single Responsibility Principle.
+
+## Table of Contents
+
+## Naming Conventions
+
+| Token | Convention | Grammar Terms | Example |
+|----------------|-------------|-----------------|-------------------|
+| Namespace | PascalCase | Noun | `Frank.PulseFlow` |
+| Class | PascalCase | Noun | `PulseFlow` |
+| Interface | IPascalCase | Noun | `IPulseFlow` |
+| Enum | PascalCase | Noun | `PulseFlowState` |
+| Enum Value | PascalCase | Noun, Adjective | `Running` |
+| Method | PascalCase | Verb | `Start` |
+| Property | PascalCase | Noun | `State` |
+| Field | _camelCase | Noun | `_state` |
+| Parameter | camelCase | Noun | `state` |
+| Local Variable | camelCase | Noun | `state` |
+| Constant | PascalCase | Noun | `Running` |
+| Event | PascalCase | Noun | `Started` |
+| Delegate | PascalCase | Noun | `Started` |
+| Type Parameter | PascalCase | Noun | `TKey` |
+| Type Argument | PascalCase | Noun | `string` |
+
+## General Guidelines
+
+### Use `var` when possible
+
+Use `var` when the type of the variable is obvious from the right-hand side of the assignment, (e.g. `var x = 1;` is fine, but `var x = new Foo();` is not).
+
+### Use `nameof` when possible
+
+Use `nameof` when the name of the variable is needed, (e.g. `nameof(foo)` instead of `"foo"`).
+
+### Use `const` when possible
+
+Use `const` when the value of the variable is known at compile time, (e.g. `const int x = 1;` is fine, but `const int x = Foo();` is not).
+
+### Use `readonly` when possible
+
+Use `readonly` when the value of the variable is known at compile time, and the variable is not a constant, (e.g. `readonly int x = 1;` is fine, but `readonly int x = Foo();` is not).
+
+### Use `static` when possible
+
+Use `static` when the value of the variable is known at compile time, and the variable is not a constant, (e.g. `static int x = 1;` is fine, but `static int x = Foo();` is not).
+
+### Use Expression-Bodied Members when possible
+
+Use Expression-Bodied Members when the body of the member is a single expression, (e.g. `public int Foo() => 1;` is fine, but `public int Foo() { return 1; }` is not).
+
+## Class Guidelines
+
+### Use `sealed` when possible
+
+Use `sealed` when the class is not intended to be inherited from, (e.g. `sealed class Foo { }` is fine, but `class Foo { }` is not).
+
+### Use `static` when possible
+
+Use `static` when the class is not intended to be instantiated, (e.g. `static class Foo { }` is fine, but `class Foo { }` is not).
+
+## Helper Class Guidelines
+
+### Use `static` always
+
+All helper classes should be `static`, (e.g. `static class Foo { }` is fine, but `class Foo { }` is not).
+
+### Helpers should be `internal` or `private` unless they are intended to be used outside of the assembly
+
+All helper classes should be `internal` or `private` unless they are intended to be used outside of the assembly, (e.g. `internal static class Foo { }` is fine, but `public static class Foo { }` is not).
+
+When a helper class is intended to be used outside of the assembly, it should be `public`, (e.g. `public static class Foo { }` is fine, but `internal static class Foo { }` is not). This is rare, and should be avoided if possible, but something like a DateTime helper class that expose Week based operations might be useful to other assemblies.
+
+## Interface Guidelines
+
+### Use `I` prefix always
+
+All interfaces should be prefixed with `I`, (e.g. `IPulseFlow` is fine, but `PulseFlow` is not).
+
+### Use `internal` or `public` always
+
+All interfaces should be `internal` or `public`, (e.g. `internal interface IPulseFlow { }` is fine, but `private interface IPulseFlow { }` is not).
+
+## Enum Guidelines
+
+### Use `PascalCase` always
+
+All enums should be `PascalCase`, (e.g. `enum PulseFlowState { Running, Stopped }` is fine, but `enum PulseFlowState { running, stopped }` is not).
+
+### Don't suffix with `Enum`, 'Type', or `Flag`
+
+Don't suffix with `Enum`, 'Type', or `Flag`, (e.g. `enum PulseFlowState { Running, Stopped }` is fine, but `enum PulseFlowStateEnum { Running, Stopped }` is not).
+
+### Don't use `Flags` unless the enum is intended to be used as a set of flags
+
+Don't use `Flags` unless the enum is intended to be used as a set of flags, (e.g. `enum PulseFlowState { Running, Stopped }` is fine, but `enum PulseFlowState { Running = 1, Stopped = 2 }` is not).
+
+### Use `internal` or `public` always
+
+All enums should be `internal` or `public`, (e.g. `internal enum PulseFlowState { Running, Stopped }` is fine, but `private enum PulseFlowState { Running, Stopped }` is not).
+
+## Enum Value Guidelines
+
+### Use `PascalCase` always
+
+All enum values should be `PascalCase`, (e.g. `enum PulseFlowState { Running, Stopped }` is fine, but `enum PulseFlowState { running, stopped }` is not).
+
+
+
+
+
diff --git a/Frank.PulseFlow/icon.png b/icon.png
similarity index 100%
rename from Frank.PulseFlow/icon.png
rename to icon.png