Myth.Commons
4.3.0
dotnet add package Myth.Commons --version 4.3.0
NuGet\Install-Package Myth.Commons -Version 4.3.0
<PackageReference Include="Myth.Commons" Version="4.3.0" />
<PackageVersion Include="Myth.Commons" Version="4.3.0" />
<PackageReference Include="Myth.Commons" />
paket add Myth.Commons --version 4.3.0
#r "nuget: Myth.Commons, 4.3.0"
#:package Myth.Commons@4.3.0
#addin nuget:?package=Myth.Commons&version=4.3.0
#tool nuget:?package=Myth.Commons&version=4.3.0
Myth.Commons
Foundation library for the Myth ecosystem providing essential utilities, value objects, global service provider management, and JSON extensions.
๐ฏ Why Myth.Commons?
Every enterprise .NET application faces the same fundamental challenges: managing cross-cutting concerns, implementing clean domain models, orchestrating dependency injection across libraries, and handling serialization consistently. Myth.Commons solves these problems once and for all, providing battle-tested patterns that eliminate boilerplate and accelerate development.
The Problem
Building enterprise applications requires:
- Cross-library integration without tight coupling or service locator anti-patterns
- Domain-Driven Design primitives (Value Objects, type-safe constants) without reinventing the wheel
- Consistent JSON handling across HTTP APIs, message queues, and data storage
- Scoped service management for transient handlers accessing EF Core DbContext
- Pagination implemented correctly with query binding and type safety
Most teams either build these from scratch (wasting weeks) or use fragmented libraries that don't integrate well together.
The Solution
Myth.Commons provides production-ready building blocks that work seamlessly together:
โ Global Service Provider - Thread-safe centralized DI resolution enabling Myth libraries to work together without coupling โ IScopedService Pattern - Execute operations in managed scopes, perfect for CQRS handlers with EF Core โ Value Objects & Constants - DDD primitives with structural equality and type safety โ JSON Extensions - Fluent API with global configuration, custom converters, and consistent error handling โ String & Collection Utilities - Common operations without external dependencies
Why Choose Myth.Commons?
| Aspect | Myth.Commons | DIY Approach | Other Libraries |
|---|---|---|---|
| Integration | Designed for Myth ecosystem | Manual wiring | Fragmented |
| DDD Support | Native Value Objects & Constants | Build from scratch | Limited or missing |
| Service Scopes | IScopedService pattern | Manual scope management | Not addressed |
| Global DI | Thread-safe MythServiceProvider | Service locator anti-pattern | Not provided |
| JSON | Fluent, global config, converters | System.Text.Json verbosity | Newtonsoft.Json dependency |
| Learning Curve | Intuitive, documented | High (design patterns) | Medium |
| Production Ready | Battle-tested | Untested | Varies |
Real-World Applications
E-Commerce Platform
Use Value Objects for Money, Address, ProductSku. Type-safe OrderStatus constants. IScopedService for CQRS handlers accessing order repositories with EF Core.
Financial Services
Immutable Value Objects for AccountNumber, TransactionAmount. Global JSON configuration for consistent API responses. Pagination for transaction history.
SaaS Multi-Tenant Systems
Global Service Provider enables tenant-scoped services. IScopedService ensures DbContext per request. Type-safe SubscriptionTier constants.
Microservices Architecture Shared JSON serialization settings across services. Value Objects for domain events. Global DI for cross-cutting concerns like logging and telemetry.
Key Differentiators
๐๏ธ Architecture-First Design Built for Clean Architecture and DDD from day one. Not an afterthought.
๐ Seamless Integration All Myth libraries use MythServiceProvider for cross-library dependency resolution without coupling.
โก Developer Experience Fluent APIs, sensible defaults, comprehensive documentation. Get started in minutes.
๐งช Testability Every pattern designed for easy mocking and unit testing. Reset global state for test isolation.
๐ฏ Type Safety Eliminate primitive obsession with Value Objects and type-safe Constants. Compile-time checks prevent runtime errors.
๐ฆ Zero Lock-In Use only what you need. Each feature works independently or together.
Conceptual Foundations
Domain-Driven Design (DDD) Value Objects provide structural equality for domain concepts. Constants eliminate magic strings/numbers while adding domain richness.
Dependency Injection Global Service Provider enables cross-library integration following Martin Fowler's "Inversion of Control" pattern without service locator anti-pattern.
CQRS (Command Query Responsibility Segregation) IScopedService pattern solves the "transient handler with scoped DbContext" problem elegantly.
Clean Architecture Infrastructure-independent JSON serialization. Domain models in core, technical details in outer layers.
Fluent Interface Pattern
JSON settings use method chaining for readable configuration: .Minify().IgnoreNull().UseCaseStrategy(CaseStrategy.SnakeCase)
Features
- Global Service Provider Management - Thread-safe centralized service provider for cross-library integration
- IScopedService Pattern - Execute operations within managed service scopes
- Value Objects - Base classes for implementing DDD value objects and type-safe constants
- JSON Extensions - Fluent JSON serialization/deserialization with global configuration
- String Utilities - Comprehensive string manipulation extensions
- Pagination Support - Built-in pagination value object
Installation
dotnet add package Myth.Commons
Global Service Provider
MythServiceProvider
Thread-safe static class for managing a global service provider instance.
Properties
IServiceProvider? Current { get; } // Current global provider or null
bool IsInitialized { get; } // Check if initialized
Methods
// First-wins initialization (subsequent calls ignored)
bool TryInitialize(IServiceProvider serviceProvider)
// Force initialization (overwrites existing - use with caution)
void Initialize(IServiceProvider serviceProvider)
// Get required (throws if not initialized)
IServiceProvider GetRequired()
// Get with fallback
IServiceProvider GetOrFallback(IServiceProvider? fallbackServiceProvider)
// Reset for testing
void Reset()
Example
// ASP.NET Core - automatic initialization
var app = builder.BuildApp(); // Initializes MythServiceProvider.Current
// Console App - manual initialization
var serviceProvider = services.BuildServiceProvider();
MythServiceProvider.Initialize(serviceProvider);
// Access global provider
var provider = MythServiceProvider.Current;
var service = provider?.GetService<IMyService>();
// Or require it (throws if not initialized)
var required = MythServiceProvider.GetRequired();
IScopedService<T>
Interface for executing operations within managed service scopes. Essential for transient services that need scoped dependencies.
Methods
// Synchronous with result
TResult Execute<TResult>(Func<T, TResult> operation)
// Asynchronous with result
Task<TResult> ExecuteAsync<TResult>(Func<T, Task<TResult>> operation)
// Synchronous void
void Execute(Action<T> operation)
// Asynchronous void
Task ExecuteAsync(Func<T, Task> operation)
Registration
services.AddScopedServiceProvider();
// Or automatic with BuildApp()
var app = builder.BuildApp(); // Auto-registers IScopedService<T>
Example
public class OrderHandler : ICommandHandler<CreateOrderCommand> {
private readonly IScopedService<IOrderRepository> _repository;
public OrderHandler(IScopedService<IOrderRepository> repository) {
_repository = repository;
}
public async Task<CommandResult> HandleAsync(CreateOrderCommand command, CancellationToken ct) {
// Executes within a managed scope
return await _repository.ExecuteAsync(async repo => {
var order = await repo.CreateAsync(command.Data, ct);
return CommandResult.Success();
});
}
}
ServiceCollection Extensions
// ASP.NET Core - replaces builder.Build()
WebApplication BuildApp(this WebApplicationBuilder builder)
// Get global provider
IServiceProvider? GetGlobalProvider()
// Register IScopedService<T> pattern
IServiceCollection AddScopedServiceProvider(this IServiceCollection services)
Value Objects
ValueObject
Abstract base class for implementing DDD value objects with value-based equality.
public class Address : ValueObject {
public string Street { get; }
public string City { get; }
public string Country { get; }
public Address(string street, string city, string country) {
Street = street;
City = city;
Country = country;
}
protected override IEnumerable<object> GetAtomicValues() {
yield return Street;
yield return City;
yield return Country;
}
}
// Usage
var addr1 = new Address("123 Main St", "New York", "USA");
var addr2 = new Address("123 Main St", "New York", "USA");
Console.WriteLine(addr1.Equals(addr2)); // True (value equality)
Console.WriteLine(addr1 == addr2); // True
var cloned = addr1.Clone(); // Shallow clone
Constant<TSelf, TValue>
Abstract base class for creating type-safe, enumeration-like constants with rich metadata.
Type Constraints:
TSelf : Constant<TSelf, TValue>TValue : IEquatable<TValue>, IComparable<TValue>
Properties
string Name { get; } // Constant name
TValue Value { get; } // Constant value
Static Methods
IReadOnlyList<TSelf> GetAll() // All instances
TSelf FromValue(TValue value) // Find by value (throws if not found)
TSelf FromName(string name) // Find by name (case insensitive, throws if not found)
bool TryFromValue(TValue value, out TSelf? result) // Try find by value
bool TryFromName(string name, out TSelf? result) // Try find by name
string GetOptions() // Formatted string of all options
IEnumerable<TSelf> All { get; } // Enumerable of all instances
Nested Class
static class Values {
static IEnumerable<TValue> All { get; } // All values only
}
Protected Methods
// Constructor
protected Constant(string name, TValue value)
// Automatic name from caller member
protected static TSelf CreateWithCallerName(TValue value, [CallerMemberName] string memberName = "")
Operators
implicit operator TValue(Constant<TSelf, TValue> constant) // Implicit conversion to value
== != < > <= >= // Comparison operators
Example
public class OrderStatus : Constant<OrderStatus, string> {
public static readonly OrderStatus Pending = CreateWithCallerName("P");
public static readonly OrderStatus Processing = CreateWithCallerName("PR");
public static readonly OrderStatus Completed = CreateWithCallerName("C");
public static readonly OrderStatus Cancelled = CreateWithCallerName("X");
private OrderStatus(string name, string value) : base(name, value) { }
}
// Usage
var status = OrderStatus.FromValue("P"); // Returns Pending
var all = OrderStatus.GetAll(); // All 4 statuses
var allValues = OrderStatus.Values.All; // ["P", "PR", "C", "X"]
string options = OrderStatus.GetOptions(); // "P: Pending | PR: Processing | C: Completed | X: Cancelled"
if (OrderStatus.TryFromName("pending", out var result)) {
Console.WriteLine(result.Value); // "P"
}
// Implicit conversion
string value = OrderStatus.Pending; // "P"
// Comparison
var isLess = OrderStatus.Pending < OrderStatus.Completed;
Pagination
Value object for pagination parameters with ASP.NET Core query binding support.
public class Pagination : ValueObject {
[FromQuery(Name = "$pagenumber")]
public int PageNumber { get; set; }
[FromQuery(Name = "$pagesize")]
public int PageSize { get; set; }
// Constructors
public Pagination(int pageNumber, int pageSize)
public Pagination() // Defaults: pageNumber=1, pageSize=10
// Static defaults
static readonly Pagination Default // pageNumber=1, pageSize=10
static readonly Pagination All // pageNumber=-1, pageSize=-1
}
// Usage in controller
[HttpGet]
public async Task<IActionResult> Get([FromQuery] Pagination pagination) {
// pagination.PageNumber from query string: ?$pagenumber=2
// pagination.PageSize from query string: ?$pagesize=20
}
Paginated<TEntity>
Class for paginated results.
public class Paginated<TEntity> : IPaginated<TEntity> {
public int PageNumber { get; }
public int PageSize { get; }
public int TotalItems { get; }
public int TotalPages { get; }
public IEnumerable<TEntity> Items { get; }
public Paginated(
int pageNumber,
int pageSize,
int totalItems,
int totalPages,
IEnumerable<TEntity> items)
}
JSON Extensions
Fluent JSON serialization/deserialization with global configuration support.
Global Configuration
JsonExtensions.Configure(settings => {
settings.CaseStrategy = CaseStrategy.SnakeCase;
settings.IgnoreNullValues = true;
settings.MinifyResult = true;
});
Methods
// Validation
bool IsValidJson(this string content)
// Serialization
string ToJson(this object content, Action<JsonSettings>? settings = null)
// Deserialization
TResponse? FromJson<TResponse>(this string content, Action<JsonSettings>? settings = null)
object? FromJson(this string content, Type responseType, Action<JsonSettings>? settings = null)
// Safe deserialization (returns default if invalid)
T? SafeFromJson<T>(this string content, Action<JsonSettings>? settings = null)
// Deserialize or throw with HTTP context
T FromJsonOrThrow<T>(
this string content,
HttpStatusCode statusCode,
string? contentType = null,
Action<JsonSettings>? settings = null)
JsonSettings
public class JsonSettings {
bool MinifyResult { get; set; } // Default: false
bool IgnoreNullValues { get; set; } // Default: false
CaseStrategy CaseStrategy { get; set; } // Default: CamelCase
IList<JsonConverter> Converters { get; set; }
Action<JsonSerializerOptions>? OtherSettings { get; set; }
// Fluent methods
JsonSettings IgnoreNull()
JsonSettings Minify()
JsonSettings UseCaseStrategy(CaseStrategy strategy)
JsonSettings UseInterfaceConverter<TInterface, TConcrete>() where TConcrete : TInterface
JsonSettings UseInterfaceConverter(Type interfaceType, Type concreteType)
JsonSettings UseCustomConverter(JsonConverter converter)
JsonSettings Copy()
}
CaseStrategy Enum
public enum CaseStrategy {
CamelCase, // myAwesomeProperty
SnakeCase // my_awesome_property
}
Examples
// Basic serialization
var user = new User { Name = "John", Email = "john@example.com" };
var json = user.ToJson();
// With settings
var minified = user.ToJson(s => s.Minify().IgnoreNull());
// Deserialization
var user = json.FromJson<User>();
// Safe deserialization
var user = json.SafeFromJson<User>(); // Returns null if invalid
// Validation
if (content.IsValidJson()) {
var data = content.FromJson<Data>();
}
// With HTTP context
try {
var user = json.FromJsonOrThrow<User>(HttpStatusCode.BadRequest);
} catch (InvalidJsonResponseException ex) {
Console.WriteLine($"Status: {ex.StatusCode}, Content: {ex.RawContent}");
}
// Global configuration
JsonExtensions.Configure(settings => {
settings.CaseStrategy = CaseStrategy.SnakeCase;
settings.IgnoreNullValues = true;
settings.UseInterfaceConverter<IUser, User>();
});
// Now all ToJson/FromJson calls use these settings
var json = user.ToJson(); // Uses snake_case and ignores nulls
String Extensions
// Remove text
string Remove(this string value, string text)
// Minify (remove all whitespace)
string Minify(this string text)
// Case transformations
string ToFirstLower(this string text)
string ToFirstUpper(this string text)
// Substring operations
string GetStringBetween(this string text, char startCharacter, char? endCharacter = null)
string? GetWordThatContains(this string text, string word)
string GetWordBefore(this string text, string word)
string? GetWordAfter(this string text, string word)
// Checks
bool ContainsAnyOf(this string text, params string[] substrings) // Case insensitive
bool StartsWithAnyOf(this string text, params string[] substrings) // Case insensitive
Examples
// Remove
"Hello World".Remove("World"); // "Hello "
// Minify
"Hello\n World\t!".Minify(); // "HelloWorld!"
// Case
"hello".ToFirstUpper(); // "Hello"
"HELLO".ToFirstLower(); // "hELLO"
// Between
"(value)".GetStringBetween('(', ')'); // "value"
"[data]".GetStringBetween('['); // "data"
// Word operations
"My awesome property".GetWordThatContains("some"); // "awesome"
"Hello beautiful world".GetWordBefore("world"); // "beautiful"
"Hello beautiful world".GetWordAfter("beautiful"); // "world"
// Checks
"hello world".ContainsAnyOf("foo", "world"); // true
"hello world".StartsWithAnyOf("HELLO", "foo"); // true (case insensitive)
Other Extensions
Enumerable Extensions
string ToStringWithSeparator(this IEnumerable<string> list, string separator = ", ")
Example:
var names = new[] { "John", "Jane", "Bob" };
var result = names.ToStringWithSeparator(); // "John, Jane, Bob"
var result = names.ToStringWithSeparator(" | "); // "John | Jane | Bob"
URL Extensions
object? EncodeAsUrl(this object value)
Example:
"hello world".EncodeAsUrl(); // "hello+world"
true.EncodeAsUrl(); // Boolean
123.EncodeAsUrl(); // 123
Exceptions
JsonParsingException
public class JsonParsingException : Exception {
public JsonParsingException(string? message, Exception? innerException)
}
InvalidJsonResponseException
public class InvalidJsonResponseException : Exception {
public HttpStatusCode StatusCode { get; }
public string RawContent { get; }
public string? ContentType { get; }
public InvalidJsonResponseException(
HttpStatusCode statusCode,
string rawContent,
string? contentType = null)
public InvalidJsonResponseException(
HttpStatusCode statusCode,
string rawContent,
string? contentType,
Exception innerException)
}
ConstantNotFoundException
public class ConstantNotFoundException : Exception {
public ConstantNotFoundException(string message)
}
Note: This exception exists in two namespaces:
Myth.Exceptions.ConstantNotFoundExceptionMyth.ValueObjects.ConstantNotFoundException
Interfaces
IPaginated
public interface IPaginated {
int PageNumber { get; }
int PageSize { get; }
int TotalPages { get; }
int TotalItems { get; }
}
IPaginated<T>
public interface IPaginated<T> : IPaginated {
IEnumerable<T> Items { get; }
}
Complete Example
// Program.cs - ASP.NET Core
var builder = WebApplication.CreateBuilder(args);
// Configure global JSON
JsonExtensions.Configure(settings => {
settings.CaseStrategy = CaseStrategy.SnakeCase;
settings.IgnoreNullValues = true;
});
// Build app (initializes MythServiceProvider automatically)
var app = builder.BuildApp();
app.MapGet("/orders", async (
[FromQuery] Pagination pagination,
IScopedService<IOrderRepository> repository) => {
return await repository.ExecuteAsync(async repo => {
var orders = await repo.GetPaginatedAsync(pagination);
return Results.Ok(orders);
});
});
app.Run();
// Value Objects
public class OrderStatus : Constant<OrderStatus, string> {
public static readonly OrderStatus Pending = CreateWithCallerName("P");
public static readonly OrderStatus Completed = CreateWithCallerName("C");
private OrderStatus(string name, string value) : base(name, value) { }
}
public class Address : ValueObject {
public string Street { get; }
public string City { get; }
public Address(string street, string city) {
Street = street;
City = city;
}
protected override IEnumerable<object> GetAtomicValues() {
yield return Street;
yield return City;
}
}
// Repository with IScopedService
public class OrderService {
private readonly IScopedService<IOrderRepository> _repository;
public async Task<Order> CreateAsync(CreateOrderDto dto) {
return await _repository.ExecuteAsync(async repo => {
var order = dto.ToJson().FromJson<Order>();
await repo.AddAsync(order);
return order;
});
}
}
License
Licensed under the Apache License 2.0. See LICENSE file for details.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- No dependencies.
NuGet packages (13)
Showing the top 5 NuGet packages that depend on Myth.Commons:
| Package | Downloads |
|---|---|
|
Myth.Specification
Query specification pattern for encapsulating business rules in readable, composable, and testable specifications. Supports filtering, sorting, pagination, and conditional logic for clean query construction. |
|
|
Myth.Repository
Generic repository pattern interfaces with async support, specification integration, and pagination. Provides read/write separation, CRUD operations, and extensible repository contracts for clean data access architecture. |
|
|
Harpy.Domain
Basis for the domain layer of the Harpy Framework |
|
|
Myth.Rest
Fluent REST client with circuit breaker, retry policies, certificate support, and object pooling. Provides resilient HTTP communication with configurable error handling and response mapping. |
|
|
Harpy.Presentation
Basis for the presentation layer of the Harpy Framework |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 4.3.0 | 0 | 2/1/2026 |
| 4.3.0-preview.3 | 29 | 2/1/2026 |
| 4.3.0-preview.2 | 141 | 12/22/2025 |
| 4.2.1-preview.1 | 631 | 12/2/2025 |
| 4.2.0 | 825 | 11/30/2025 |
| 4.2.0-preview.1 | 71 | 11/29/2025 |
| 4.1.0 | 695 | 11/27/2025 |
| 4.1.0-preview.3 | 140 | 11/27/2025 |
| 4.1.0-preview.2 | 135 | 11/27/2025 |
| 4.1.0-preview.1 | 136 | 11/26/2025 |
| 4.0.1 | 526 | 11/22/2025 |
| 4.0.1-preview.8 | 160 | 11/22/2025 |
| 4.0.1-preview.7 | 162 | 11/22/2025 |
| 4.0.1-preview.6 | 147 | 11/22/2025 |
| 4.0.1-preview.5 | 207 | 11/21/2025 |
| 4.0.1-preview.4 | 218 | 11/21/2025 |
| 4.0.1-preview.3 | 220 | 11/21/2025 |
| 4.0.1-preview.2 | 250 | 11/21/2025 |
| 4.0.1-preview.1 | 256 | 11/21/2025 |
| 4.0.0 | 748 | 11/20/2025 |
| 4.0.0-preview.3 | 352 | 11/19/2025 |
| 4.0.0-preview.2 | 98 | 11/15/2025 |
| 4.0.0-preview.1 | 117 | 11/15/2025 |
| 3.10.0 | 1,268 | 11/15/2025 |
| 3.0.5-preview.15 | 158 | 11/14/2025 |
| 3.0.5-preview.14 | 229 | 11/12/2025 |
| 3.0.5-preview.13 | 234 | 11/12/2025 |
| 3.0.5-preview.12 | 242 | 11/11/2025 |
| 3.0.5-preview.11 | 240 | 11/11/2025 |
| 3.0.5-preview.10 | 232 | 11/11/2025 |
| 3.0.5-preview.9 | 234 | 11/10/2025 |
| 3.0.5-preview.8 | 107 | 11/8/2025 |
| 3.0.5-preview.7 | 100 | 11/8/2025 |
| 3.0.5-preview.6 | 97 | 11/8/2025 |
| 3.0.5-preview.5 | 98 | 11/8/2025 |
| 3.0.5-preview.4 | 75 | 11/7/2025 |
| 3.0.5-preview.3 | 146 | 11/4/2025 |
| 3.0.5-preview.2 | 153 | 11/4/2025 |
| 3.0.5-preview.1 | 151 | 11/4/2025 |
| 3.0.4 | 675 | 11/3/2025 |
| 3.0.4-preview.19 | 85 | 11/2/2025 |
| 3.0.4-preview.17 | 81 | 11/1/2025 |
| 3.0.4-preview.16 | 85 | 11/1/2025 |
| 3.0.4-preview.15 | 77 | 10/31/2025 |
| 3.0.4-preview.14 | 146 | 10/31/2025 |
| 3.0.4-preview.13 | 142 | 10/30/2025 |
| 3.0.4-preview.12 | 132 | 10/23/2025 |
| 3.0.4-preview.11 | 133 | 10/23/2025 |
| 3.0.4-preview.10 | 129 | 10/23/2025 |
| 3.0.4-preview.9 | 123 | 10/23/2025 |
| 3.0.4-preview.8 | 123 | 10/22/2025 |
| 3.0.4-preview.6 | 126 | 10/21/2025 |
| 3.0.4-preview.5 | 124 | 10/21/2025 |
| 3.0.4-preview.4 | 131 | 10/20/2025 |
| 3.0.4-preview.3 | 127 | 10/20/2025 |
| 3.0.4-preview.2 | 52 | 10/18/2025 |
| 3.0.4-preview.1 | 130 | 10/7/2025 |
| 3.0.3 | 588 | 8/30/2025 |
| 3.0.2 | 489 | 8/23/2025 |
| 3.0.2-preview.4 | 138 | 8/21/2025 |
| 3.0.2-preview.3 | 105 | 8/16/2025 |
| 3.0.2-preview.1 | 82 | 5/23/2025 |
| 3.0.1 | 6,887 | 3/12/2025 |
| 3.0.1-preview.2 | 152 | 3/11/2025 |
| 3.0.1-preview.1 | 97 | 2/5/2025 |
| 3.0.0.2-preview | 207 | 12/10/2024 |
| 3.0.0.1-preview | 213 | 6/29/2024 |
| 3.0.0 | 4,946 | 12/10/2024 |
| 3.0.0-preview | 221 | 6/28/2024 |
| 2.0.0.16 | 16,728 | 12/15/2023 |
| 2.0.0.15 | 668 | 12/15/2023 |
| 2.0.0.11 | 5,907 | 8/11/2022 |
| 2.0.0.10 | 3,324 | 7/20/2022 |
| 2.0.0.9 | 3,417 | 7/15/2022 |
| 2.0.0.8 | 3,438 | 7/12/2022 |
| 2.0.0.7 | 3,355 | 6/20/2022 |
| 2.0.0.6 | 3,469 | 5/23/2022 |
| 2.0.0.5 | 3,466 | 5/18/2022 |
| 2.0.0 | 3,563 | 2/17/2022 |
| 1.0.0.8 | 4,229 | 12/8/2020 |
| 1.0.0.8-stage-02 | 1,209 | 12/7/2020 |
| 1.0.0.8-stage-01 | 1,471 | 9/25/2020 |
| 1.0.0.7 | 5,485 | 7/28/2020 |
| 1.0.0.7-stage-03 | 1,251 | 7/28/2020 |
| 1.0.0.7-stage-02 | 1,135 | 7/23/2020 |
| 1.0.0.7-stage-01 | 1,087 | 7/21/2020 |
| 1.0.0.6 | 4,013 | 6/28/2020 |
| 1.0.0.4 | 3,857 | 6/27/2020 |
| 1.0.0.3 | 2,210 | 6/27/2020 |
| 1.0.0.2 | 6,906 | 6/25/2020 |
| 1.0.0.1 | 2,639 | 6/25/2020 |
| 1.0.0 | 888 | 6/25/2020 |