Skip to content

Releases: codebeltnet/savvyio

v4.0.2

18 Apr 17:47
8e509f1
Compare
Choose a tag to compare

What's Changed

Full Changelog: v4.0.1...v4.0.2

v4.0.1

31 Jan 20:51
9c093b3
Compare
Choose a tag to compare

What's Changed

Full Changelog: v4.0.0...v4.0.1

v4.0.0

13 Nov 06:30
d943657
Compare
Choose a tag to compare

What's Changed

Full Changelog: v3.0.0...v4.0.0

v4.0.0-rc.1

12 Nov 00:14
551b251
Compare
Choose a tag to compare
v4.0.0-rc.1 Pre-release
Pre-release

What's Changed

Full Changelog: v4.0.0-preview.2...v4.0.0-rc.1

v4.0.0-preview.2

06 Oct 21:57
41f42ca
Compare
Choose a tag to compare
v4.0.0-preview.2 Pre-release
Pre-release

What's Changed

Full Changelog: v4.0.0-preview.1...v4.0.0-preview.2

v4.0.0-preview.1

06 Sep 22:25
cec50d3
Compare
Choose a tag to compare
v4.0.0-preview.1 Pre-release
Pre-release

What's Changed

Full Changelog: v3.0.0...v4.0.0-preview.1

v3.0.0

01 Sep 21:46
915ca90
Compare
Choose a tag to compare

Noticeable highlights:

  • Support for Azure Storage Queue
  • Support for Azure Event Grid
  • CloudEvent now supports attribute extensions
  • Both Newtonsoft and System.Text.Json marshallers now supports naming conventions other than camelCase
  • Messages now support Acknowledgeable

Added

Savvyio.Commands.Messaging

  • CommandExtensions class in the Savvyio.Commands.Messaging namespace that consist of extension methods for the ICommand interface: ToMessage{T}
  • InMemoryCommandQueue class in the Savvyio.Commands.Messaging namespace that provides an in-memory implementation of the IPointToPointChannel{TRequest} interface useful for unit testing and the likes thereof

Savvyio.Core

  • AcknowledgedEventArgs class in the Savvyio.Messaging namespace that provides data for message related operations
  • IAcknowledgeable interface in the Savvyio.Messaging namespace that defines a generic way to make a message acknowledgeable
  • AsyncEventHandler{TEventArgs} delegate in the Savvyio namespace that represents the method that will handle an event when the event provides data asynchronously

Savvyio.EventDriven.Messaging

  • CloudEventExtensions class in the Savvyio.EventDriven.Messaging.CloudEvents.Cryptography namespace that consist of extension methods for the ICloudEvent{T} interface: SignCloudEvent{T}
  • SignedCloudEventExtensions class in the Savvyio.EventDriven.Messaging.CloudEvents.Cryptography namespace that consist of extension methods for the ISignedCloudEvent{T} interface: CheckCloudEventSignature{T}
  • SignedCloudEvent{T} class in the Savvyio.EventDriven.Messaging.CloudEvents.Cryptography namespace that provides a default implementation of the ISignedCloudEvent{T} interface
  • CloudEvent{T} class in the Savvyio.EventDriven.Messaging.CloudEvents namespace that provides a default implementation of the ICloudEvent{T} interface
  • MessageExtensions class in the Savvyio.EventDriven.Messaging.CloudEvents namespace that consist of extension methods for the IMessage{T} interface: ToCloudEvent{T}
  • IntegrationEventExtensions class in the Savvyio.EventDriven.Messaging namespace that consist of extension methods for the IIntegrationEvent interface: ToMessage{T}
  • InMemoryEventBus class in the Savvyio.EventDriven.Messaging namespace that provides an in-memory implementation of the IPublishSubscribeChannel{TRequest} interface useful for unit testing and the likes thereof

Savvyio.Extensions.DependencyInjection

  • ServiceCollectionExtensions class in the Savvyio.Extensions.DependencyInjection.Domain namespace was extended with a new extension method for the IServiceCollection interface: AddUnitOfWork{TService}

Savvyio.Extensions.DependencyInjection.QueueStorage

  • AzureCommandQueue{TMarker} class in the Savvyio.Extensions.DependencyInjection.QueueStorage.Commands namespace that provides a default implementation of the AzureCommandQueue class that is optimized for Dependency Injection
  • AzureEventBus{TMarker} class in the Savvyio.Extensions.DependencyInjection.QueueStorage.EventDriven namespace that provides a default implementation of the AzureEventBus class that is optimized for Dependency Injection
  • AzureEventBusOptions{TMarker} class in the Savvyio.Extensions.DependencyInjection.QueueStorage.EventDriven namespace that provides configuration options for AzureEventBus{TMarker}
  • AzureQueueOptions{TMarker} class in the Savvyio.Extensions.DependencyInjection.QueueStorage namespace that provides configuration options for AzureQueueOptions{TMarker}
  • ServiceCollectionExtensions class in the Savvyio.Extensions.DependencyInjection.QueueStorage namespace that consist of extension methods for the IServiceCollection interface: AddAzureCommandQueue, AddAzureEventBus

Savvyio.Extensions.Newtonsoft.Json

  • JsonSerializerExtensions class in the Savvyio.Extensions.Newtonsoft.Json namespace that consist of extension methods for the JsonSerializer class: ResolvePropertyKeyByConvention, ResolveDictionaryKeyByConvention

Savvyio.Extensions.QueueStorage

  • AzureCommandQueue class in the Savvyio.Extensions.QueueStorage.Commands namespace provides an Azure Storage Queue implementation of the IPointToPointChannel{TRequest}
  • AzureEventBus class in the Savvyio.Extensions.QueueStorage.EventDriven namespace provides a combined Azure Event Grid/Azure Storage Queue implementation of the IPublishSubscribeChannel{TRequest}
  • AzureEventBusOptions class in the Savvyio.Extensions.QueueStorage.EventDriven namespace that provides configuration options for AzureEventBus
  • AzureQueue{TRequest} class in the Savvyio.Extensions.QueueStorage namespace that represents the base class from which all implementations of Azure Storage Queue should derive
  • AzureQueueOptions class in the Savvyio.Extensions.QueueStorage namespace that provides configuration options for AzureQueue{TRequest}
  • AzureQueueReceiveOptions class in the Savvyio.Extensions.QueueStorage namespace that provides options that is related to receiving messages from an Azure Storage Queue
  • AzureQueueSendOptions class in the Savvyio.Extensions.QueueStorage namespace that provides options that is related to sending messages from an Azure Storage Queue

Changed

Savvyio.Commands

  • Dependencies to latest and greatest with respect to TFMs

Savvyio.Core

  • Dependencies to latest and greatest with respect to TFMs
  • IMessage interface to inherit from IAcknowledgeable

Savvyio.Domain

  • Dependencies to latest and greatest with respect to TFMs

Savvyio.Domain.EventSourcing

  • Dependencies to latest and greatest with respect to TFMs

Savvyio.EventDriven

  • Dependencies to latest and greatest with respect to TFMs

Savvyio.Extensions.Dapper

  • Dependencies to latest and greatest with respect to TFMs

Savvyio.Extensions.DapperExtensions

  • Dependencies to latest and greatest with respect to TFMs

Savvyio.Extensions.DependencyInjection

  • Dependencies to latest and greatest with respect to TFMs
  • AddDataStore{TService, T} extension method on the ServiceCollectionExtensions class in the Savvyio.Extensions.DependencyInjection.Data namespace to use a default lifetime of Scoped
  • AddDataStore{TService, T, TOptions} extension method on the ServiceCollectionExtensions class in the Savvyio.Extensions.DependencyInjection.Data namespace to use a default lifetime of Scoped
  • AddRepository{TService, TEntity, TKey} extension method on the ServiceCollectionExtensions class in the Savvyio.Extensions.DependencyInjection.Domain namespace to use a default lifetime of Scoped
  • AddMarshaller{TService} extension method on the ServiceCollectionExtensions class in the Savvyio.Extensions.DependencyInjection namespace to use a default lifetime of Singleton
  • AddDataSource{TService} extension method on the ServiceCollectionExtensions class in the Savvyio.Extensions.DependencyInjection namespace to use a default lifetime of Scoped
  • ConfigureTriple{TOptions} extension method on the ServiceCollectionExtensions class in the Savvyio.Extensions.DependencyInjection namespace was renamed to: AddConfiguredOptions{TOptions}

Savvyio.Extensions.DependencyInjection.Dapper

  • Dependencies to latest and greatest with respect to TFMs

Savvyio.Extensions.DependencyInjection.DapperExtensions

  • Dependencies to latest and greatest with respect to TFMs

Savvyio.Extensions.DependencyInjection.Domain

  • Dependencies to latest and greatest with respect to TFMs
  • AddAggregateRepository{TService, TEntity, TKey} extension method on the ServiceCollectionExtensions class in the Savvyio.Extensions.DependencyInjection.Domain namespace to use a default lifetime of Scoped

Savvyio.Extensions.DependencyInjection.EFCore

  • Dependencies to latest and greatest with respect to TFMs
  • DefaultEfCoreDataStore{T, TMarker} class in the Savvyio.Extensions.DependencyInjection.EFCore namespace was renamed to EfCoreDataStore{T, TMarker}

Savvyio.Extensions.DependencyInjection.EFCore.Domain

  • Dependencies to latest and greatest with respect to TFMs
  • AddEfCoreAggregateDataSource extension methods on the ServiceCollectionExtensions class in the Savvyio.Extensions.DependencyInjection.EFCore.Domain namespace uses Action{ServiceOptions} instead of Action{EfCoreServiceOptions}
  • AddEfCoreAggregateRepository extension methods on the ServiceCollectionExtensions class in the Savvyio.Extensions.DependencyInjection.EFCore.Domain namespace uses Action{ServiceOptions} instead of Action{EfCoreServiceOptions}

Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing

  • Dependencies to latest and greatest with respect to TFMs
  • AddEfCoreTracedAggregateRepository extension methods on the ServiceCollectionExtensions class in the Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing namespace uses Action{ServiceOptions} instead of Action{EfCoreServiceOptions}

Savvyio.Extensions.DependencyInjection.SimpleQueueService

  • Dependencies to latest and greatest with respect to TFMs
  • AddAmazonCommandQueue extension methods on the ServiceCollectionExtensions class in the Savvyio.Extensions.DependencyInjection.SimpleQueueService namespace to use a default lifetime of Singleton
  • AddAmazonEventBus extension methods on the ServiceCollectionExtensions class in the Savvyio.Extensions.DependencyInjection.SimpleQueueService namespace to use a default lifetime of Singleton

Savvyio.Extensions.Dispatchers

  • Dependencies to latest and greatest with respect to TFMs

Savvyio.Extensions.EFCore

  • Dependencies to latest and greatest with respect to TFMs
  • EfCoreDataStore{T, TOptions} abstract class in the Savvyio.Extensions.EFCore namespace was refactored to EfCoreDataStore{T} class using fixed EfCoreQueryOptions{T} while making it consistent with other default implementations

Savvyio.Extensions.EFCore.Domain

  • Dependencies to lat...
Read more

2.2.0

24 Jul 22:30
d82622c
Compare
Choose a tag to compare

Changed

Savvyio.Core

  • Dependencies to latest and greatest with respect to TFMs

Savvyio.Extensions.Dapper

  • Dependencies to latest and greatest with respect to TFMs

Savvyio.Extensions.DapperExtensions

  • Dependencies to latest and greatest with respect to TFMs

Savvyio.Extensions.DependencyInjection

  • Dependencies to latest and greatest with respect to TFMs

Savvyio.Extensions.EFCore

  • Dependencies to latest and greatest with respect to TFMs

Savvyio.Extensions.EFCore.Domain

  • Dependencies to latest and greatest with respect to TFMs

Savvyio.Extensions.EFCore.Domain.EventSourcing

  • Dependencies to latest and greatest with respect to TFMs

Savvyio.Extensions.Newtonsoft.Json

  • Dependencies to latest and greatest with respect to TFMs

Savvyio.Extensions.SimpleQueueService

  • Dependencies to latest and greatest with respect to TFMs

Savvyio.Extensions.Text.Json

  • Dependencies to latest and greatest with respect to TFMs

2.1.0

05 Mar 19:46
67715ca
Compare
Choose a tag to compare

Added

Savvyio.Core

  • MessageExtensions class in the Savvyio.Messaging.Cryptography namespace that consist of extension methods for the IMessage{T} interface: Sign{T} and CheckSignature{T}
  • MessageExtensions class in the Savvyio.Messaging namespace that consist of extension methods for the IMessage{T} interface: Clone{T}

Savvyio.Extensions.Newtonsoft.Json

  • NewtonsoftJsonMarshaller class in the Savvyio.Extensions.Newtonsoft.Json namespace was extended to include a new static method: Default (that provides a default instance of the NewtonsoftJsonMarshaller class optimized for messaging)

Savvyio.Extensions.SimpleQueueService

  • AmazonMessageOptions class in the Savvyio.Extensions.SimpleQueueService namespace was extended with a new read-only property, ClientConfigurations, that can be set using the ConfigureClient method
  • ClientConfigExtensions class in the Savvyio.Extensions.SimpleQueueService namespace that consist of extension methods for the ClientConfig class: IsValid, SimpleQueueService and SimpleNotificationService

Savvyio.Extensions.Text.Json

  • JsonMarshaller class in the Savvyio.Extensions.Text.Json namespace was extended to include a new static method: Default (that provides a default instance of the JsonMarshaller class optimized for messaging)

Changed

Savvyio.Commands

  • MessageExtensions class in the Savvyio.Commands.Messaging.Cryptography namespace was removed to favor the new generic equivalent in the Savvyio.Messaging.Cryptography namespace

Savvyio.EventDriven

  • MessageExtensions class in the Savvyio.EventDriven.Messaging.Cryptography namespace was removed to favor the new generic equivalent in the Savvyio.Messaging.Cryptography namespace
  • CloudEventExtensions class in the Savvyio.EventDriven.Messaging.CloudEvents.Cryptography namespace was extended with new extension methods for the ICloudEvent{T} interface: CheckSignature{T}
  • Sign{T} extension method on the CloudEventExtensions class in the Savvyio.EventDriven.Messaging.CloudEvents.Cryptography namespace was renamed to SignCloudEvent{T}

Savvyio.Extensions.SimpleQueueService

  • AmazonCommandQueue class in the Savvyio.Extensions.SimpleQueueService.Commands namespace to use the ClientConfigurations property when configured; otherwise the Endpoint property is used as it has previously (both properties are part of AmazonMessageOptions)
  • AmazonEventBus class in the Savvyio.Extensions.SimpleQueueService.EventDriven namespace to use the ClientConfigurations property when configured; otherwise the Endpoint property is used as it has previously (both properties are part of AmazonMessageOptions)
  • AmazonMessage{TRequest} class in the Savvyio.Extensions.SimpleQueueService namespace to use the ClientConfigurations property when configured; otherwise the Endpoint property is used as it has previously (both properties are part of AmazonMessageOptions)
  • AmazonCommandQueue class in the Savvyio.Extensions.SimpleQueueService.Commands namespace to store the full type name of the actual IMessage{T} implementation instead of the enclosing type of the payload data
  • AmazonEventBus class in the Savvyio.Extensions.SimpleQueueService.EventDriven namespace to store the full type name of the actual IMessage{T} implementation instead of the enclosing type of the payload data
  • AmazonMessage{TRequest} class in the Savvyio.Extensions.SimpleQueueService namespace to use the full type name of the actual IMessage{T} implementation instead of the enclosing type of the payload data glued together with MakeGenericType on IMessage{T}

2.0.0

11 Feb 06:51
ac4f934
Compare
Choose a tag to compare

Added

Savvyio.Commands

  • MessageExtensions class in the Savvyio.Commands.Messaging.Cryptography namespace that consist of extension methods for the IMessage{T} interface: Sign{T}

Savvyio.Core

  • ISignedMessage{T} interface in the Savvyio.Messaging.Cryptography namespace that defines a generic way to wrap an IRequest inside a cryptographically signed message
  • SignedMessage{T} record in the Savvyio.Messaging.Cryptography namespace that provides a default implementation of the ISignedMessage{T} interface
  • SignedMessageOptions class in the Savvyio.Messaging.Cryptography namespace that specifies options that is related to wrapping an IRequest implementation inside a cryptographically signed message
  • IMarshaller interface in the Savvyio namespace that defines methods for serializing and deserializing objects to and from a Stream
  • MetadataExtensions class in the Savvyio namespace was extended with new extension methods for the IMetadata interface: GetMemberType{T}
  • ICommand interface in the Savvyio.Commands namespace that defines a marker interface that specifies an intention to do something (e.g. change the state)
  • ICommandDispatcher interface in the Savvyio.Commands namespace that defines a Command dispatcher that uses Fire-and-Forget/In-Only MEP
  • ICommandHandler interface in the Savvyio.Commands namespace that defines a handler responsible for objects that implements the ICommand interface
  • ITracedAggregateRepository interface in the Savvyio.Domain.EventSourcing namespace that defines a generic way of abstracting traced read- and writable repositories (CRud) that is optimized for Domain Driven Design
  • ITracedAggregateRoot interface in the Savvyio.Domain.EventSourcing namespace that defines an Event Sourcing capable contract of an Aggregate as specified in Domain Driven Design
  • ITracedDomainEvent interface in the Savvyio.Domain.EventSourcing namespace that specifies something that happened in the domain that you want other parts of the same domain (in-process/inner-application) to be aware of
  • IAggregateRepository interface in the Savvyio.Domain namespace that defines a generic way of abstracting persistent repositories (CRUD) that is optimized for Domain Driven Design
  • IAggregateRoot interface in the Savvyio.Domain namespace that defines a marker interface of an Aggregate as specified in Domain Driven Design
  • IDomainEvent interface in the Savvyio.Domain namespace that defines a marker interface that specifies something that happened in the domain that you want other parts of the same domain (in-process/inner-application) to be made aware of
  • IDomainEventDispatcher interface in the Savvyio.Domain namespace that defines a Domain Event dispatcher that uses Fire-and-Forget/In-Only MEP
  • IDomainEventHandler interface in the Savvyio.Domain namespace that specifies a handler responsible for objects that implements the IDomainEvent interface
  • IEntity interface in the Savvyio.Domain namespace that defines an Entity as specified in Domain Driven Design
  • IIntegrationEvent interface in the Savvyio.EventDriven namespace that defines a marker interface that specifies something that happened when an Aggregate was successfully persisted and you want other subsystems (out-process/inter-application) to be made aware of
  • IIntegrationEventDispatcher interface in the Savvyio.EventDriven namespace that defines an Integration Event dispatcher that uses Fire-and-Forget/In-Only MEP
  • IIntegrationEventHandler interface in the Savvyio.EventDriven namespace that specifies a handler responsible for objects that implements the IIntegrationEvent interface
  • IQuery interface in the Savvyio.Queries namespace that defines a marker interface that specifies something that returns data
  • IQueryDispatcher interface in the Savvyio.Queries namespace that defines a Query dispatcher that uses Request-Reply/In-Out MEP
  • IQueryHandler interface in the Savvyio.Queries namespace that defines a handler responsible for objects that implements the IQuery interface
  • ISignedCloudEvent{T} interface in the Savvyio.EventDriven.Messaging.CloudEvents.Cryptography namespace that defines a generic way to wrap an IRequest inside a CloudEvents compliant message format
  • ICloudEvent{T} interface in the Savvyio.EventDriven.Messaging.CloudEvents namespace that defines a generic way to wrap an IRequest inside a CloudEvents compliant message format
  • AssemblyContext class in the Savvyio.Reflection namespace that provides a set of static methods and properties to manage and filter assemblies in the current application domain

Savvio.EventDriven

  • MessageExtensions class in the Savvyio.EventDriven.Messaging.Cryptography namespace that consist of extension methods for the IMessage{T} interface: Sign{T}
  • CloudEventExtensions class in the Savvyio.EventDriven.Messaging.CloudEvents.Cryptography namespace that consist of extension methods for the ICloudEvent{T} interface: Sign{T}
  • SignedCloudEvent{T} class in the Savvyio.EventDriven.Messaging.CloudEvents.Cryptography namespace that provides a default implementation of the ISignedCloudEvent{T} interface
  • CloudEvent{T} class in the Savvyio.EventDriven.Messaging.CloudEvents namespace that provides a default implementation of the ICloudEvent{T} interface
  • MessageExtensions class in the Savvyio.EventDriven.Messaging.CloudEvents namespace that consist of extension methods for the IMessage{T} interface: ToCloudEvent{T}

Savvyio.Extensions.DependencyInjection

  • ServiceCollectionExtensions class in the Savvyio.Extensions.DependencyInjection namespace was extended with new extension methods for the IServiceCollection interface: AddMarshaller{TService}

Savvyio.Extensions.Newtonsoft.Json

  • MessageConverter class in the Savvyio.Extensions.Newtonsoft.Json.Converters namespace that converts an IMessage{T} (or derived) to or from JSON
  • RequestConverter class in the Savvyio.Extensions.Newtonsoft.Json.Converters namespace that converts an IRequest to or from JSON
  • JsonConverterExtensions class in the Savvyio.Extensions.Newtonsoft.Json namespace was extended with new extension methods for the JsonConverter class: AddMessageConverter, AddRequestConverter
  • NewtonsoftJsonMarshaller class in the Savvyio.Extensions.Newtonsoft.Json namespace that provides a class for marshalling data using the Newtonsoft JSON library

Savvyio.Extensions.SimpleQueueService

  • AmazonMessageReceiveOptions class in the Savvyio.Extensions.SimpleQueueService namespace that provides options that is related to receive operations on AWS SQS

Savvyio.Extensions.Text.Json

  • DateTimeConverter class in the Savvyio.Extensions.Text.Json.Converters namespace that converts a DateTime value to or from JSON using ISO8601
  • DateTimeOffsetConverter class in the Savvyio.Extensions.Text.Json.Converters namespace that converts a DateTimeOffset value to or from JSON using ISO8601
  • MessageConverter class in the Savvyio.Extensions.Text.Json.Converters namespace that converts IMessage{T} (or derived) implementations to or from JSON
  • MetadataDictionaryConverter class in the Savvyio.Extensions.Text.Json.Converters namespace that converts IMetadataDictionary implementations to or from JSON
  • RequestConverter class in the Savvyio.Extensions.Text.Json.Converters namespace that converts IRequest implementations to or from JSON
  • JsonConverterExtensions class in the Savvyio.Extensions.Text.Json namespace that consist of extension methods for the JsonConverter class: RemoveAllOf, RemoveAllOf{T}, AddMetadataDictionaryConverter, AddMessageConverter, AddRequestConverter, AddDateTimeConverter and AddDateTimeOffsetConverter
  • JsonMarshaller class in the Savvyio.Extensions.Text.Json namespace that provides a class for marshalling data using native JSON support in .NET
  • JsonSerializerOptionsExtensions class in the Savvyio.Extensions.Text.Json namespace that consist of extension methods for the JsonSerializerOptions class: Clone

Changed

Savvyio.Commands

  • EncloseToMessage{T} extension method on the CommandExtensions class in the Savvyio.Commands.Messaging namespace to ToMessage{T}
  • ToMessage{T} extension method on the CommandExtensions class in the Savvyio.Commands.Messaging namespace to include a string that describes the type of command
  • MemoryCommandQueue class in the Savvyio.Commands.Messaging namespace to InMemoryCommandQueue (consistency with Microsoft naming convention)

Savvyio.Core

  • Time property on the IMessage{T} interface in the Savvyio.Messaging namespace from a string signature to a nullable DateTime signature
  • Time property on the Message{T} class in the Savvyio.Messaging namespace from a string signature to a nullable DateTime signature
  • SetTimestamp{T} extension method on the MetadataExtensions class in the Savvyio namespace to include an optional nullable DateTime parameter
  • Request record in the Savvyio namespace to automatically set the member type of the current implementation in the default constructor
  • ReceiveAsync method on the IReceiver{TRequest} interface in the Savvyio.Messaging namespace from Task{IEnumerable{IMessage{TRequest}}} to IAsyncEnumerable{IMessage{TRequest}}

Savvyio.Domain

  • SerializableAttribute and ISerializable implementations was removed from all custom exceptions due to Microsoft decision on deprecating most of the legacy serialization infrastructure dotnet/docs#34893

Savvyio.Domain.EventSourcing

  • TracedDomainEvent record in the Savvyio.Domain.EventSourcing namespace to exclude optional Type parameter from the constructor

Savvyio.EventDriven

  • EncloseToMessage{T} extension method on the IntegrationEventExtensions class in the Savvyio.EventDriven.Messaging namespace to ToMessage{T}
  • ToMessage{T} extension method on the IntegrationEventExtensions class in the Savvyio.EventDriven.Messaging namespace to include a string that describes t...
Read more