EasyExtensions 0.1.61

There is a newer version of this package available.
See the version list below for details.
dotnet add package EasyExtensions --version 0.1.61                
NuGet\Install-Package EasyExtensions -Version 0.1.61                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="EasyExtensions" Version="0.1.61" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add EasyExtensions --version 0.1.61                
#r "nuget: EasyExtensions, 0.1.61"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install EasyExtensions as a Cake Addin
#addin nuget:?package=EasyExtensions&version=0.1.61

// Install EasyExtensions as a Cake Tool
#tool nuget:?package=EasyExtensions&version=0.1.61                

GitHub Nuget Static Badge GitHub Actions Workflow Status NuGet version (EasyExtensions) CodeFactor GitHub repo size

EasyExtensions

Ready-to-use .NET Standard library for convenient development.

Purposes

  • Easy to use - just add a few lines of code to start working with the library.
  • Flexible - use the library as a base for your project.
  • Fast - add new features and commands in a few minutes.
  • Modern - use the latest technologies and approaches.
  • Secure - protect your data and users.
  • Open Source - contribute to the project and make it better.
  • Free - use the library for free.
  • Cross-platform - run the library on any platform.
  • Lightweight - use only necessary features.
  • Documented - read the documentation and start using the library.

Getting Started

  • Start by importing the library into your project
dotnet add package EasyExtensions --version 0.1.47
  • Add AspNetCore package if you want to use AspNetCore extensions
dotnet add package EasyExtensions.AspNetCore --version 0.1.47
  • Add Quartz package if you want to use Quartz extensions
dotnet add package EasyExtensions.Quartz --version 0.1.47
  • Add Entity Framework Core package if you want to use Entity Framework extensions
dotnet add package EasyExtensions.EntityFrameworkCore --version 0.1.47
  • Add Drawing package if you want to use Drawing extensions
dotnet add package EasyExtensions.Drawing --version 0.1.47
  • Add Authorization package if you want to use Authorization extensions
dotnet add package EasyExtensions.Authorization --version 0.1.47

Contents

Extensions

Byte Array Extensions

/// <summary>
/// Calculate SHA512 hash of byte array.
/// </summary>
/// <param name="bytes"> Data to calculate hash. </param>
/// <returns> SHA512 hash of byte array. </returns>
string SHA512(this byte[] bytes);

Claims Principal Extensions

/// <summary>
/// Get user id.
/// </summary>
/// <param name="user"> User instance. </param>
/// <returns> User id. </returns>
/// <exception cref="KeyNotFoundException"> Throws when claim not found. </exception>
int GetId(this ClaimsPrincipal? user);

/// <summary>
/// Try get user id.
/// </summary>
/// <param name="user"> User instance. </param>
/// <returns> User id, or 0 if not found. </returns>
int TryGetId(this ClaimsPrincipal? user);

/// <summary>
/// Get user roles.
/// </summary>
/// <param name="user"> User instance. </param>
/// <param name="rolePrefix"> Role prefix, for example: "user-group-" prefix returns group like "user-group-admins" </param>
/// <returns> User roles. </returns>
IEnumerable<string> GetRoles(this ClaimsPrincipal user, string rolePrefix = "");

DateTime Extensions

/// <summary>
/// Remove microseconds from <see cref="DateTime"/>.
/// </summary>
/// <returns> DateTime without microseconds. </returns>
DateTime DropMicroseconds(this DateTime value);

/// <summary>
/// Remove microseconds from <see cref="DateTime"/>.
/// </summary>
/// <returns> DateTime without microseconds. </returns>
DateTimeOffset DropMicroseconds(this DateTimeOffset value);

/// <summary>
/// Create new datetime with same values but <see cref="DateTimeKind.Utc"/>.
/// </summary>
/// <returns> New datetime. </returns>
DateTime ToUniversalTimeWithoutOffset(this DateTime value);

/// <summary>
/// Convert datetime value to nullable datetime type.
/// </summary>
/// <returns> Wrapped datetime value. </returns>
DateTime? ToNullable(this DateTime value);

Enumerable Extensions

/// <summary>
/// Shuffles the elements of the <see cref="IEnumerable{T}"/>.
/// </summary>
/// <typeparam name="T">The type of the elements in the <see cref="IEnumerable{T}"/>.</typeparam>
/// <param name="source">The <see cref="IEnumerable{T}"/> to shuffle.</param>
/// <returns>A shuffled <see cref="IEnumerable{T}"/>.</returns>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="source"/> is null.</exception>
IEnumerable<T> Shuffle<T>(this IEnumerable<T> source);

/// <summary>
/// Gets a random element from the <see cref="IEnumerable{T}"/>.
/// </summary>
/// <typeparam name="T">The type of the elements in the <see cref="IEnumerable{T}"/>.</typeparam>
/// <param name="enumerable">The <see cref="IEnumerable{T}"/> to get a random element from.</param>
/// <returns>A random element from the <see cref="IEnumerable{T}"/>.</returns>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="enumerable"/> is null.</exception>
T Random<T>(this IEnumerable<T> enumerable);

Exception Extensions

/// <summary>
/// Create string with error message from all inner exceptions if exists.
/// </summary>
/// <returns> Error message. </returns>
string ToStringWithInner(this Exception exception);

HttpRequest Extensions

/// <summary>
/// Get remote host IP address using proxy "X-Real-IP", "CF-Connecting-IP", "X-Forwarded-For" headers, or connection remote IP address.
/// </summary>
/// <returns> IP address, or "Unknown" by default. </returns>
string GetRemoteAddress(this HttpRequest request);

Math Extensions

/// <summary>
/// Pow specified foundation to exponent.
/// </summary>
/// <param name="number"> Foundation. </param>
/// <param name="exponent"> Exponent of pow. </param>
/// <returns> Calculation result. </returns>
/// <exception cref="OverflowException"> Throws when calculation result is too big. </exception>
int Pow(this int number, int exponent);

Object Extensions

/// <summary>
/// Clone object with MemberwiseClone.
/// </summary>
/// <typeparam name="TObj"> Type of object. </typeparam>
/// <param name="obj"> Object to clone. </param>
/// <returns> Cloned object. </returns>
TObj MemberwiseClone<TObj>(this TObj obj);

ServiceCollection Extensions

/// <summary>
/// Adds <see cref="CpuUsageService"/> to the <see cref="IServiceCollection"/>.
/// </summary>
/// <param name="services"> Current <see cref="IServiceCollection"/> instance. </param>
/// <returns> Current <see cref="IServiceCollection"/> instance. </returns>
IServiceCollection AddCpuUsageService(this IServiceCollection services);

/// <summary>
/// Add all types inherited from TInterface.
/// </summary>
/// <param name="services"> Current <see cref="IServiceCollection"/> instance. </param>
/// <param name="serviceLifetime"> Service lifetime, default is Scoped. </param>
/// <typeparam name="TInterface"> Interface type. </typeparam>
/// <returns> Current <see cref="IServiceCollection"/> instance. </returns>
IServiceCollection AddTypesOfInterface<TInterface>(this IServiceCollection services, ServiceLifetime serviceLifetime = ServiceLifetime.Scoped) where TInterface : class

Stream Extensions

/// <summary>
/// Reads the bytes from the current stream and writes them to the byte array.
/// </summary>
/// <returns> Received byte array. </returns>
/// <exception cref="IOException"> An I/O error occurred. </exception>
/// <exception cref="ArgumentNullException"> Destination is null. </exception>
/// <exception cref="ObjectDisposedException"> Either the current stream or the destination stream is disposed. </exception>
/// <exception cref="NotSupportedException"> The current stream does not support reading, or the destination stream does not support writing. </exception>
byte[] ReadToEnd(this Stream stream);

/// <summary>
/// Asynchronously reads the bytes from the current stream and writes them to the byte array.
/// </summary>
/// <returns> Received byte array. </returns>
/// <exception cref="ArgumentNullException"> Destination is null. </exception>
/// <exception cref="ObjectDisposedException"> Either the current stream or the destination stream is disposed. </exception>
/// <exception cref="NotSupportedException"> The current stream does not support reading, or the destination stream does not support writing. </exception>
public static async Task<byte[]> ReadToEndAsync(this Stream stream)

/// <summary>
/// Calculate SHA512 hash of byte stream.
/// </summary>
/// <param name="stream"> Data to calculate hash. </param>
/// <returns> SHA512 hash of byte stream. </returns>
string SHA512(this Stream stream);

String Extensions

/// <summary>
/// Make first letter as lower case. If text is null or whitespace - returns <see cref="string.Empty"/>
/// </summary>
/// <returns> Text with lower case first letter. </returns>
string ToLowerFirstLetter(this string text);

/// <summary>
/// Make first letter as upper case. If text is null or whitespace - returns <see cref="string.Empty"/>
/// </summary>
/// <returns> Text with upper case first letter. </returns>
string ToUpperFirstLetter(this string text);

/// <summary>
/// Create SHA512 hash of specified text string.
/// </summary>
/// <returns> SHA512 hash. </returns>
string SHA512(this string str);

/// <summary>
/// Read only numbers from specified string.
/// </summary>
/// <returns> Parsed number, or -1 by default. </returns>
long ReadOnlyNumbers(this string str);

IP Address Extensions

/// <summary>
/// Get network address.
/// </summary>
/// <param name="address"> IP address. </param>
/// <param name="subnetMask"> Subnet mask. </param>
/// <returns> Network address. </returns>
IPAddress GetNetwork(this IPAddress address, IPAddress subnetMask);

/// <summary>
/// Get broadcast address.
/// </summary>
/// <param name="address"> IP address. </param>
/// <param name="subnetMask"> Subnet mask. </param>
/// <returns> Broadcast address. </returns>
IPAddress GetBroadcast(this IPAddress address, IPAddress subnetMask);

/// <summary>
/// Get network address.
/// </summary>
/// <param name="address"> IP address. </param>
/// <param name="subnetMask"> Subnet mask. </param>
/// <returns> Network address. </returns>
/// <exception cref="ArgumentOutOfRangeException"> Thrown when subnet mask is invalid. </exception>
IPAddress GetNetwork(this IPAddress address, int subnetMask);

/// <summary>
/// Get broadcast address.
/// </summary>
/// <param name="address"> IP address. </param>
/// <param name="subnetMask"> Subnet mask. </param>
/// <returns> Broadcast address. </returns>
/// <exception cref="ArgumentOutOfRangeException"> Thrown when subnet mask is invalid. </exception>
IPAddress GetBroadcast(this IPAddress address, int subnetMask);

Helpers

DateTime Helpers

/// <summary>
/// Parse DateTime from JSON format ISO 8601.
/// </summary>
/// <returns> Parsed datetime with UTC kind. </returns>
/// <exception cref="ArgumentException"></exception>
/// <exception cref="FormatException"></exception>
/// <exception cref="NotSupportedException"></exception>
DateTime ParseDateTime(string datetime);

/// <summary>
/// Parse DateTimeOffset from JSON format ISO 8601.
/// </summary>
/// <returns> Parsed datetime offset. </returns>
/// <exception cref="ArgumentException"></exception>
/// <exception cref="FormatException"></exception>
DateTimeOffset ParseDateTimeOffset(string datetime);

Reflection Helpers

/// <summary>
/// Get all types inherited from interface.
/// </summary>
/// <typeparam name="TInterface"> Interface type. </typeparam>
/// <returns> All types inherited from interface. </returns>
IEnumerable<Type> GetTypesOfInterface<TInterface>() where TInterface : class

/// <summary>
/// Copy matching properties from source to destination.
/// </summary>
/// <param name="source"> Source object. </param>
/// <param name="destination"> Destination object. </param>
void CopyMatchingProperties(object source, object destination);

String Helpers

/// <summary>
/// Fast generate pseudo random string with <see cref="DefaultCharset"/> and string length.
/// </summary>
/// <returns> Pseudo-random string. </returns>
string CreatePseudoRandomString();

/// <summary>
/// Fast generate pseudo random string with <see cref="DefaultCharset"/> and specified string length.
/// </summary>
/// <param name="length"> Result string length. </param>
/// <returns> Pseudo-random string. </returns>
string CreatePseudoRandomString(int length);

/// <summary>
/// Fast generate pseudo random string with specified charset and string length.
/// </summary>
/// <param name="charset"> Generator charset. </param>
/// <param name="length"> Result string length. </param>
/// <returns> Pseudo-random string. </returns>
string CreatePseudoRandomString(int length, string charset);

/// <summary>
/// Generate random string with <see cref="DefaultCharset"/> and string length.
/// </summary>
/// <returns> Really random string. </returns>
string CreateRandomString();

/// <summary>
/// Generate random string with <see cref="DefaultCharset"/> and specified string length.
/// </summary>
/// <param name="length"> Result string length. </param>
/// <returns> Really random string. </returns>
string CreateRandomString(int length);

/// <summary>
/// Generate random string with specified charset and string length.
/// </summary>
/// <param name="charset"> Generator charset. </param>
/// <param name="length"> Result string length. </param>
/// <returns> Really random string. </returns>
string CreateRandomString(int length, string charset);

/// <summary>
/// Remove spaces from string - trim, replace new lines and multiple spaces.
/// </summary>
/// <param name="comment"></param>
/// <returns></returns>
string RemoveSpaces(string? comment);

IP Address Helpers

/// <summary>
/// Convert IP address to number.
/// </summary>
/// <param name="ipAddress"> IP address. </param>
/// <returns> IP address as number. </returns>
BigInteger IpToNumber(string ipAddress);

/// <summary>
/// Convert number to IP address.
/// </summary>
/// <param name="ipNumber"> IP address as number. </param>
/// <returns> IP address. </returns>
IPAddress NumberToIp(BigInteger ipNumber);

/// <summary>
/// Get subnet mask address.
/// </summary>
/// <param name="subnetMask"> Subnet mask. </param>
/// <returns> Subnet address. </returns>
/// <exception cref="ArgumentOutOfRangeException"> Thrown when subnet mask is invalid. </exception>
IPAddress GetMaskAddress(int subnetMask);

/// <summary>
/// Extract subnet mask from IP address.
/// </summary>
/// <param name="ip"> IP address. </param>
/// <returns> Subnet mask, or null if not found. </returns>
int? ExtractMask(string ip);

Quartz Extensions

Usually, Quartz integration requires a lot of boilerplate code. This library simplifies the process of adding Quartz jobs to the project.

ServiceCollection Extensions

/// <summary>
/// Adds Quartz jobs with <see cref="JobTriggerAttribute"/> to the <see cref="IServiceCollection"/>.
/// </summary>
/// <param name="services">IServiceCollection instance.</param>
/// <returns> Current <see cref="IServiceCollection"/> instance. </returns>
IServiceCollection AddQuartzJobs(this IServiceCollection services);

example of usage:

builder.Services.AddQuartzJobs();

Attributes

JobTriggerAttribute

Example of usage:

[JobTrigger(minutes: 1)]
[DisallowConcurrentExecution]
public class TestJob : IJob
{
    public Task Execute(IJobExecutionContext context)
    {
        Console.WriteLine("Test job executed.");
        return Task.CompletedTask;
    }
}

Authorization Extensions

ServiceCollection Extensions

/// <summary>
/// Adds CORS policy with origins.
/// </summary>
/// <param name="services"> <see cref="IServiceCollection"/> instance. </param>
/// <param name="policyName"> Name of the policy. </param>
/// <param name="origins"> Origins to add to the policy. </param>
/// <returns></returns>
IServiceCollection AddCorsWithOrigins(this IServiceCollection services, string policyName, params string[] origins);

/// <summary>
/// Adds JWT authentication from JwtSettings section or Jwt[Key] configuration values.
/// </summary>
/// <param name="services"> <see cref="IServiceCollection"/> instance. </param>
/// <param name="configuration"> Configuration from which to get JWT settings. </param>
/// <returns> Current <see cref="IServiceCollection"/> instance. </returns>
/// <exception cref="KeyNotFoundException"> When JwtSettings section is not set. </exception>
IServiceCollection AddJwt(this IServiceCollection services, IConfiguration configuration);

/// <summary>
/// Ignore <see cref="AuthorizeAttribute"/> when application is on development environment.
/// </summary>
/// <returns> Current <see cref="IServiceCollection"/> instance. </returns>
IServiceCollection AllowAnonymousOnDevelopment(this IServiceCollection services);

Drawing Extensions

Image Extensions

/// <summary>
/// Fit image to target size and copy and blur it to background.
/// </summary>
/// <param name="image">Target image.</param>
/// <param name="targetWidth">Target width.</param>
/// <param name="targetHeight">Target height.</param>
/// <param name="gaussianBlurLevel">Gaussian blur level (optional).</param>
/// <returns cref="Image">Image with blured background.</returns>
Image FitBluredBackground(this Image image, int targetWidth, int targetHeight, float gaussianBlurLevel = 8F);

/// <summary>
/// Save image as JPEG to byte array.
/// </summary>
/// <param name="image">Target image.</param>
/// <returns>Byte array of image.</returns>
byte[] SaveAsJpegToArray(this Image image);

Entity Framework Extensions

ServiceCollection Extensions

/// <summary>
/// Adds exception handler for EasyExtensions.EntityFrameworkCore.Exceptions to the <see cref="IServiceCollection"/>.
/// </summary>
/// <param name="services"> The <see cref="IServiceCollection"/> instance. </param>
/// <returns> Current <see cref="IServiceCollection"/> instance. </returns>
IServiceCollection AddExceptionHandler(this IServiceCollection services);

/// <summary>
/// Sets up Gridify.
/// </summary>
IServiceCollection AddGridifyMappers(this IServiceCollection services);

/// <summary>
/// Adds a <see cref="DbContext"/> to the <see cref="IServiceCollection"/> using the 
/// <see cref="IConfigurationRoot"/> to build the connection string from DatabaseSettings section.
/// </summary>
/// <typeparam name="TContext"> The type of <see cref="DbContext"/> to add. </typeparam>
/// <param name="services"> The <see cref="IServiceCollection"/> instance. </param>
/// <param name="configuration"> The <see cref="IConfigurationRoot"/> instance. </param>
/// <param name="maxPoolSize"> The maximum pool size, default is 100. </param>
/// <param name="timeout_s"> The connection timeout in seconds, default is 60. </param>
/// <returns> Current <see cref="IServiceCollection"/> instance. </returns>
/// <exception cref="KeyNotFoundException"> When DatabaseSettings section is not set. </exception>
IServiceCollection AddDbContext<TContext>(this IServiceCollection services, IConfigurationRoot configuration, int maxPoolSize = 100, int timeout_s = 60) where TContext : DbContext

Host Extensions

/// <summary>
/// Applies migrations to the database.
/// </summary>
/// <returns> Current <see cref="IHost"/> instance. </returns>
IHost ApplyMigrations<TContext>(this IHost host) where TContext : DbContext

Sentry Extensions

WebHostBuilder Extensions

/// <summary>
/// Use Sentry integration with specified DSN.
/// </summary>
/// <param name="builder"> Current <see cref="IWebHostBuilder"/> instance. </param>
/// <param name="dsn"> Sentry DSN. </param>
/// <param name="forceUseInDevelopment"> Force use in development environment. </param>
/// <returns> Current <see cref="IWebHostBuilder"/> instance. </returns>
IWebHostBuilder UseSentryWithUserCapturing(this IWebHostBuilder builder, string dsn, bool forceUseInDevelopment = false);

Contributing

Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are greatly appreciated.

If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement". Don't forget to give the project a star! Thanks again!

  1. Fork the Project
  2. Create your Feature Branch (git checkout -b feature/AmazingFeature)
  3. Commit your Changes (git commit -m 'Add some AmazingFeature')
  4. Push to the Branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

License

Distributed under the MIT License. See LICENSE.md for more information.

Contact

E-Mail

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
.NET Core netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.1 is compatible. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • .NETStandard 2.1

    • No dependencies.

NuGet packages (6)

Showing the top 5 NuGet packages that depend on EasyExtensions:

Package Downloads
EasyExtensions.AspNetCore

Ready-to-use library for simplifying the development of .NET applications.

EasyExtensions.Quartz

Ready-to-use library for simplifying the development of .NET applications.

EasyExtensions.EntityFrameworkCore

Ready-to-use library for simplifying the development of .NET applications.

EasyExtensions.Drawing

Ready-to-use library for simplifying the development of .NET applications.

EasyExtensions.AspNetCore.Authorization

Ready-to-use library for simplifying the development of .NET applications.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
0.1.84 185 11/19/2024
0.1.83 261 11/15/2024
0.1.82 123 11/15/2024
0.1.81 176 11/13/2024
0.1.80 323 11/10/2024
0.1.79 489 10/22/2024
0.1.78 154 10/21/2024
0.1.77 159 10/21/2024
0.1.76 119 10/21/2024
0.1.75 120 10/21/2024
0.1.74 111 10/21/2024
0.1.73 370 10/17/2024
0.1.72 238 10/16/2024
0.1.71 112 10/15/2024
0.1.70 216 10/15/2024
0.1.69 118 10/15/2024
0.1.68 189 10/15/2024
0.1.67 118 10/15/2024
0.1.66 204 10/14/2024
0.1.65 145 10/13/2024
0.1.64 119 10/13/2024
0.1.63 142 10/12/2024
0.1.62 154 10/12/2024
0.1.61 123 10/12/2024
0.1.60 191 10/12/2024
0.1.59 116 10/12/2024
0.1.58 181 10/11/2024
0.1.57 517 9/30/2024
0.1.56 120 9/30/2024
0.1.55 128 9/27/2024
0.1.54 145 9/27/2024
0.1.53 127 9/27/2024
0.1.52 154 9/24/2024
0.1.51 125 9/24/2024
0.1.50 187 9/24/2024
0.1.49 272 9/18/2024
0.1.48 176 9/17/2024
0.1.47 183 9/15/2024
0.1.46 271 8/22/2024
0.1.45 392 8/9/2024
0.1.44 151 8/7/2024
0.1.43 130 8/7/2024
0.1.42 141 8/7/2024
0.1.41 325 8/5/2024
0.1.40 150 8/5/2024
0.1.39 123 8/5/2024
0.1.38 121 8/5/2024
0.1.37 165 8/4/2024
0.1.36 123 8/3/2024
0.1.35 140 8/2/2024
0.1.34 139 8/2/2024
0.1.33 226 8/1/2024
0.1.32 126 8/1/2024
0.1.31 112 8/1/2024
0.1.30 114 8/1/2024
0.1.29 110 8/1/2024
0.1.28 153 8/1/2024
0.1.27 146 7/30/2024
0.1.26 108 7/30/2024
0.1.25 136 7/28/2024
0.1.24 114 7/27/2024
0.1.23 121 7/27/2024
0.1.22 172 7/27/2024
0.1.21 115 7/27/2024
0.1.20 119 7/27/2024
0.1.19 122 7/27/2024
0.1.18 141 7/26/2024
0.1.17 112 7/26/2024
0.1.16 141 7/26/2024
0.1.15 99 7/26/2024
0.1.14 96 7/26/2024
0.1.13 85 7/26/2024
0.1.12 89 7/26/2024
0.1.11 111 7/26/2024
0.1.10 88 7/26/2024
0.1.9 82 7/26/2024
0.1.8 80 7/26/2024
0.1.7 70 7/26/2024
0.1.6 65 7/26/2024
0.1.5 86 7/26/2024
0.1.4 47 7/26/2024
0.1.3 69 7/24/2024
0.1.2 65 7/23/2024
0.1.1 55 7/23/2024
0.1.0 53 7/23/2024