Skip to content

Commit

Permalink
feat: added function getManyByPredicate
Browse files Browse the repository at this point in the history
  • Loading branch information
Sergey Rogachev committed Sep 4, 2023
1 parent 39637f6 commit 51957ff
Show file tree
Hide file tree
Showing 3 changed files with 145 additions and 1 deletion.
12 changes: 12 additions & 0 deletions docs/docs/features/entities-management/entities.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,18 @@ import { getEntityByPredicate } from '@ngneat/elf-entities';
const todo = todosStore.query(getEntityByPredicate(({ title }) => title === 'Elf'));
```

### `getManyByPredicate`

Get multiple entities from the store by predicate:

```ts
import { getManyByPredicate } from '@ngneat/elf-entities';

const todo = todosStore.query(getManyByPredicate(({ active }) => active));
const todo = todosStore.query(getManyByPredicate(({ active }) => active), { pluck: 'title });
const todo = todosStore.query(getManyByPredicate(({ active }) => active), { ref: UIEntitiesRef, pluck: 'title });
```
### `hasEntity`
Returns whether an entity exists:
Expand Down
92 changes: 92 additions & 0 deletions packages/entities/src/lib/queries.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
hasEntity,
getEntitiesIds,
getEntityByPredicate,
getManyByPredicate,
} from './queries';
import { addEntities } from './add.mutation';
import { UIEntitiesRef } from './entity.state';
Expand Down Expand Up @@ -195,4 +196,95 @@ describe('queries', () => {
]
`);
});

describe('getManyByPredicate', () => {
it('should return the collection', () => {
const store = createEntitiesStore();
store.update(addEntities(createTodo(1)));
store.update(addEntities(createTodo(2)));
store.update(addEntities(createTodo(3)));
store.update(addEntities(createTodo(4)));
expect(
store.query(getManyByPredicate((el: Todo) => [2, 3].includes(el.id)))
).toMatchInlineSnapshot(`
Array [
Object {
"completed": false,
"id": 2,
"title": "todo 2",
},
Object {
"completed": false,
"id": 3,
"title": "todo 3",
},
]
`);
});
it('should work with pluck', () => {
const store = createEntitiesStore();
store.update(addEntities(createTodo(1)));
store.update(addEntities(createTodo(2)));
store.update(addEntities(createTodo(3)));
store.update(addEntities(createTodo(4)));
expect(
store.query(getManyByPredicate((el: Todo) => [4, 3].includes(el.id)))
).toMatchInlineSnapshot(`
Array [
3,
4,
]
`);
});

it('should work with ref', () => {
const store = createUIEntityStore();

store.update(addEntities(createUITodo(1), { ref: UIEntitiesRef }));
store.update(addEntities(createUITodo(2), { ref: UIEntitiesRef }));
store.update(addEntities(createUITodo(3), { ref: UIEntitiesRef }));
store.update(addEntities(createUITodo(4), { ref: UIEntitiesRef }));
expect(
store.query(
getManyByPredicate(
(el: { id: number; open: boolean }) => [2, 3].includes(el.id),
{ ref: UIEntitiesRef }
)
)
).toMatchInlineSnapshot(`
Array [
Object {
"id": 2,
"open": false,
},
Object {
"id": 3,
"open": false,
},
]
`);
});

it('should work with ref and pluck', () => {
const store = createUIEntityStore();

store.update(addEntities(createUITodo(1), { ref: UIEntitiesRef }));
store.update(addEntities(createUITodo(2), { ref: UIEntitiesRef }));
store.update(addEntities(createUITodo(3), { ref: UIEntitiesRef }));
store.update(addEntities(createUITodo(4), { ref: UIEntitiesRef }));
expect(
store.query(
getManyByPredicate(
(el: { id: number; open: boolean }) => [2, 3].includes(el.id),
{ ref: UIEntitiesRef, pluck: 'id' }
)
)
).toMatchInlineSnapshot(`
Array [
2,
3,
]
`);
});
});
});
42 changes: 41 additions & 1 deletion packages/entities/src/lib/queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
ItemPredicate,
} from './entity.state';
import { Query } from '@ngneat/elf';
import { checkPluck } from './entity.utils';

/**
*
Expand Down Expand Up @@ -109,7 +110,7 @@ export function getEntityByPredicate<
predicate: ItemPredicate<getEntityType<S, Ref>>,
options: BaseEntityOptions<Ref> = {}
): Query<S, getEntityType<S, Ref> | undefined> {
return function (state) {
return function (state) {
const { ref: { entitiesKey, idsKey } = defaultEntitiesRef } = options;
const entities = state[entitiesKey];
const id = state[idsKey].find((id: getIdType<S, Ref>) => {
Expand All @@ -120,6 +121,45 @@ export function getEntityByPredicate<
};
}

/**
*
* Get many entities by predicate
*
* @example
*
* store.query(geManyByPredicate(({ active }) => active))
* store.query(geManyByPredicate((el: Todo) => el.active, { pluck: 'title' }))
* store.query(geManyByPredicate((el: Todo) => el.active, { ref: UIEntitiesRef, pluck: 'title' }))
*/
export function getManyByPredicate<
S extends EntitiesState<Ref>,
R extends getEntityType<S, Ref>[],
K extends keyof getEntityType<S, Ref>,
Ref extends EntitiesRef = DefaultEntitiesRef
>(
predicate: ItemPredicate<getEntityType<S, Ref>>,
options?: {
pluck?: K | ((entity: getEntityType<S, Ref>) => R);
} & BaseEntityOptions<Ref>
): Query<S, getEntityType<S, Ref>[]> {
return function (state) {
const { ref: { entitiesKey, idsKey } = defaultEntitiesRef, pluck } =
options || {};
const filteredEntities: getEntityType<S, Ref>[] = [];

state[idsKey].forEach((id: getIdType<S, Ref>, index: number) => {
const entity = state[entitiesKey][id];

if (predicate(entity, index)) {
filteredEntities.push(checkPluck(entity, pluck));
}
});
console.log(filteredEntities);

return filteredEntities;
};
}

/**
*
* Check whether the entity exist
Expand Down

0 comments on commit 51957ff

Please sign in to comment.