entity-state
entity-state copied to clipboard
Feature/Discussion: Collection Sort/Filter
I've gone through the code in this to try and see if I can use it to replace (or get some better ideas on) our homegrown version of doing the same thing (ours has WAY too much boilerplate though and probably much worse performance).
There are a couple of things which most APIs have in common, some of which this repo addresses, however there are use cases I can't see addressed so far. Could I get some feedback on whether these are currently possible, or whether this could be planned for a future update? I'm interested in helping contribute where I can as I would like to use this.
- Differentiating between a single resource and a collection of resources.
- A collection may contain filters so as to not return the entire table.
- A collection may be sorted and return only part of the table.
- Entities can be related.
Currently I have a state for each API endpoint which contains the following keys:
table: Map<string, T>;
collections: Map<Params, string[]>;
I'm assuming this isn't the most perfect method, however, when requesting a single resource, it is checked first in the table, and then loaded via the service (being saved in the table). When a collection is requested, the parameters for that request are mapped to the identities returned. The individual resources are then saved in the table.
Would this implementation be required on top of this repository, or is this something this repository could accomplish? At the very least the discussion here may produce fruit for those searching for a similar answer, if not provide grounds for documentation.
As for entities being related, this leads into ORM which I'm not sure is a good idea client side, however I can see the benefits.
Thanks.
Can you provide a concrete example (including fetching, collections, ...) ?
If I understand you correctly, the table will store all entities. Then there are multiple collections, where you store a defined query like "age > 18" as key and the matching IDs will be saved in the array as the value.
I think the best approach is still to use Selectors here, which you can define somewhere outside as well, as long as you dont notice a significant performance hit. You could also define custom RXJS operators, if a selector does not suffice.
How would you realise relationships? I don't see how you can realise a generic implementation without a dedicated DSL. Which is certainly technically possible but blows the scope of this library, I think.
Thanks for getting back to me.
Regarding collections, correct, a map of query parameters to a list of array keys. The query parameters could include page number, page limit, sort key, sort direction, key=>value queries etc. Personally, I use query parameters for my API to accomplish this. I'll look at creating a slackblitz to demonstrate. Ideally I'd like to be able to create one class which can be configured per microservice (at the moment I have a state for each microservice which extends an abstract class - and it is in this vein how I'm most eager to use this plugin).
The purpose of the above which at present I don't see EntityState able to accomplish, is the ability to store multiple collections and share the resources between them. Thus when one collection is updated to retrieve a new version of a resource that is used in another collection, then provided the state is within a reasonable lastUpdated period and is not loading, anywhere referencing the old collection will get the updated resource.
The downsides to the above is that an appropriate cache invalidation strategy would be required as the updated resource may no longer be considered a part of the collection on the server side. That said, it may be that if an entity is updated, all collections are instantly invalidated all the time?
The above strategy would require a different EntityStateModel to remove the Page* properties for example and move that into a CollectionStateModel. At present I'm reinventing the wheel so I'm not sure if this is something you would want as part of this plugin (would it be that reusable? I am following a lose interpretation of the HAL+JSON standard). Would it be better to split out the Page* properties to allow for a custom extension to this plugin? I'll follow your advice here.
As for a ORM, I agree but my question would be whether this should be handled on the service upstream of the state, on the state itself, or between the state and the component? This is a very common use case, and although beyond the scope of this plugin, I do believe any suggestions/recommendations in documentation would be appreciated as I see a large intersection between those requiring this plugin and those requiring ORM of this kind. [This would probably be better tracked in a separate issue with this restricted to the above collection sort/filter request.]
Would a slackblitz or a public repo be better for this demo?
I would prefer a public repo. It might get clearer when I see it, but it anyhow it sounds like you want some quite complex things. I think a separate service is needed anyways to separate the functionalities. With the public repo I can give you my opinion if it's a thing for this library and if so you could develop a generic version in a fork? If it's a great feature I'm sure there will be support from us and the community to help you with that.
I don't have a good rule of thumb on where to handle these relationships. I lack the experience with projects with such use cases.