What is the recommended way to share functionality between Environment clients?
I'm currently developing a way to create, access and cache attachments for a feature. I find myself wanting to create an AttachmentsClient (with a .live and .mock extensions) and leverage that in the environment. However, other clients in the environment would likely want to access this functionality as well, and do so while accessing details specific to their implementation.
For example, a hypothetical .live WidgetsClient implementation could provide a list of WidgetRowStates as an Effect by querying documents in a local, no-sql database. As part of transforming the database query results into row states, it would also transform attachment identifiers into remote or local cache URLs to display widget photos in the list.
It's likely those implementation query results shouldn't leak out of the client into the state. Even if that was not specific to the live implementation, I don't think I'd want to receive the row state results from the WidgetClient in the reducer, extract the identifiers from the row states, pass them into the AttachmentsClient (which would return URLs as an Effect), then generate a new set of row states with the resulting URLs. (The AttachmentClient shouldn't know about WidgetRowStates, so splicing them together would have to happen in the reducer.)
On the other hand, I'd like to reuse this functionality across other clients, such as a .live GizmoClient also using a local, no-sql database, etc. In addition, similar functionality would be useful as a client in environment itself, such as clearing the attachment cache, retrieving the total on disk storage, etc. That would imply having an AttachmentsClient in the environment that would be available to the reducer.
My line of thought at the moment is to use composition to pass some kind of attachment manager with shared functionality into clients, such as a WidgetClient, and also wrap that with a AttachmentClient struct that makes it available in the environment / reducer. However, I'm not sure if this too should be an TCA environment-like struct, a class that implements an AttachmentManager protocol, etc.? I can see the benefits of creating mock and live versions of this attachment manager as well.