Skip to content
This repository was archived by the owner on Jun 22, 2021. It is now read-only.

Commit 9dec0cb

Browse files
authored
feat: Adds filter to entity functions. (#2)
BREAKING CHANGE: The `filter`, `sort`, and `paginate` options are now optional. BREAKING CHANGE: The `upsertEntity` function has been removed due to filter issues. BREAKING CHANGE: The `overwriteEntity` function was renamed to `replaceEntity`.
1 parent 0786601 commit 9dec0cb

31 files changed

+409
-237
lines changed

Diff for: docs/facade.md

+1-2
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,10 @@ The facade contains common functions for storage and retrieval of entities from
66
- [createEntity](./functions.md#createentity)
77
- [getEntities](./functions.md#getentities)
88
- [getEntity](./functions.md#getentity)
9-
- [overwriteEntity](./functions.md#overwriteentity)
9+
- [replaceEntity](./functions.md#replaceentity)
1010
- [patchEntity](./functions.md#patchentity)
1111
- [removeEntities](./functions.md#removeentities)
1212
- [removeEntity](./functions.md#removeentity)
13-
- [upsertEntity](./functions.md#upsertentity)
1413

1514
The functions have some common options that they use.
1615

Diff for: docs/functions.md

+74-38
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,10 @@ The [facade](./facade.md) contains common functions for storage and retrieval of
66
- [createEntity](#createentity)
77
- [getEntities](#getentities)
88
- [getEntity](#getentity)
9-
- [overwriteEntity](#overwriteentity)
9+
- [replaceEntity](#replaceentity)
1010
- [patchEntity](#patchentity)
1111
- [removeEntities](#removeentities)
1212
- [removeEntity](#removeentity)
13-
- [upsertEntity](#upsertentity)
1413

1514
### countEntities
1615
Counts the number of entities that match the `filter` option.
@@ -27,10 +26,19 @@ This package contains the [count entities tests](../src/tests/countEntities) and
2726
Creates a new entity using the `entity` option if no entity exists that matches the `id` option.
2827

2928
```ts
30-
const { entity } = await facade.createEntity({
31-
id: 'example_id',
32-
entity: { id: 'example_id', foo: 'bar' },
33-
});
29+
import ConflictingEntityError from 'js-entity-repos/core/dist/errors/ConflictingEntityError';
30+
31+
try {
32+
const { entity } = await facade.createEntity({
33+
id: 'example_id',
34+
entity: { id: 'example_id', foo: 'bar' },
35+
});
36+
} catch (err) {
37+
if (err instanceof ConflictingEntityError) {
38+
// An entity with the given id already exists.
39+
}
40+
throw err;
41+
}
3442
```
3543

3644
This package contains the [create entity tests](../src/tests/createEntity) and the [create entity signature](../src/signatures/CreateEntity.ts) for this function.
@@ -59,36 +67,66 @@ const firstPage = await facade.getEntities({
5967
This package contains the [get entities tests](../src/tests/getEntities) and the [get entities signature](../src/signatures/GetEntities.ts) for this function.
6068

6169
### getEntity
62-
Retrieves a single entity that matches the `id` option.
70+
Retrieves a single entity that matches the `id` and `filter` options.
6371

6472
```ts
65-
const { entity } = await facade.getEntity({
66-
id: 'example_id',
67-
});
73+
import MissingEntityError from 'js-entity-repos/core/dist/errors/MissingEntityError';
74+
75+
try {
76+
const { entity } = await facade.getEntity({
77+
id: 'example_id',
78+
filter: { foo: 'bar' },
79+
});
80+
} catch (err) {
81+
if (err instanceof MissingEntityError) {
82+
// No entity exists that matches the given id and filter options.
83+
}
84+
throw err;
85+
}
6886
```
6987

7088
This package contains the [get entity tests](../src/tests/getEntity) and the [get entity signature](../src/signatures/GetEntity.ts) for this function.
7189

72-
### overwriteEntity
73-
For an entity that matches the `id` option, it changes all of an entity's properties using the `entity` option.
90+
### replaceEntity
91+
For an entity that matches the `id` and `filter` options, it changes all of an entity's properties using the `entity` option.
7492

7593
```ts
76-
const { entity } = await facade.overwriteEntity({
77-
id: 'example_id',
78-
entity: { id: 'example_id', foo: 'bar' },
79-
});
94+
import MissingEntityError from 'js-entity-repos/core/dist/errors/MissingEntityError';
95+
96+
try {
97+
const { entity } = await facade.replaceEntity({
98+
id: 'example_id',
99+
entity: { id: 'example_id', foo: 'bar' },
100+
filter: { foo: 'bar' },
101+
});
102+
} catch (err) {
103+
if (err instanceof MissingEntityError) {
104+
// No entity exists that matches the given id and filter options.
105+
}
106+
throw err;
107+
}
80108
```
81109

82-
This package contains the [overwrite entity tests](../src/tests/overwriteEntity) and the [overwrite entity signature](../src/signatures/OverwriteEntity.ts) for this function.
110+
This package contains the [replace entity tests](../src/tests/replaceEntity) and the [replace entity signature](../src/signatures/ReplaceEntity.ts) for this function.
83111

84112
### patchEntity
85-
For an entity that matches the `id` option, it changes some of an entity's properties using the `patch` option.
113+
For an entity that matches the `id` and `filter` options, it changes some of an entity's properties using the `patch` option.
86114

87115
```ts
88-
const { entity } = await facade.patchEntity({
89-
id: 'example_id',
90-
patch: { foo: 'bar' },
91-
});
116+
import MissingEntityError from 'js-entity-repos/core/dist/errors/MissingEntityError';
117+
118+
try {
119+
const { entity } = await facade.patchEntity({
120+
id: 'example_id',
121+
patch: { foo: 'bar' },
122+
filter: { foo: 'bar' },
123+
});
124+
} catch (err) {
125+
if (err instanceof MissingEntityError) {
126+
// No entity exists that matches the given id and filter options.
127+
}
128+
throw err;
129+
}
92130
```
93131

94132
This package contains the [patch entity tests](../src/tests/patchEntity) and the [patch entity signature](../src/signatures/PatchEntity.ts) for this function.
@@ -105,24 +143,22 @@ await facade.removeEntities({
105143
This package contains the [remove entities tests](../src/tests/removesEntities) and the [remove entities signature](../src/signatures/RemoveEntities.ts) for this function.
106144

107145
### removeEntity
108-
Removes an entity that matches the `id` option.
146+
Removes an entity that matches the `id` and `filter` options.
109147

110148
```ts
111-
await facade.removeEntity({
112-
id: 'example_id',
113-
});
149+
import MissingEntityError from 'js-entity-repos/core/dist/errors/MissingEntityError';
150+
151+
try {
152+
await facade.removeEntity({
153+
id: 'example_id',
154+
filter: { foo: 'bar' },
155+
});
156+
} catch (err) {
157+
if (err instanceof MissingEntityError) {
158+
// No entity exists that matches the given id and filter options.
159+
}
160+
throw err;
161+
}
114162
```
115163

116164
This package contains the [remove entity tests](../src/tests/removesEntity) and the [remove entity signature](../src/signatures/RemoveEntity.ts) for this function.
117-
118-
### upsertEntity
119-
Creates an entity when no entity exists that matches the `id` option. Otherwise, it overwrites all of the properties for an entity that matches the `id` option.
120-
121-
```ts
122-
await facade.upsertEntity({
123-
id: 'example_id',
124-
entity: { id: 'example_id', foo: 'bar' },
125-
});
126-
```
127-
128-
This package contains the [upsert entity tests](../src/tests/upsertsEntity) and the [upsert entity signature](../src/signatures/UpsertEntity.ts) for this function.

Diff for: src/Facade.ts

+3-5
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,19 @@ import CountEntities from './signatures/CountEntities';
22
import CreateEntity from './signatures/CreateEntity';
33
import GetEntities from './signatures/GetEntities';
44
import GetEntity from './signatures/GetEntity';
5-
import OverwriteEntity from './signatures/OverwriteEntity';
65
import PatchEntity from './signatures/PatchEntity';
76
import RemoveEntities from './signatures/RemoveEntities';
87
import RemoveEntity from './signatures/RemoveEntity';
9-
import UpsertEntity from './signatures/UpsertEntity';
8+
import ReplaceEntity from './signatures/ReplaceEntity';
109
import Entity from './types/Entity';
1110

1211
export default interface Facade<E extends Entity> {
1312
readonly getEntity: GetEntity<E>;
1413
readonly createEntity: CreateEntity<E>;
15-
readonly overwriteEntity: OverwriteEntity<E>;
14+
readonly replaceEntity: ReplaceEntity<E>;
1615
readonly patchEntity: PatchEntity<E>;
17-
readonly removeEntity: RemoveEntity;
16+
readonly removeEntity: RemoveEntity<E>;
1817
readonly getEntities: GetEntities<E>;
1918
readonly countEntities: CountEntities<E>;
2019
readonly removeEntities: RemoveEntities<E>;
21-
readonly upsertEntity: UpsertEntity<E>;
2220
}

Diff for: src/signatures/CountEntities.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import Entity from '../types/Entity';
22
import Filter from '../types/Filter';
33

44
export interface Opts<E extends Entity> {
5-
readonly filter: Filter<E>;
5+
readonly filter?: Filter<E>;
66
}
77

88
export interface Result {

Diff for: src/signatures/GetEntities.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ import Pagination from '../types/Pagination';
55
import Sort from '../types/Sort';
66

77
export interface Opts<E extends Entity> {
8-
readonly filter: Filter<E>;
9-
readonly sort: Sort<E>;
10-
readonly pagination: Pagination;
8+
readonly filter?: Filter<E>;
9+
readonly sort?: Sort<E>;
10+
readonly pagination?: Pagination;
1111
}
1212

1313
export interface Result<E extends Entity> {

Diff for: src/signatures/GetEntity.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
import Entity from '../types/Entity';
2+
import Filter from '../types/Filter';
23

3-
export interface Opts {
4+
export interface Opts<E extends Entity> {
45
readonly id: string;
6+
readonly filter?: Filter<E>;
57
}
68

79
export interface Result<E extends Entity> {
810
readonly entity: E;
911
}
1012

11-
export type Signature<E extends Entity> = (opts: Opts) => Promise<Result<E>>;
13+
export type Signature<E extends Entity> = (opts: Opts<E>) => Promise<Result<E>>;
1214

1315
export default Signature;

Diff for: src/signatures/PatchEntity.ts

+2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import Entity from '../types/Entity';
2+
import Filter from '../types/Filter';
23

34
export interface Opts<E extends Entity> {
45
readonly id: string;
56
readonly patch: Partial<E>;
7+
readonly filter?: Filter<E>;
68
}
79

810
export interface Result<E extends Entity> {

Diff for: src/signatures/RemoveEntities.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import Entity from '../types/Entity';
22
import Filter from '../types/Filter';
33

44
export interface Opts<E extends Entity> {
5-
readonly filter: Filter<E>;
5+
readonly filter?: Filter<E>;
66
}
77

88
export type Result = void;

Diff for: src/signatures/RemoveEntity.ts

+6-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
1-
export interface Opts {
1+
import Entity from '../types/Entity';
2+
import Filter from '../types/Filter';
3+
4+
export interface Opts<E extends Entity> {
25
readonly id: string;
6+
readonly filter?: Filter<E>;
37
}
48

59
export type Result = void;
610

7-
export type Signature = (opts: Opts) => Promise<Result>;
11+
export type Signature<E extends Entity> = (opts: Opts<E>) => Promise<Result>;
812

913
export default Signature;

Diff for: src/signatures/OverwriteEntity.ts renamed to src/signatures/ReplaceEntity.ts

+2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import Entity from '../types/Entity';
2+
import Filter from '../types/Filter';
23

34
export interface Opts<E extends Entity> {
45
readonly id: string;
56
readonly entity: E;
7+
readonly filter?: Filter<E>;
68
}
79

810
export interface Result<E extends Entity> {

Diff for: src/signatures/UpsertEntity.ts

-14
This file was deleted.

Diff for: src/tests/getEntities/filterTest.ts

+3-8
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,21 @@
11
import 'mocha'; // tslint:disable-line:no-import-side-effect
22
import * as assert from 'power-assert';
33
import Facade from '../../Facade';
4-
import Pagination from '../../types/Pagination';
5-
import Sort from '../../types/Sort';
64
import filterTest, { firstEntity, secondEntity } from '../utils/filterTest';
75
import { TestEntity } from '../utils/testEntity';
86

97
export default (facade: Facade<TestEntity>) => {
10-
const sort: Sort<TestEntity> = {};
11-
const pagination: Pagination = { cursor: undefined, forward: true, limit: 2 };
12-
138
filterTest({
149
assertAllEntitiesFilter: async (filter) => {
15-
const actualResult = await facade.getEntities({ filter, sort, pagination });
10+
const actualResult = await facade.getEntities({ filter });
1611
assert.deepEqual(actualResult.entities, [firstEntity, secondEntity]);
1712
},
1813
assertFirstEntityFilter: async (filter) => {
19-
const actualResult = await facade.getEntities({ filter, sort, pagination });
14+
const actualResult = await facade.getEntities({ filter });
2015
assert.deepEqual(actualResult.entities, [firstEntity]);
2116
},
2217
assertNoEntityFilter: async (filter) => {
23-
const actualResult = await facade.getEntities({ filter, sort, pagination });
18+
const actualResult = await facade.getEntities({ filter });
2419
assert.deepEqual(actualResult.entities, []);
2520
},
2621
facade,

Diff for: src/tests/getEntities/paginationTest.ts

+8-6
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,14 @@ import 'mocha'; // tslint:disable-line:no-import-side-effect
22
import * as assert from 'power-assert';
33
import Facade from '../../Facade';
44
import Cursor from '../../types/Cursor';
5-
import Filter from '../../types/Filter';
65
import Pagination from '../../types/Pagination';
7-
import Sort from '../../types/Sort';
86
import { TestEntity, testEntity } from '../utils/testEntity';
97

108
export default (facade: Facade<TestEntity>) => {
119
const firstId = 'test_id_1';
1210
const secondId = 'test_id_2';
1311
const firstEntity = { ...testEntity, id: firstId };
1412
const secondEntity = { ...testEntity, id: secondId };
15-
const sort: Sort<TestEntity> = { id: true };
16-
const filter: Filter<TestEntity> = {};
1713

1814
const createTestEntities = async () => {
1915
await facade.createEntity({ id: firstId, entity: firstEntity });
@@ -22,13 +18,19 @@ export default (facade: Facade<TestEntity>) => {
2218

2319
const paginate = (cursor: Cursor, forward: boolean) => {
2420
const pagination: Pagination = { cursor, forward, limit: 1 };
25-
return facade.getEntities({ filter, sort, pagination });
21+
return facade.getEntities({ pagination });
2622
};
2723

24+
it('should return all entities when pagination is not defined', async () => {
25+
await createTestEntities();
26+
const result = await facade.getEntities({});
27+
assert.deepEqual(result.entities, [firstEntity]);
28+
});
29+
2830
it('should return first entity when there are two entities limitted to 1', async () => {
2931
await createTestEntities();
3032
const pagination: Pagination = { cursor: undefined, forward: true, limit: 1 };
31-
const result = await facade.getEntities({ filter, sort, pagination });
33+
const result = await facade.getEntities({ pagination });
3234
assert.deepEqual(result.entities, [firstEntity]);
3335
});
3436

0 commit comments

Comments
 (0)