Skip to content
This repository was archived by the owner on Nov 23, 2024. It is now read-only.

Commit c65bc15

Browse files
authored
Allow a shorthand of entityType for invalidates (#8)
1 parent 23fa79b commit c65bc15

File tree

8 files changed

+144
-21
lines changed

8 files changed

+144
-21
lines changed

examples/svelte-counter/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
"typescript": "^3.9.3"
2727
},
2828
"dependencies": {
29-
"@reduxjs/toolkit": "^1.4.0",
29+
"@reduxjs/toolkit": "https://pkg.csb.dev/reduxjs/redux-toolkit/commit/56994225/@reduxjs/toolkit",
3030
"sirv-cli": "^1.0.0"
3131
}
3232
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"template": "node"
3+
}

examples/svelte-counter/src/App.svelte

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
<script lang="ts">
22
import { onMount } from 'svelte';
3-
import { QueryStatus } from '../../../dist';
3+
import { QueryStatus } from '@rtk-incubator/simple-query/dist';
44
import { counterApi } from './services/counter';
55
import { store } from './store';
6+
import Counter from './Counter.svelte'
7+
8+
let counters = [] as number[];
69
710
const { incrementCount, decrementCount } = counterApi.mutationActions;
811
@@ -44,4 +47,11 @@
4447
<button on:click={() => store.dispatch(incrementCount(1, { track: false }))}>Increase</button>
4548
<button on:click={() => store.dispatch(decrementCount(1, { track: false }))}>Decrease</button>
4649
<button on:click={getCount} disabled={loading}>Refetch count</button>
50+
51+
<hr />
52+
<h3>Custom counters!</h3><button on:click={() => { counters = [...counters, counters.length + 1] }}>Add counter</button>
53+
54+
{#each counters as id}
55+
<Counter {id} />
56+
{/each}
4757
</main>
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
2+
<script lang="ts">
3+
export let id: number = null;
4+
import { onMount } from 'svelte';
5+
import { QueryStatus } from '@rtk-incubator/simple-query/dist';
6+
import { counterApi } from './services/counter';
7+
import { store } from './store';
8+
9+
const { incrementCountById, decrementCountById } = counterApi.mutationActions;
10+
11+
let incrementStatus, decrementStatus;
12+
$: ({ data, status: getStatus, error } = counterApi.selectors.query.getCountById(id)($store));
13+
$: ({ status: incrementStatus } = counterApi.selectors.query.getCountById(id)($store));
14+
$: ({ status: decrementStatus } = counterApi.selectors.query.getCountById(id)($store));
15+
16+
$: loading = [incrementStatus, decrementStatus, getStatus].some(status => status === QueryStatus.pending);
17+
18+
onMount(() => {
19+
store.dispatch(counterApi.queryActions.getCountById(id));
20+
});
21+
</script>
22+
23+
<style>
24+
main {
25+
padding: 0.5em;
26+
}
27+
28+
.count {
29+
color: #a74524;
30+
text-transform: uppercase;
31+
font-size: 2em;
32+
font-weight: 100;
33+
margin-right: 20px;
34+
}
35+
36+
</style>
37+
38+
<main>
39+
<span class="count">{data?.count || 0}</span>
40+
<button on:click={() => store.dispatch(incrementCountById({ id, amount: 1 }, { track: false }))} disabled={loading}>Increase</button>
41+
<button on:click={() => store.dispatch(decrementCountById({ id, amount: 1 }, { track: false }))} disabled={loading}>Decrease</button>
42+
<small>(id: {id})</small>
43+
44+
</main>

examples/svelte-counter/src/mocks/handlers.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import { rest } from 'msw';
33
// high tech in-memory storage
44
let count = 0;
55

6+
let counters = {};
7+
68
export const handlers = [
79
rest.put<{ amount: number }>('/increment', (req, res, ctx) => {
810
const { amount } = req.body;
@@ -19,4 +21,35 @@ export const handlers = [
1921
rest.get('/count', (req, res, ctx) => {
2022
return res(ctx.json({ count }));
2123
}),
24+
rest.get('/:id', (req, res, ctx) => {
25+
const { id } = req.params;
26+
27+
const count = counters[id] || (counters[id] = 0);
28+
29+
return res(ctx.json({ count }));
30+
}),
31+
rest.put<{ amount: number }>('/:id/increment', (req, res, ctx) => {
32+
const { amount } = req.body;
33+
const { id } = req.params;
34+
35+
if (typeof counters[id] === 'undefined') {
36+
return res(ctx.json({ message: 'Counter not found' }), ctx.status(402));
37+
}
38+
39+
const count = (counters[id] = counters[id] + amount);
40+
41+
return res(ctx.json({ count }));
42+
}),
43+
rest.put<{ amount: number }>('/:id/decrement', (req, res, ctx) => {
44+
const { amount } = req.body;
45+
const { id } = req.params;
46+
47+
if (typeof counters[id] === 'undefined') {
48+
return res(ctx.json({ message: 'Counter not found' }), ctx.status(402));
49+
}
50+
51+
const count = (counters[id] = counters[id] - amount);
52+
53+
return res(ctx.json({ count }));
54+
}),
2255
];

examples/svelte-counter/src/services/counter.ts

Lines changed: 42 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,24 +10,52 @@ export const counterApi = createApi({
1010
entityTypes: ['Counter'],
1111
endpoints: (build) => ({
1212
getCount: build.query<CountResponse, void>({
13-
query: () => `count`,
14-
provides: [{ type: 'Counter' }],
13+
query: () => 'count',
14+
provides: ['Counter'],
15+
}),
16+
getCountById: build.query<CountResponse, number>({
17+
query: (id: number) => `${id}`,
18+
provides: (_, id) => [{ type: 'Counter', id }],
1519
}),
1620
incrementCount: build.mutation<CountResponse, number>({
17-
query: (amount) => ({
18-
url: `increment`,
19-
method: 'PUT',
20-
body: JSON.stringify({ amount }),
21-
}),
22-
invalidates: [{ type: 'Counter' }],
21+
query(amount) {
22+
return {
23+
url: `increment`,
24+
method: 'PUT',
25+
body: JSON.stringify({ amount }),
26+
};
27+
},
28+
invalidates: ['Counter'],
29+
}),
30+
incrementCountById: build.mutation<CountResponse, { id: number; amount: number }>({
31+
query({ id, amount }) {
32+
return {
33+
url: `${id}/increment`,
34+
method: 'PUT',
35+
body: JSON.stringify({ amount }),
36+
};
37+
},
38+
invalidates: (_, { id }) => [{ type: 'Counter', id }],
2339
}),
2440
decrementCount: build.mutation<CountResponse, number>({
25-
query: (amount) => ({
26-
url: `decrement`,
27-
method: 'PUT',
28-
body: JSON.stringify({ amount }),
29-
}),
30-
invalidates: [{ type: 'Counter' }],
41+
query(amount) {
42+
return {
43+
url: `decrement`,
44+
method: 'PUT',
45+
body: JSON.stringify({ amount }),
46+
};
47+
},
48+
invalidates: ['Counter'],
49+
}),
50+
decrementCountById: build.mutation<CountResponse, { id: number; amount: number }>({
51+
query({ id, amount }) {
52+
return {
53+
url: `${id}/decrement`,
54+
method: 'PUT',
55+
body: JSON.stringify({ amount }),
56+
};
57+
},
58+
invalidates: (_, { id }) => [{ type: 'Counter', id }],
3159
}),
3260
}),
3361
});

src/buildMiddleware.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ export function buildMiddleware<Definitions extends EndpointDefinitions, Reducer
3737
const invalidateEntities = calculateProvidedBy(
3838
endpointDefinitions[action.meta.arg.endpoint].invalidates,
3939
action.payload,
40-
state.mutations[action.meta.arg.endpoint]?.[action.meta.requestId]?.arg
40+
action.meta.arg.arg
4141
);
4242
const toInvalidate: { [endpoint: string]: Set<string> } = {};
4343
for (const entity of invalidateEntities) {

src/endpointDefinitions.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ export type GetResultDescriptionFn<EntityTypes extends string, ResultType, Query
1616
arg: QueryArg
1717
) => ReadonlyArray<EntityDescription<EntityTypes>>;
1818

19-
export type EntityDescription<EntityType> = { type: EntityType; id?: number | string };
19+
export type FullEntityDescription<EntityType> = { type: EntityType; id?: number | string };
20+
export type EntityDescription<EntityType> = EntityType | FullEntityDescription<EntityType>;
2021
export type ResultDescription<EntityTypes extends string, ResultType, QueryArg> =
2122
| ReadonlyArray<EntityDescription<EntityTypes>>
2223
| GetResultDescriptionFn<EntityTypes, ResultType, QueryArg>;
@@ -64,16 +65,20 @@ export function calculateProvidedBy<ResultType, QueryArg, D extends ResultDescri
6465
description: D | undefined,
6566
result: ResultType,
6667
queryArg: QueryArg
67-
): readonly EntityDescription<string>[] {
68+
): readonly FullEntityDescription<string>[] {
6869
if (isFunction(description)) {
69-
return description(result, queryArg);
70+
return description(result, queryArg).map(expandEntityDescription);
7071
}
7172
if (Array.isArray(description)) {
72-
return description;
73+
return description.map(expandEntityDescription);
7374
}
7475
return [];
7576
}
7677

7778
function isFunction<T>(t: T): t is Extract<T, Function> {
7879
return typeof t === 'function';
7980
}
81+
82+
function expandEntityDescription(description: EntityDescription<string>): FullEntityDescription<string> {
83+
return typeof description === 'string' ? { type: description } : description;
84+
}

0 commit comments

Comments
 (0)