@data-client/core 0.10.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/dist/index.js +122 -89
- package/dist/index.umd.min.js +1 -1
- package/legacy/actionTypes.js +1 -1
- package/legacy/actions.js +1 -1
- package/legacy/controller/AbortOptimistic.js +2 -0
- package/legacy/controller/Controller.js +108 -76
- package/legacy/controller/createExpireAll.js +1 -1
- package/legacy/controller/createFetch.js +1 -1
- package/legacy/controller/createInvalidate.js +1 -1
- package/legacy/controller/createInvalidateAll.js +1 -1
- package/legacy/controller/createOptimistic.js +1 -1
- package/legacy/controller/createReset.js +1 -1
- package/legacy/controller/createSet.js +1 -1
- package/legacy/controller/createSubscription.js +1 -1
- package/legacy/controller/ensurePojo.js +1 -1
- package/legacy/controller/types.js +1 -1
- package/legacy/index.js +1 -1
- package/legacy/internal.js +2 -2
- package/legacy/manager/ConnectionListener.js +1 -1
- package/legacy/manager/DefaultConnectionListener.js +1 -1
- package/legacy/manager/DevtoolsManager.js +1 -1
- package/legacy/manager/LogoutManager.js +1 -1
- package/legacy/manager/NetworkManager.js +1 -1
- package/legacy/manager/PollingSubscription.js +1 -1
- package/legacy/manager/SubscriptionManager.js +1 -1
- package/legacy/manager/applyManager.js +1 -1
- package/legacy/manager/devtoolsTypes.js +1 -1
- package/legacy/manager/index.js +1 -1
- package/legacy/middlewareTypes.js +1 -1
- package/legacy/next/index.js +1 -1
- package/legacy/state/RIC.js +1 -1
- package/legacy/state/reducer/createReducer.js +4 -4
- package/legacy/state/reducer/expireReducer.js +1 -1
- package/legacy/state/reducer/fetchReducer.js +1 -1
- package/legacy/state/reducer/invalidateReducer.js +5 -5
- package/legacy/state/reducer/setReducer.js +7 -7
- package/legacy/state/selectMeta.js +1 -1
- package/legacy/types.js +1 -1
- package/lib/actionTypes.js +1 -1
- package/lib/actions.d.ts +1 -1
- package/lib/actions.d.ts.map +1 -1
- package/lib/actions.js +1 -1
- package/lib/controller/AbortOptimistic.d.ts +3 -0
- package/lib/controller/AbortOptimistic.d.ts.map +1 -0
- package/lib/controller/AbortOptimistic.js +2 -0
- package/lib/controller/Controller.d.ts +36 -11
- package/lib/controller/Controller.d.ts.map +1 -1
- package/lib/controller/Controller.js +108 -76
- package/lib/controller/createExpireAll.js +1 -1
- package/lib/controller/createFetch.js +1 -1
- package/lib/controller/createInvalidate.js +1 -1
- package/lib/controller/createInvalidateAll.js +1 -1
- package/lib/controller/createOptimistic.js +1 -1
- package/lib/controller/createReset.js +1 -1
- package/lib/controller/createSet.js +1 -1
- package/lib/controller/createSubscription.js +1 -1
- package/lib/controller/ensurePojo.js +1 -1
- package/lib/controller/types.js +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -1
- package/lib/internal.d.ts +1 -1
- package/lib/internal.d.ts.map +1 -1
- package/lib/internal.js +2 -2
- package/lib/manager/ConnectionListener.js +1 -1
- package/lib/manager/DefaultConnectionListener.js +1 -1
- package/lib/manager/DevtoolsManager.js +1 -1
- package/lib/manager/LogoutManager.js +1 -1
- package/lib/manager/NetworkManager.js +1 -1
- package/lib/manager/PollingSubscription.js +1 -1
- package/lib/manager/SubscriptionManager.js +1 -1
- package/lib/manager/applyManager.js +1 -1
- package/lib/manager/devtoolsTypes.js +1 -1
- package/lib/manager/index.js +1 -1
- package/lib/middlewareTypes.js +1 -1
- package/lib/next/index.js +1 -1
- package/lib/state/RIC.js +1 -1
- package/lib/state/reducer/createReducer.js +4 -4
- package/lib/state/reducer/expireReducer.d.ts +1 -1
- package/lib/state/reducer/expireReducer.js +1 -1
- package/lib/state/reducer/fetchReducer.js +1 -1
- package/lib/state/reducer/invalidateReducer.d.ts +1 -1
- package/lib/state/reducer/invalidateReducer.js +6 -6
- package/lib/state/reducer/setReducer.d.ts.map +1 -1
- package/lib/state/reducer/setReducer.js +8 -8
- package/lib/state/selectMeta.js +1 -1
- package/lib/types.d.ts +1 -1
- package/lib/types.d.ts.map +1 -1
- package/lib/types.js +1 -1
- package/package.json +3 -3
- package/src/actions.ts +1 -1
- package/src/controller/AbortOptimistic.ts +1 -0
- package/src/controller/Controller.ts +185 -63
- package/src/controller/__tests__/Controller.ts +2 -4
- package/src/controller/__tests__/__snapshots__/get.ts.snap +120 -0
- package/src/controller/__tests__/get.ts +285 -0
- package/src/controller/__tests__/getResponse.ts +2 -2
- package/src/index.ts +2 -1
- package/src/internal.ts +1 -1
- package/src/state/__tests__/__snapshots__/reducer.ts.snap +4 -4
- package/src/state/__tests__/reducer.ts +25 -25
- package/src/state/reducer/createReducer.ts +3 -3
- package/src/state/reducer/invalidateReducer.ts +4 -4
- package/src/state/reducer/setReducer.ts +7 -6
- package/src/types.ts +3 -1
- package/ts3.4/actions.d.ts +1 -1
- package/ts3.4/controller/AbortOptimistic.d.ts +3 -0
- package/ts3.4/controller/Controller.d.ts +47 -19
- package/ts3.4/index.d.ts +1 -1
- package/ts3.4/internal.d.ts +1 -1
- package/ts3.4/state/reducer/expireReducer.d.ts +1 -1
- package/ts3.4/state/reducer/invalidateReducer.d.ts +1 -1
- package/ts3.4/types.d.ts +1 -1
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import { Endpoint, Entity } from '@data-client/endpoint';
|
|
2
1
|
import { normalize } from '@data-client/normalizr';
|
|
3
2
|
import { CoolerArticleResource } from '__tests__/new';
|
|
4
3
|
import { createEntityMeta } from '__tests__/utils';
|
|
5
4
|
|
|
6
|
-
import { ExpiryStatus } from '../..';
|
|
7
5
|
import { initialState } from '../../state/reducer/createReducer';
|
|
8
6
|
import Controller from '../Controller';
|
|
9
7
|
|
|
@@ -45,7 +43,7 @@ describe('Controller', () => {
|
|
|
45
43
|
const state = {
|
|
46
44
|
...initialState,
|
|
47
45
|
entities,
|
|
48
|
-
|
|
46
|
+
endpoints: {
|
|
49
47
|
[fetchKey]: result,
|
|
50
48
|
},
|
|
51
49
|
entityMeta: createEntityMeta(entities),
|
|
@@ -82,7 +80,7 @@ describe('Controller', () => {
|
|
|
82
80
|
const state = {
|
|
83
81
|
...initialState,
|
|
84
82
|
entities,
|
|
85
|
-
|
|
83
|
+
endpoints: {
|
|
86
84
|
[fetchKey]: result,
|
|
87
85
|
},
|
|
88
86
|
entityMeta: createEntityMeta(entities),
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
+
|
|
3
|
+
exports[`Controller.get() Query+All based on args 1`] = `
|
|
4
|
+
[
|
|
5
|
+
Tacos {
|
|
6
|
+
"id": "1",
|
|
7
|
+
"type": "foo",
|
|
8
|
+
},
|
|
9
|
+
]
|
|
10
|
+
`;
|
|
11
|
+
|
|
12
|
+
exports[`Controller.get() Query+All based on args 2`] = `
|
|
13
|
+
[
|
|
14
|
+
Tacos {
|
|
15
|
+
"id": "1",
|
|
16
|
+
"type": "foo",
|
|
17
|
+
},
|
|
18
|
+
Tacos {
|
|
19
|
+
"id": "2",
|
|
20
|
+
"type": "bar",
|
|
21
|
+
},
|
|
22
|
+
]
|
|
23
|
+
`;
|
|
24
|
+
|
|
25
|
+
exports[`Controller.get() Query+All based on args 3`] = `
|
|
26
|
+
[
|
|
27
|
+
Tacos {
|
|
28
|
+
"id": "2",
|
|
29
|
+
"type": "bar",
|
|
30
|
+
},
|
|
31
|
+
Tacos {
|
|
32
|
+
"id": "3",
|
|
33
|
+
"name": "thing3",
|
|
34
|
+
"type": "bar",
|
|
35
|
+
},
|
|
36
|
+
]
|
|
37
|
+
`;
|
|
38
|
+
|
|
39
|
+
exports[`Controller.get() Union based on args 1`] = `
|
|
40
|
+
User {
|
|
41
|
+
"id": "1",
|
|
42
|
+
"type": "users",
|
|
43
|
+
"username": "bob",
|
|
44
|
+
}
|
|
45
|
+
`;
|
|
46
|
+
|
|
47
|
+
exports[`Controller.get() Union based on args 2`] = `
|
|
48
|
+
Group {
|
|
49
|
+
"groupname": "fast",
|
|
50
|
+
"id": "2",
|
|
51
|
+
"memberCount": 5,
|
|
52
|
+
"type": "groups",
|
|
53
|
+
}
|
|
54
|
+
`;
|
|
55
|
+
|
|
56
|
+
exports[`Controller.get() query All should get all entities 1`] = `
|
|
57
|
+
[
|
|
58
|
+
Tacos {
|
|
59
|
+
"id": "1",
|
|
60
|
+
"type": "foo",
|
|
61
|
+
},
|
|
62
|
+
Tacos {
|
|
63
|
+
"id": "2",
|
|
64
|
+
"type": "bar",
|
|
65
|
+
},
|
|
66
|
+
]
|
|
67
|
+
`;
|
|
68
|
+
|
|
69
|
+
exports[`Controller.get() query All should include new entities when added 1`] = `
|
|
70
|
+
[
|
|
71
|
+
Tacos {
|
|
72
|
+
"id": "1",
|
|
73
|
+
"type": "foo",
|
|
74
|
+
},
|
|
75
|
+
Tacos {
|
|
76
|
+
"id": "2",
|
|
77
|
+
"type": "bar",
|
|
78
|
+
},
|
|
79
|
+
Tacos {
|
|
80
|
+
"id": "3",
|
|
81
|
+
"type": "extra",
|
|
82
|
+
},
|
|
83
|
+
]
|
|
84
|
+
`;
|
|
85
|
+
|
|
86
|
+
exports[`Controller.get() query Collection based on args 1`] = `
|
|
87
|
+
[
|
|
88
|
+
Tacos {
|
|
89
|
+
"id": "1",
|
|
90
|
+
"type": "foo",
|
|
91
|
+
},
|
|
92
|
+
]
|
|
93
|
+
`;
|
|
94
|
+
|
|
95
|
+
exports[`Controller.get() query Collection based on args 2`] = `
|
|
96
|
+
[
|
|
97
|
+
Tacos {
|
|
98
|
+
"id": "1",
|
|
99
|
+
"type": "foo",
|
|
100
|
+
},
|
|
101
|
+
Tacos {
|
|
102
|
+
"id": "2",
|
|
103
|
+
"type": "bar",
|
|
104
|
+
},
|
|
105
|
+
]
|
|
106
|
+
`;
|
|
107
|
+
|
|
108
|
+
exports[`Controller.get() query Entity based on index 1`] = `
|
|
109
|
+
User {
|
|
110
|
+
"id": "1",
|
|
111
|
+
"username": "bob",
|
|
112
|
+
}
|
|
113
|
+
`;
|
|
114
|
+
|
|
115
|
+
exports[`Controller.get() query Entity based on pk 1`] = `
|
|
116
|
+
Tacos {
|
|
117
|
+
"id": "1",
|
|
118
|
+
"type": "foo",
|
|
119
|
+
}
|
|
120
|
+
`;
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
import { Entity, schema } from '@data-client/endpoint';
|
|
2
|
+
|
|
3
|
+
import { initialState } from '../../state/reducer/createReducer';
|
|
4
|
+
import Controller from '../Controller';
|
|
5
|
+
|
|
6
|
+
describe('Controller.get()', () => {
|
|
7
|
+
class Tacos extends Entity {
|
|
8
|
+
type = '';
|
|
9
|
+
id = '';
|
|
10
|
+
pk() {
|
|
11
|
+
return this.id;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
const TacoList = new schema.Collection([Tacos]);
|
|
15
|
+
const entities = {
|
|
16
|
+
Tacos: {
|
|
17
|
+
1: { id: '1', type: 'foo' },
|
|
18
|
+
2: { id: '2', type: 'bar' },
|
|
19
|
+
},
|
|
20
|
+
[TacoList.key]: {
|
|
21
|
+
[TacoList.pk(undefined, undefined, '', [{ type: 'foo' }])]: ['1'],
|
|
22
|
+
[TacoList.pk(undefined, undefined, '', [{ type: 'bar' }])]: ['2'],
|
|
23
|
+
[TacoList.pk(undefined, undefined, '', [])]: ['1', '2'],
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
it('query Entity based on pk', () => {
|
|
28
|
+
const controller = new Controller();
|
|
29
|
+
const state = {
|
|
30
|
+
...initialState,
|
|
31
|
+
entities,
|
|
32
|
+
};
|
|
33
|
+
const taco = controller.get(Tacos, { id: '1' }, state);
|
|
34
|
+
expect(taco).toBeDefined();
|
|
35
|
+
expect(taco).toBeInstanceOf(Tacos);
|
|
36
|
+
expect(taco).toMatchSnapshot();
|
|
37
|
+
const taco2 = controller.get(Tacos, { id: '2' }, state);
|
|
38
|
+
expect(taco2).toBeDefined();
|
|
39
|
+
expect(taco2).toBeInstanceOf(Tacos);
|
|
40
|
+
expect(taco2).not.toEqual(taco);
|
|
41
|
+
// should maintain referential equality
|
|
42
|
+
expect(taco).toBe(controller.get(Tacos, { id: '1' }, state));
|
|
43
|
+
|
|
44
|
+
// @ts-expect-error
|
|
45
|
+
() => controller.get(Tacos, { id: { bob: 5 } }, state);
|
|
46
|
+
// @ts-expect-error
|
|
47
|
+
expect(controller.get(Tacos, 5, state)).toBeUndefined();
|
|
48
|
+
// @ts-expect-error
|
|
49
|
+
() => controller.get(Tacos, { doesnotexist: 5 }, state);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it('query Entity based on index', () => {
|
|
53
|
+
class User extends Entity {
|
|
54
|
+
id = '';
|
|
55
|
+
username = '';
|
|
56
|
+
|
|
57
|
+
pk() {
|
|
58
|
+
return this.id;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
static indexes = ['username'] as const;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const controller = new Controller();
|
|
65
|
+
const state = {
|
|
66
|
+
...initialState,
|
|
67
|
+
entities: {
|
|
68
|
+
User: {
|
|
69
|
+
'1': { id: '1', username: 'bob' },
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
indexes: {
|
|
73
|
+
User: {
|
|
74
|
+
username: {
|
|
75
|
+
bob: '1',
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
const bob = controller.get(User, { username: 'bob' }, state);
|
|
82
|
+
expect(bob).toBeDefined();
|
|
83
|
+
expect(bob).toBeInstanceOf(User);
|
|
84
|
+
expect(bob).toMatchSnapshot();
|
|
85
|
+
// should be same as id lookup
|
|
86
|
+
expect(bob).toBe(controller.get(User, { id: '1' }, state));
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('query Collection based on args', () => {
|
|
90
|
+
const controller = new Controller();
|
|
91
|
+
const state = {
|
|
92
|
+
...initialState,
|
|
93
|
+
entities,
|
|
94
|
+
};
|
|
95
|
+
const tacos = controller.get(TacoList, { type: 'foo' }, state);
|
|
96
|
+
expect(tacos).toBeDefined();
|
|
97
|
+
expect(tacos?.[0]).toBeInstanceOf(Tacos);
|
|
98
|
+
expect(tacos).toMatchSnapshot();
|
|
99
|
+
const tacosBars = controller.get(TacoList, { type: 'bar' }, state);
|
|
100
|
+
expect(tacosBars).toBeDefined();
|
|
101
|
+
expect(tacosBars?.[0]).toBeInstanceOf(Tacos);
|
|
102
|
+
expect(tacosBars).not.toEqual(tacos);
|
|
103
|
+
// should maintain referential equality
|
|
104
|
+
expect(tacos).toBe(controller.get(TacoList, { type: 'foo' }, state));
|
|
105
|
+
|
|
106
|
+
const allTacos = controller.get(TacoList, state);
|
|
107
|
+
expect(allTacos).toBeDefined();
|
|
108
|
+
expect(allTacos).toHaveLength(2);
|
|
109
|
+
expect(allTacos).toMatchSnapshot();
|
|
110
|
+
|
|
111
|
+
// @ts-expect-error
|
|
112
|
+
() => controller.get(TacoList, 5, state);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
describe('query All', () => {
|
|
116
|
+
const controller = new Controller();
|
|
117
|
+
const state = {
|
|
118
|
+
...initialState,
|
|
119
|
+
entities,
|
|
120
|
+
};
|
|
121
|
+
const AllTacos = new schema.All(Tacos);
|
|
122
|
+
|
|
123
|
+
it('should get all entities', () => {
|
|
124
|
+
const allTacos = controller.get(AllTacos, state);
|
|
125
|
+
expect(allTacos).toBeDefined();
|
|
126
|
+
expect(allTacos).toHaveLength(2);
|
|
127
|
+
expect(allTacos).toMatchSnapshot();
|
|
128
|
+
|
|
129
|
+
// TODO: @ts-expect-error (we have a hack to make this not break other things now)
|
|
130
|
+
() => controller.get(AllTacos, 5, state);
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it('should maintain referential equality', () => {
|
|
134
|
+
const allTacos = controller.get(AllTacos, state);
|
|
135
|
+
expect(allTacos).toStrictEqual(controller.get(TacoList, state));
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
it('should include new entities when added', () => {
|
|
139
|
+
controller.get(AllTacos, state);
|
|
140
|
+
const tacosWithExtra = controller.get(AllTacos, {
|
|
141
|
+
...state,
|
|
142
|
+
entities: {
|
|
143
|
+
...entities,
|
|
144
|
+
Tacos: {
|
|
145
|
+
...entities.Tacos,
|
|
146
|
+
3: { id: '3', type: 'extra' },
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
});
|
|
150
|
+
expect(tacosWithExtra).toBeDefined();
|
|
151
|
+
expect(tacosWithExtra).toHaveLength(3);
|
|
152
|
+
expect(tacosWithExtra).toMatchSnapshot();
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
it('Query+All based on args', () => {
|
|
157
|
+
const controller = new Controller();
|
|
158
|
+
const state = {
|
|
159
|
+
...initialState,
|
|
160
|
+
entities,
|
|
161
|
+
};
|
|
162
|
+
const queryTacos = new schema.Query(
|
|
163
|
+
new schema.All(Tacos),
|
|
164
|
+
(tacos, { type }: { type?: string } = {}) => {
|
|
165
|
+
if (!type) return tacos;
|
|
166
|
+
return tacos.filter(taco => taco.type === type);
|
|
167
|
+
},
|
|
168
|
+
);
|
|
169
|
+
|
|
170
|
+
const tacos = controller.get(queryTacos, { type: 'foo' }, state);
|
|
171
|
+
expect(tacos).toBeDefined();
|
|
172
|
+
expect(tacos?.[0]).toBeInstanceOf(Tacos);
|
|
173
|
+
expect(tacos).toMatchSnapshot();
|
|
174
|
+
const tacosBars = controller.get(queryTacos, { type: 'bar' }, state);
|
|
175
|
+
expect(tacosBars).toBeDefined();
|
|
176
|
+
expect(tacosBars?.[0]).toBeInstanceOf(Tacos);
|
|
177
|
+
expect(tacosBars).not.toEqual(tacos);
|
|
178
|
+
// should maintain referential equality
|
|
179
|
+
expect(tacos).toBe(controller.get(queryTacos, { type: 'foo' }, state));
|
|
180
|
+
|
|
181
|
+
const allTacos = controller.get(queryTacos, state);
|
|
182
|
+
expect(allTacos).toBeDefined();
|
|
183
|
+
expect(allTacos).toHaveLength(2);
|
|
184
|
+
expect(allTacos).toMatchSnapshot();
|
|
185
|
+
|
|
186
|
+
// @ts-expect-error
|
|
187
|
+
() => controller.get(queryTacos, 5, state);
|
|
188
|
+
|
|
189
|
+
const tacosWithExtra = controller.get(
|
|
190
|
+
queryTacos,
|
|
191
|
+
{ type: 'bar' },
|
|
192
|
+
{
|
|
193
|
+
...state,
|
|
194
|
+
entities: {
|
|
195
|
+
...entities,
|
|
196
|
+
Tacos: {
|
|
197
|
+
...entities.Tacos,
|
|
198
|
+
3: { id: '3', type: 'bar', name: 'thing3' },
|
|
199
|
+
},
|
|
200
|
+
},
|
|
201
|
+
},
|
|
202
|
+
);
|
|
203
|
+
expect(tacosWithExtra).toBeDefined();
|
|
204
|
+
expect(tacosWithExtra).toHaveLength(2);
|
|
205
|
+
expect(tacosWithExtra).toMatchSnapshot();
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
it('Query+Collection based on args', () => {
|
|
209
|
+
const controller = new Controller();
|
|
210
|
+
const state = {
|
|
211
|
+
...initialState,
|
|
212
|
+
entities,
|
|
213
|
+
};
|
|
214
|
+
const tacoCount = new schema.Query(TacoList, tacos => {
|
|
215
|
+
return tacos?.length ?? 0;
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
expect(controller.get(tacoCount, { type: 'foo' }, state)).toBe(1);
|
|
219
|
+
expect(controller.get(tacoCount, { type: 'bar' }, state)).toBe(1);
|
|
220
|
+
expect(controller.get(tacoCount, state)).toBe(2);
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
it('Union based on args', () => {
|
|
224
|
+
class IDEntity extends Entity {
|
|
225
|
+
id: string = '';
|
|
226
|
+
pk() {
|
|
227
|
+
return this.id;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
class User extends IDEntity {
|
|
231
|
+
type = 'user';
|
|
232
|
+
username: string = '';
|
|
233
|
+
}
|
|
234
|
+
class Group extends IDEntity {
|
|
235
|
+
type = 'group';
|
|
236
|
+
groupname: string = '';
|
|
237
|
+
memberCount = 0;
|
|
238
|
+
}
|
|
239
|
+
const queryPerson = new schema.Union(
|
|
240
|
+
{
|
|
241
|
+
users: User,
|
|
242
|
+
groups: Group,
|
|
243
|
+
},
|
|
244
|
+
'type',
|
|
245
|
+
);
|
|
246
|
+
const controller = new Controller();
|
|
247
|
+
const state = {
|
|
248
|
+
...initialState,
|
|
249
|
+
entities: {
|
|
250
|
+
User: {
|
|
251
|
+
'1': { id: '1', type: 'users', username: 'bob' },
|
|
252
|
+
},
|
|
253
|
+
Group: {
|
|
254
|
+
'2': { id: '2', type: 'groups', groupname: 'fast', memberCount: 5 },
|
|
255
|
+
},
|
|
256
|
+
},
|
|
257
|
+
};
|
|
258
|
+
const user = controller.get(queryPerson, { id: '1', type: 'users' }, state);
|
|
259
|
+
expect(user).toBeDefined();
|
|
260
|
+
expect(user).toBeInstanceOf(User);
|
|
261
|
+
expect(user).toMatchSnapshot();
|
|
262
|
+
const group = controller.get(
|
|
263
|
+
queryPerson,
|
|
264
|
+
{ id: '2', type: 'groups' },
|
|
265
|
+
state,
|
|
266
|
+
);
|
|
267
|
+
expect(group).toBeDefined();
|
|
268
|
+
expect(group).toBeInstanceOf(Group);
|
|
269
|
+
expect(group).toMatchSnapshot();
|
|
270
|
+
|
|
271
|
+
// should maintain referential equality
|
|
272
|
+
expect(user).toBe(
|
|
273
|
+
controller.get(queryPerson, { id: '1', type: 'users' }, state),
|
|
274
|
+
);
|
|
275
|
+
|
|
276
|
+
// @ts-expect-error
|
|
277
|
+
() => controller.get(queryPerson, { id: { bob: 5 } }, state);
|
|
278
|
+
// @ts-expect-error
|
|
279
|
+
expect(controller.get(queryPerson, 5, state)).toBeUndefined();
|
|
280
|
+
// @ts-expect-error
|
|
281
|
+
() => controller.get(queryPerson, { doesnotexist: 5 }, state);
|
|
282
|
+
// @ts-expect-error
|
|
283
|
+
() => controller.get(queryPerson, { id: '1', doesnotexist: 5 }, state);
|
|
284
|
+
});
|
|
285
|
+
});
|
|
@@ -39,7 +39,7 @@ describe('Controller.getResponse()', () => {
|
|
|
39
39
|
const state = {
|
|
40
40
|
...initialState,
|
|
41
41
|
entities,
|
|
42
|
-
|
|
42
|
+
endpoints: {
|
|
43
43
|
[ep.key()]: {
|
|
44
44
|
data: ['1', '2'],
|
|
45
45
|
},
|
|
@@ -84,7 +84,7 @@ describe('Controller.getResponse()', () => {
|
|
|
84
84
|
const state = {
|
|
85
85
|
...initialState,
|
|
86
86
|
entities,
|
|
87
|
-
|
|
87
|
+
endpoints: {
|
|
88
88
|
[ep.key()]: {
|
|
89
89
|
data: ['1', '2'],
|
|
90
90
|
},
|
package/src/index.ts
CHANGED
|
@@ -13,13 +13,14 @@ export type {
|
|
|
13
13
|
EndpointInterface,
|
|
14
14
|
EntityInterface,
|
|
15
15
|
ResolveType,
|
|
16
|
-
DenormalizeCache,
|
|
17
16
|
DenormalizeNullable,
|
|
18
17
|
Denormalize,
|
|
19
18
|
Normalize,
|
|
20
19
|
NormalizeNullable,
|
|
21
20
|
FetchFunction,
|
|
22
21
|
EndpointExtraOptions,
|
|
22
|
+
Queryable,
|
|
23
|
+
SchemaArgs,
|
|
23
24
|
} from '@data-client/normalizr';
|
|
24
25
|
export { ExpiryStatus } from '@data-client/normalizr';
|
|
25
26
|
export {
|
package/src/internal.ts
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
exports[`reducer should set error in meta for "set" 1`] = `
|
|
4
4
|
{
|
|
5
|
+
"endpoints": {},
|
|
5
6
|
"entities": {},
|
|
6
7
|
"entityMeta": {},
|
|
7
8
|
"indexes": {},
|
|
@@ -15,12 +16,14 @@ exports[`reducer should set error in meta for "set" 1`] = `
|
|
|
15
16
|
},
|
|
16
17
|
},
|
|
17
18
|
"optimistic": [],
|
|
18
|
-
"results": {},
|
|
19
19
|
}
|
|
20
20
|
`;
|
|
21
21
|
|
|
22
22
|
exports[`reducer singles should update state correctly 1`] = `
|
|
23
23
|
{
|
|
24
|
+
"endpoints": {
|
|
25
|
+
"http://test.com/article/20": "20",
|
|
26
|
+
},
|
|
24
27
|
"entities": {
|
|
25
28
|
"Article": {
|
|
26
29
|
"20": {
|
|
@@ -49,8 +52,5 @@ exports[`reducer singles should update state correctly 1`] = `
|
|
|
49
52
|
},
|
|
50
53
|
},
|
|
51
54
|
"optimistic": [],
|
|
52
|
-
"results": {
|
|
53
|
-
"http://test.com/article/20": "20",
|
|
54
|
-
},
|
|
55
55
|
}
|
|
56
56
|
`;
|
|
@@ -207,7 +207,7 @@ describe('reducer', () => {
|
|
|
207
207
|
});
|
|
208
208
|
});
|
|
209
209
|
|
|
210
|
-
it('mutate should never change
|
|
210
|
+
it('mutate should never change endpoints', () => {
|
|
211
211
|
const id = 20;
|
|
212
212
|
const payload = { id, title: 'hi', content: 'this is the content' };
|
|
213
213
|
const action: SetAction = {
|
|
@@ -224,10 +224,10 @@ describe('reducer', () => {
|
|
|
224
224
|
};
|
|
225
225
|
const iniState = {
|
|
226
226
|
...initialState,
|
|
227
|
-
|
|
227
|
+
endpoints: { abc: '5', [ArticleResource.get.key(payload)]: `${id}` },
|
|
228
228
|
};
|
|
229
229
|
const newState = reducer(iniState, action);
|
|
230
|
-
expect(newState.
|
|
230
|
+
expect(newState.endpoints).toStrictEqual(iniState.endpoints);
|
|
231
231
|
});
|
|
232
232
|
it('purge should delete entities', () => {
|
|
233
233
|
const id = 20;
|
|
@@ -256,10 +256,10 @@ describe('reducer', () => {
|
|
|
256
256
|
},
|
|
257
257
|
'5': undefined,
|
|
258
258
|
},
|
|
259
|
-
|
|
259
|
+
endpoints: { abc: '20' },
|
|
260
260
|
};
|
|
261
261
|
const newState = reducer(iniState, action);
|
|
262
|
-
expect(newState.
|
|
262
|
+
expect(newState.endpoints.abc).toBe(iniState.endpoints.abc);
|
|
263
263
|
const expectedEntities = { ...iniState.entities[Article.key] };
|
|
264
264
|
expectedEntities['20'] = INVALID;
|
|
265
265
|
expect(newState.entities[Article.key]).toEqual(expectedEntities);
|
|
@@ -277,8 +277,8 @@ describe('reducer', () => {
|
|
|
277
277
|
'10': PaginatedArticle.fromJS({ id: 10 }),
|
|
278
278
|
},
|
|
279
279
|
},
|
|
280
|
-
|
|
281
|
-
[PaginatedArticleResource.getList.key({})]: {
|
|
280
|
+
endpoints: {
|
|
281
|
+
[PaginatedArticleResource.getList.key({})]: { endpoints: ['10'] },
|
|
282
282
|
},
|
|
283
283
|
};
|
|
284
284
|
|
|
@@ -301,7 +301,7 @@ describe('reducer', () => {
|
|
|
301
301
|
);
|
|
302
302
|
const newState = reducer(iniState, action);
|
|
303
303
|
expect(
|
|
304
|
-
newState.
|
|
304
|
+
newState.endpoints[PaginatedArticleResource.getList.key({})],
|
|
305
305
|
).toStrictEqual({
|
|
306
306
|
results: ['10', '11', '12'],
|
|
307
307
|
});
|
|
@@ -328,7 +328,7 @@ describe('reducer', () => {
|
|
|
328
328
|
),
|
|
329
329
|
);
|
|
330
330
|
expect(
|
|
331
|
-
newState.
|
|
331
|
+
newState.endpoints[PaginatedArticleResource.getList.key({})],
|
|
332
332
|
).toStrictEqual({
|
|
333
333
|
results: ['11', '12', '10'],
|
|
334
334
|
});
|
|
@@ -342,7 +342,7 @@ describe('reducer', () => {
|
|
|
342
342
|
'10': PaginatedArticle.fromJS({ id: 10 }),
|
|
343
343
|
},
|
|
344
344
|
},
|
|
345
|
-
|
|
345
|
+
endpoints: {
|
|
346
346
|
[PaginatedArticleResource.getList.key({ admin: true })]: {
|
|
347
347
|
results: ['10'],
|
|
348
348
|
},
|
|
@@ -369,7 +369,7 @@ describe('reducer', () => {
|
|
|
369
369
|
),
|
|
370
370
|
);
|
|
371
371
|
expect(
|
|
372
|
-
newState.
|
|
372
|
+
newState.endpoints[
|
|
373
373
|
PaginatedArticleResource.getList.key({ admin: true })
|
|
374
374
|
],
|
|
375
375
|
).toStrictEqual({
|
|
@@ -400,7 +400,7 @@ describe('reducer', () => {
|
|
|
400
400
|
},
|
|
401
401
|
'5': undefined,
|
|
402
402
|
},
|
|
403
|
-
|
|
403
|
+
endpoints: { abc: '20' },
|
|
404
404
|
meta: {
|
|
405
405
|
'20': {
|
|
406
406
|
expiresAt: 500,
|
|
@@ -411,7 +411,7 @@ describe('reducer', () => {
|
|
|
411
411
|
},
|
|
412
412
|
};
|
|
413
413
|
const newState = reducer(iniState, action);
|
|
414
|
-
expect(newState.
|
|
414
|
+
expect(newState.endpoints).toEqual(iniState.endpoints);
|
|
415
415
|
expect(newState.entities).toBe(iniState.entities);
|
|
416
416
|
const expectedMeta = { ...iniState.meta };
|
|
417
417
|
expectedMeta['20'] = { expiresAt: 0, invalidated: true };
|
|
@@ -481,7 +481,7 @@ describe('reducer', () => {
|
|
|
481
481
|
[id]: Article.fromJS({}),
|
|
482
482
|
},
|
|
483
483
|
},
|
|
484
|
-
|
|
484
|
+
endpoints: {
|
|
485
485
|
[ArticleResource.get.url({ id })]: id,
|
|
486
486
|
},
|
|
487
487
|
};
|
|
@@ -509,7 +509,7 @@ describe('reducer', () => {
|
|
|
509
509
|
};
|
|
510
510
|
const iniState = {
|
|
511
511
|
...initialState,
|
|
512
|
-
|
|
512
|
+
endpoints: { abc: '5' },
|
|
513
513
|
};
|
|
514
514
|
const newState = reducer(iniState, action);
|
|
515
515
|
expect(newState).toBe(iniState);
|
|
@@ -524,7 +524,7 @@ describe('reducer', () => {
|
|
|
524
524
|
};
|
|
525
525
|
const iniState = {
|
|
526
526
|
...initialState,
|
|
527
|
-
|
|
527
|
+
endpoints: { abc: '5' },
|
|
528
528
|
};
|
|
529
529
|
const newState = reducer(iniState, action);
|
|
530
530
|
expect(newState).toBe(iniState);
|
|
@@ -556,10 +556,10 @@ describe('reducer', () => {
|
|
|
556
556
|
},
|
|
557
557
|
'5': undefined,
|
|
558
558
|
},
|
|
559
|
-
|
|
559
|
+
endpoints: { abc: '20' },
|
|
560
560
|
};
|
|
561
561
|
const newState = reducer(iniState, action);
|
|
562
|
-
expect(newState.
|
|
562
|
+
expect(newState.endpoints).toEqual({});
|
|
563
563
|
expect(newState.meta).toEqual({});
|
|
564
564
|
expect(newState.entities).toEqual({});
|
|
565
565
|
});
|
|
@@ -591,7 +591,7 @@ describe('reducer', () => {
|
|
|
591
591
|
'250': { date: 0, expiresAt: 10000, fetchedAt: 0 },
|
|
592
592
|
},
|
|
593
593
|
},
|
|
594
|
-
|
|
594
|
+
endpoints: { abc: '20' },
|
|
595
595
|
};
|
|
596
596
|
});
|
|
597
597
|
|
|
@@ -599,13 +599,13 @@ describe('reducer', () => {
|
|
|
599
599
|
const action: GCAction = {
|
|
600
600
|
type: GC_TYPE,
|
|
601
601
|
entities: [],
|
|
602
|
-
|
|
602
|
+
endpoints: [],
|
|
603
603
|
};
|
|
604
604
|
|
|
605
605
|
const newState = reducer(iniState, action);
|
|
606
606
|
expect(newState).toBe(iniState);
|
|
607
607
|
expect(Object.keys(newState.entities[Article.key] ?? {}).length).toBe(4);
|
|
608
|
-
expect(Object.keys(newState.
|
|
608
|
+
expect(Object.keys(newState.endpoints).length).toBe(1);
|
|
609
609
|
});
|
|
610
610
|
|
|
611
611
|
it('empty deleting entities should work', () => {
|
|
@@ -615,7 +615,7 @@ describe('reducer', () => {
|
|
|
615
615
|
[Article.key, '10'],
|
|
616
616
|
[Article.key, '250'],
|
|
617
617
|
],
|
|
618
|
-
|
|
618
|
+
endpoints: ['abc'],
|
|
619
619
|
};
|
|
620
620
|
|
|
621
621
|
const newState = reducer(iniState, action);
|
|
@@ -624,7 +624,7 @@ describe('reducer', () => {
|
|
|
624
624
|
expect(Object.keys(newState.entityMeta[Article.key] ?? {}).length).toBe(
|
|
625
625
|
2,
|
|
626
626
|
);
|
|
627
|
-
expect(Object.keys(newState.
|
|
627
|
+
expect(Object.keys(newState.endpoints).length).toBe(0);
|
|
628
628
|
});
|
|
629
629
|
|
|
630
630
|
it('empty deleting nonexistant things should passthrough', () => {
|
|
@@ -634,13 +634,13 @@ describe('reducer', () => {
|
|
|
634
634
|
[Article.key, '100000000'],
|
|
635
635
|
['sillythings', '10'],
|
|
636
636
|
],
|
|
637
|
-
|
|
637
|
+
endpoints: [],
|
|
638
638
|
};
|
|
639
639
|
|
|
640
640
|
const newState = reducer(iniState, action);
|
|
641
641
|
expect(newState).toBe(iniState);
|
|
642
642
|
expect(Object.keys(newState.entities[Article.key] ?? {}).length).toBe(4);
|
|
643
|
-
expect(Object.keys(newState.
|
|
643
|
+
expect(Object.keys(newState.endpoints).length).toBe(1);
|
|
644
644
|
});
|
|
645
645
|
});
|
|
646
646
|
});
|