@data-client/core 0.1.0 → 0.2.1
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/dist/index.js +134 -409
- package/dist/index.umd.min.js +1 -1
- package/dist/next.js +61 -101
- package/legacy/actionTypes.js +2 -2
- package/legacy/controller/Controller.js +276 -6
- package/legacy/controller/createFetch.js +3 -14
- package/legacy/controller/createInvalidate.js +1 -1
- package/legacy/controller/createInvalidateAll.js +1 -1
- package/legacy/controller/createOptimistic.js +1 -7
- package/legacy/controller/createReset.js +1 -1
- package/legacy/controller/createSet.js +31 -0
- package/legacy/controller/createSubscription.js +3 -7
- package/legacy/index.js +2 -5
- package/legacy/internal.js +2 -2
- package/legacy/manager/DevtoolsManager.js +2 -2
- package/legacy/manager/LogoutManager.js +2 -2
- package/legacy/manager/NetworkManager.js +28 -59
- package/legacy/manager/PollingSubscription.js +18 -27
- package/legacy/manager/SubscriptionManager.js +16 -42
- package/legacy/manager/applyManager.js +2 -1
- package/legacy/middlewareTypes.js +1 -1
- package/legacy/newActions.js +1 -1
- package/legacy/next/index.js +3 -3
- package/legacy/state/reducer/createReducer.js +2 -6
- package/legacy/state/reducer/fetchReducer.js +3 -13
- package/legacy/state/reducer/invalidateReducer.js +1 -1
- package/legacy/state/reducer/setReducer.js +9 -16
- package/legacy/types.js +2 -6
- package/lib/actionTypes.d.ts +1 -0
- package/lib/actionTypes.d.ts.map +1 -1
- package/lib/actionTypes.js +2 -2
- package/lib/controller/Controller.d.ts +126 -6
- package/lib/controller/Controller.d.ts.map +1 -1
- package/lib/controller/Controller.js +276 -6
- package/lib/controller/createFetch.d.ts +2 -2
- package/lib/controller/createFetch.d.ts.map +1 -1
- package/lib/controller/createFetch.js +3 -14
- package/lib/controller/createInvalidate.d.ts +1 -1
- package/lib/controller/createInvalidate.d.ts.map +1 -1
- package/lib/controller/createInvalidate.js +1 -1
- package/lib/controller/createInvalidateAll.d.ts +1 -1
- package/lib/controller/createInvalidateAll.d.ts.map +1 -1
- package/lib/controller/createInvalidateAll.js +1 -1
- package/lib/controller/createOptimistic.d.ts +2 -2
- package/lib/controller/createOptimistic.d.ts.map +1 -1
- package/lib/controller/createOptimistic.js +1 -7
- package/lib/controller/createReset.d.ts +1 -1
- package/lib/controller/createReset.d.ts.map +1 -1
- package/lib/controller/createReset.js +1 -1
- package/lib/controller/{createReceive.d.ts → createSet.d.ts} +6 -6
- package/lib/controller/createSet.d.ts.map +1 -0
- package/lib/controller/createSet.js +31 -0
- package/lib/controller/createSubscription.d.ts +3 -3
- package/lib/controller/createSubscription.d.ts.map +1 -1
- package/lib/controller/createSubscription.js +3 -7
- package/lib/index.d.ts +2 -6
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +2 -5
- package/lib/internal.d.ts +1 -1
- package/lib/internal.d.ts.map +1 -1
- package/lib/internal.js +2 -2
- package/lib/manager/DevtoolsManager.d.ts +1 -1
- package/lib/manager/DevtoolsManager.js +2 -2
- package/lib/manager/LogoutManager.d.ts +4 -5
- package/lib/manager/LogoutManager.d.ts.map +1 -1
- package/lib/manager/LogoutManager.js +2 -2
- package/lib/manager/NetworkManager.d.ts +4 -5
- package/lib/manager/NetworkManager.d.ts.map +1 -1
- package/lib/manager/NetworkManager.js +28 -61
- package/lib/manager/PollingSubscription.d.ts +9 -9
- package/lib/manager/PollingSubscription.d.ts.map +1 -1
- package/lib/manager/PollingSubscription.js +18 -27
- package/lib/manager/SubscriptionManager.d.ts +10 -15
- package/lib/manager/SubscriptionManager.d.ts.map +1 -1
- package/lib/manager/SubscriptionManager.js +16 -42
- package/lib/manager/applyManager.d.ts.map +1 -1
- package/lib/manager/applyManager.js +2 -1
- package/lib/middlewareTypes.d.ts +5 -5
- package/lib/middlewareTypes.d.ts.map +1 -1
- package/lib/middlewareTypes.js +1 -1
- package/lib/newActions.d.ts +26 -18
- package/lib/newActions.d.ts.map +1 -1
- package/lib/newActions.js +1 -1
- package/lib/next/index.d.ts +2 -2
- package/lib/next/index.d.ts.map +1 -1
- package/lib/next/index.js +3 -3
- package/lib/state/reducer/createReducer.d.ts.map +1 -1
- package/lib/state/reducer/createReducer.js +2 -6
- package/lib/state/reducer/fetchReducer.d.ts +1 -2
- package/lib/state/reducer/fetchReducer.d.ts.map +1 -1
- package/lib/state/reducer/fetchReducer.js +3 -14
- package/lib/state/reducer/invalidateReducer.d.ts +3 -4
- package/lib/state/reducer/invalidateReducer.d.ts.map +1 -1
- package/lib/state/reducer/invalidateReducer.js +1 -1
- package/lib/state/reducer/setReducer.d.ts +2 -38
- package/lib/state/reducer/setReducer.d.ts.map +1 -1
- package/lib/state/reducer/setReducer.js +9 -17
- package/lib/types.d.ts +9 -30
- package/lib/types.d.ts.map +1 -1
- package/lib/types.js +2 -6
- package/package.json +10 -7
- package/src/actionTypes.ts +1 -1
- package/src/controller/Controller.ts +491 -10
- package/src/controller/createFetch.ts +4 -19
- package/src/controller/createInvalidate.ts +1 -1
- package/src/controller/createInvalidateAll.ts +1 -1
- package/src/controller/createOptimistic.ts +3 -9
- package/src/controller/createReset.ts +1 -1
- package/src/controller/{createReceive.ts → createSet.ts} +9 -17
- package/src/controller/createSubscription.ts +3 -10
- package/src/index.ts +2 -16
- package/src/internal.ts +1 -1
- package/src/manager/DevtoolsManager.ts +1 -1
- package/src/manager/LogoutManager.ts +4 -5
- package/src/manager/NetworkManager.ts +31 -80
- package/src/manager/PollingSubscription.ts +40 -38
- package/src/manager/SubscriptionManager.ts +22 -54
- package/src/manager/__tests__/__snapshots__/pollingSubscription.ts.snap +10 -8
- package/src/manager/__tests__/logoutManager.ts +5 -5
- package/src/manager/__tests__/manager.ts +2 -4
- package/src/manager/__tests__/networkManager.ts +8 -42
- package/src/manager/__tests__/pollingSubscription.ts +259 -151
- package/src/manager/__tests__/subscriptionManager.ts +7 -13
- package/src/manager/applyManager.ts +1 -0
- package/src/middlewareTypes.ts +5 -10
- package/src/newActions.ts +33 -23
- package/src/next/index.ts +2 -2
- package/src/state/__tests__/reducer.ts +59 -297
- package/src/state/reducer/createReducer.ts +3 -11
- package/src/state/reducer/fetchReducer.ts +5 -18
- package/src/state/reducer/invalidateReducer.ts +2 -2
- package/src/state/reducer/setReducer.ts +10 -22
- package/src/types.ts +9 -78
- package/ts3.4/actionTypes.d.ts +1 -0
- package/ts3.4/controller/Controller.d.ts +168 -6
- package/ts3.4/controller/createFetch.d.ts +2 -2
- package/ts3.4/controller/createInvalidate.d.ts +1 -1
- package/ts3.4/controller/createInvalidateAll.d.ts +1 -1
- package/ts3.4/controller/createOptimistic.d.ts +1 -1
- package/ts3.4/controller/createReset.d.ts +1 -1
- package/ts3.4/controller/{createReceive.d.ts → createSet.d.ts} +6 -6
- package/ts3.4/controller/createSubscription.d.ts +3 -3
- package/ts3.4/index.d.ts +2 -7
- package/ts3.4/internal.d.ts +1 -1
- package/ts3.4/manager/DevtoolsManager.d.ts +1 -1
- package/ts3.4/manager/LogoutManager.d.ts +4 -5
- package/ts3.4/manager/NetworkManager.d.ts +4 -5
- package/ts3.4/manager/PollingSubscription.d.ts +9 -9
- package/ts3.4/manager/SubscriptionManager.d.ts +10 -15
- package/ts3.4/middlewareTypes.d.ts +5 -5
- package/ts3.4/newActions.d.ts +26 -18
- package/ts3.4/next/index.d.ts +2 -2
- package/ts3.4/state/reducer/fetchReducer.d.ts +1 -2
- package/ts3.4/state/reducer/invalidateReducer.d.ts +3 -4
- package/ts3.4/state/reducer/setReducer.d.ts +2 -38
- package/ts3.4/types.d.ts +8 -30
- package/legacy/compatibleActions.js +0 -2
- package/legacy/controller/BaseController.js +0 -289
- package/legacy/controller/createReceive.js +0 -36
- package/legacy/endpoint/index.js +0 -2
- package/legacy/endpoint/shapes.js +0 -2
- package/legacy/endpoint/types.js +0 -2
- package/legacy/legacyActions.js +0 -2
- package/legacy/next/Controller.js +0 -24
- package/legacy/previousActions.js +0 -2
- package/legacy/state/applyUpdatersToResults.js +0 -4
- package/legacy/state/legacy-actions/createFetch.js +0 -62
- package/legacy/state/legacy-actions/createReceive.js +0 -37
- package/legacy/state/legacy-actions/createReceiveError.js +0 -28
- package/legacy/state/legacy-actions/index.js +0 -4
- package/legacy/state/reducerInstance.js +0 -9
- package/lib/compatibleActions.d.ts +0 -47
- package/lib/compatibleActions.d.ts.map +0 -1
- package/lib/compatibleActions.js +0 -2
- package/lib/controller/BaseController.d.ts +0 -128
- package/lib/controller/BaseController.d.ts.map +0 -1
- package/lib/controller/BaseController.js +0 -289
- package/lib/controller/createReceive.d.ts.map +0 -1
- package/lib/controller/createReceive.js +0 -36
- package/lib/endpoint/index.d.ts +0 -3
- package/lib/endpoint/index.d.ts.map +0 -1
- package/lib/endpoint/index.js +0 -2
- package/lib/endpoint/shapes.d.ts +0 -25
- package/lib/endpoint/shapes.d.ts.map +0 -1
- package/lib/endpoint/shapes.js +0 -2
- package/lib/endpoint/types.d.ts +0 -45
- package/lib/endpoint/types.d.ts.map +0 -1
- package/lib/endpoint/types.js +0 -2
- package/lib/legacyActions.d.ts +0 -92
- package/lib/legacyActions.d.ts.map +0 -1
- package/lib/legacyActions.js +0 -2
- package/lib/next/Controller.d.ts +0 -14
- package/lib/next/Controller.d.ts.map +0 -1
- package/lib/next/Controller.js +0 -24
- package/lib/previousActions.d.ts +0 -91
- package/lib/previousActions.d.ts.map +0 -1
- package/lib/previousActions.js +0 -2
- package/lib/state/applyUpdatersToResults.d.ts +0 -13
- package/lib/state/applyUpdatersToResults.d.ts.map +0 -1
- package/lib/state/applyUpdatersToResults.js +0 -7
- package/lib/state/legacy-actions/createFetch.d.ts +0 -19
- package/lib/state/legacy-actions/createFetch.d.ts.map +0 -1
- package/lib/state/legacy-actions/createFetch.js +0 -62
- package/lib/state/legacy-actions/createReceive.d.ts +0 -14
- package/lib/state/legacy-actions/createReceive.d.ts.map +0 -1
- package/lib/state/legacy-actions/createReceive.js +0 -37
- package/lib/state/legacy-actions/createReceiveError.d.ts +0 -9
- package/lib/state/legacy-actions/createReceiveError.d.ts.map +0 -1
- package/lib/state/legacy-actions/createReceiveError.js +0 -28
- package/lib/state/legacy-actions/index.d.ts +0 -4
- package/lib/state/legacy-actions/index.d.ts.map +0 -1
- package/lib/state/legacy-actions/index.js +0 -4
- package/lib/state/reducerInstance.d.ts +0 -7
- package/lib/state/reducerInstance.d.ts.map +0 -1
- package/lib/state/reducerInstance.js +0 -9
- package/src/compatibleActions.ts +0 -96
- package/src/controller/BaseController.ts +0 -508
- package/src/endpoint/index.ts +0 -14
- package/src/endpoint/shapes.ts +0 -53
- package/src/endpoint/types.ts +0 -72
- package/src/legacyActions.ts +0 -163
- package/src/manager/__tests__/__snapshots__/pollingSubscription-endpoint.ts.snap +0 -49
- package/src/manager/__tests__/networkManager-legacy.ts +0 -394
- package/src/manager/__tests__/pollingSubscription-endpoint.ts +0 -423
- package/src/next/Controller.ts +0 -39
- package/src/previousActions.ts +0 -159
- package/src/state/__tests__/applyUpdatersToResults.ts +0 -40
- package/src/state/applyUpdatersToResults.ts +0 -29
- package/src/state/legacy-actions/createFetch.ts +0 -95
- package/src/state/legacy-actions/createReceive.ts +0 -68
- package/src/state/legacy-actions/createReceiveError.ts +0 -43
- package/src/state/legacy-actions/index.ts +0 -3
- package/src/state/reducerInstance.ts +0 -14
- package/ts3.4/compatibleActions.d.ts +0 -47
- package/ts3.4/controller/BaseController.d.ts +0 -170
- package/ts3.4/endpoint/index.d.ts +0 -3
- package/ts3.4/endpoint/shapes.d.ts +0 -25
- package/ts3.4/endpoint/types.d.ts +0 -45
- package/ts3.4/legacyActions.d.ts +0 -95
- package/ts3.4/next/Controller.d.ts +0 -14
- package/ts3.4/previousActions.d.ts +0 -94
- package/ts3.4/state/applyUpdatersToResults.d.ts +0 -13
- package/ts3.4/state/legacy-actions/createFetch.d.ts +0 -19
- package/ts3.4/state/legacy-actions/createReceive.d.ts +0 -14
- package/ts3.4/state/legacy-actions/createReceiveError.d.ts +0 -9
- package/ts3.4/state/legacy-actions/index.d.ts +0 -4
- package/ts3.4/state/reducerInstance.d.ts +0 -7
|
@@ -1,24 +1,18 @@
|
|
|
1
1
|
import type { EndpointInterface } from '@data-client/normalizr';
|
|
2
2
|
|
|
3
3
|
import { SUBSCRIBE_TYPE, UNSUBSCRIBE_TYPE } from '../actionTypes.js';
|
|
4
|
-
import type {
|
|
5
|
-
CompatibleSubscribeAction,
|
|
6
|
-
CompatibleUnsubscribeAction,
|
|
7
|
-
} from '../compatibleActions.js';
|
|
4
|
+
import type { SubscribeAction, UnsubscribeAction } from '../types.js';
|
|
8
5
|
|
|
9
6
|
export function createSubscription<E extends EndpointInterface>(
|
|
10
7
|
endpoint: E,
|
|
11
8
|
{ args }: { args: readonly [...Parameters<E>] },
|
|
12
|
-
):
|
|
9
|
+
): SubscribeAction<E> {
|
|
13
10
|
return {
|
|
14
11
|
type: SUBSCRIBE_TYPE,
|
|
15
12
|
endpoint,
|
|
16
13
|
meta: {
|
|
17
14
|
args,
|
|
18
15
|
key: endpoint.key(...args),
|
|
19
|
-
fetch: () => endpoint(...args),
|
|
20
|
-
schema: endpoint.schema,
|
|
21
|
-
options: endpoint,
|
|
22
16
|
},
|
|
23
17
|
};
|
|
24
18
|
}
|
|
@@ -26,14 +20,13 @@ export function createSubscription<E extends EndpointInterface>(
|
|
|
26
20
|
export function createUnsubscription<E extends EndpointInterface>(
|
|
27
21
|
endpoint: E,
|
|
28
22
|
{ args }: { args: readonly [...Parameters<E>] },
|
|
29
|
-
):
|
|
23
|
+
): UnsubscribeAction<E> {
|
|
30
24
|
return {
|
|
31
25
|
type: UNSUBSCRIBE_TYPE,
|
|
32
26
|
endpoint,
|
|
33
27
|
meta: {
|
|
34
28
|
args,
|
|
35
29
|
key: endpoint.key(...args),
|
|
36
|
-
options: endpoint,
|
|
37
30
|
},
|
|
38
31
|
};
|
|
39
32
|
}
|
package/src/index.ts
CHANGED
|
@@ -30,32 +30,18 @@ export {
|
|
|
30
30
|
default as createReducer,
|
|
31
31
|
initialState,
|
|
32
32
|
} from './state/reducer/createReducer.js';
|
|
33
|
-
export { default as reducer } from './state/reducerInstance.js';
|
|
34
33
|
export { default as applyManager } from './manager/applyManager.js';
|
|
35
34
|
|
|
36
35
|
export { default as Controller } from './controller/Controller.js';
|
|
37
36
|
export type {
|
|
38
|
-
|
|
37
|
+
DataClientDispatch,
|
|
39
38
|
GenericDispatch,
|
|
40
39
|
} from './controller/Controller.js';
|
|
41
40
|
export { default as createFetch } from './controller/createFetch.js';
|
|
42
|
-
export { default as createReceive } from './controller/
|
|
41
|
+
export { default as createReceive } from './controller/createSet.js';
|
|
43
42
|
|
|
44
43
|
export * from './controller/types.js';
|
|
45
|
-
export * as legacyActions from './state/legacy-actions/index.js';
|
|
46
44
|
export * as actionTypes from './actionTypes.js';
|
|
47
45
|
/* istanbul ignore next */
|
|
48
46
|
export * from './types.js';
|
|
49
|
-
export type {
|
|
50
|
-
FetchShape,
|
|
51
|
-
ReadShape,
|
|
52
|
-
MutateShape,
|
|
53
|
-
DeleteShape,
|
|
54
|
-
} from './endpoint/shapes.js';
|
|
55
|
-
export type {
|
|
56
|
-
SetShapeParams,
|
|
57
|
-
ParamsFromShape,
|
|
58
|
-
BodyFromShape,
|
|
59
|
-
ReturnFromShape,
|
|
60
|
-
} from './endpoint/types.js';
|
|
61
47
|
export * from './manager/index.js';
|
package/src/internal.ts
CHANGED
|
@@ -37,7 +37,7 @@ const DEFAULT_CONFIG = {
|
|
|
37
37
|
*
|
|
38
38
|
* Options: https://github.com/reduxjs/redux-devtools/blob/main/extension/docs/API/Arguments.md
|
|
39
39
|
*
|
|
40
|
-
* @see https://
|
|
40
|
+
* @see https://dataclient.io/docs/api/DevToolsManager
|
|
41
41
|
*/
|
|
42
42
|
export default class DevToolsManager implements Manager {
|
|
43
43
|
protected declare middleware: Middleware;
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import { SET_TYPE } from '../actionTypes.js';
|
|
2
2
|
import Controller from '../controller/Controller.js';
|
|
3
3
|
import { UnknownError } from '../index.js';
|
|
4
|
-
import
|
|
5
|
-
import { Manager } from '../types.js';
|
|
4
|
+
import { ActionTypes, Manager } from '../types.js';
|
|
6
5
|
|
|
7
6
|
/** Handling network unauthorized indicators like HTTP 401
|
|
8
7
|
*
|
|
9
|
-
* @see https://
|
|
8
|
+
* @see https://dataclient.io/docs/api/LogoutManager
|
|
10
9
|
*/
|
|
11
|
-
export default class LogoutManager implements Manager
|
|
10
|
+
export default class LogoutManager implements Manager {
|
|
12
11
|
protected declare middleware: Middleware;
|
|
13
12
|
|
|
14
13
|
constructor({ handleLogout, shouldLogout }: Props = {}) {
|
|
@@ -42,7 +41,7 @@ export default class LogoutManager implements Manager<CombinedActionTypes> {
|
|
|
42
41
|
}
|
|
43
42
|
}
|
|
44
43
|
|
|
45
|
-
type Dispatch = (value:
|
|
44
|
+
type Dispatch = (value: ActionTypes) => Promise<void>;
|
|
46
45
|
|
|
47
46
|
// this further restricts the types to be future compatible
|
|
48
47
|
export type Middleware = <C extends Controller<Dispatch>>(
|
|
@@ -1,19 +1,14 @@
|
|
|
1
1
|
import { SET_TYPE, FETCH_TYPE, RESET_TYPE } from '../actionTypes.js';
|
|
2
2
|
import Controller from '../controller/Controller.js';
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
5
|
-
createReceive,
|
|
6
|
-
createReceiveError,
|
|
7
|
-
} from '../state/legacy-actions/index.js';
|
|
3
|
+
import createSet from '../controller/createSet.js';
|
|
8
4
|
import RIC from '../state/RIC.js';
|
|
9
5
|
import type {
|
|
10
6
|
FetchAction,
|
|
11
|
-
ReceiveAction,
|
|
12
7
|
Manager,
|
|
13
8
|
ActionTypes,
|
|
14
9
|
MiddlewareAPI,
|
|
15
10
|
Middleware,
|
|
16
|
-
|
|
11
|
+
SetAction,
|
|
17
12
|
} from '../types.js';
|
|
18
13
|
|
|
19
14
|
export class ResetError extends Error {
|
|
@@ -31,7 +26,7 @@ export class ResetError extends Error {
|
|
|
31
26
|
*
|
|
32
27
|
* Interfaces with store via a redux-compatible middleware.
|
|
33
28
|
*
|
|
34
|
-
* @see https://
|
|
29
|
+
* @see https://dataclient.io/docs/api/NetworkManager
|
|
35
30
|
*/
|
|
36
31
|
export default class NetworkManager implements Manager {
|
|
37
32
|
protected fetched: { [k: string]: Promise<any> } = Object.create(null);
|
|
@@ -41,7 +36,6 @@ export default class NetworkManager implements Manager {
|
|
|
41
36
|
declare readonly dataExpiryLength: number;
|
|
42
37
|
declare readonly errorExpiryLength: number;
|
|
43
38
|
protected declare middleware: Middleware;
|
|
44
|
-
protected getState: () => State<unknown> = () => initialState;
|
|
45
39
|
protected controller: Controller = new Controller();
|
|
46
40
|
declare cleanupDate?: number;
|
|
47
41
|
|
|
@@ -49,25 +43,19 @@ export default class NetworkManager implements Manager {
|
|
|
49
43
|
this.dataExpiryLength = dataExpiryLength;
|
|
50
44
|
this.errorExpiryLength = errorExpiryLength;
|
|
51
45
|
|
|
52
|
-
this.middleware = <C extends MiddlewareAPI>({
|
|
53
|
-
dispatch,
|
|
54
|
-
getState,
|
|
55
|
-
controller,
|
|
56
|
-
}: C) => {
|
|
57
|
-
this.getState = getState;
|
|
46
|
+
this.middleware = <C extends MiddlewareAPI>(controller: C) => {
|
|
58
47
|
this.controller = controller;
|
|
59
48
|
return (next: C['dispatch']): C['dispatch'] =>
|
|
60
49
|
(action): Promise<void> => {
|
|
61
50
|
switch (action.type) {
|
|
62
51
|
case FETCH_TYPE:
|
|
63
|
-
this.handleFetch(action
|
|
52
|
+
this.handleFetch(action);
|
|
64
53
|
// This is the only case that causes any state change
|
|
65
54
|
// It's important to intercept other fetches as we don't want to trigger reducers during
|
|
66
55
|
// render - so we need to stop 'readonly' fetches which can be triggered in render
|
|
67
56
|
if (
|
|
68
|
-
action.
|
|
69
|
-
|
|
70
|
-
action.endpoint.sideEffect)
|
|
57
|
+
action.endpoint.getOptimisticResponse !== undefined &&
|
|
58
|
+
action.endpoint.sideEffect
|
|
71
59
|
) {
|
|
72
60
|
return next(action);
|
|
73
61
|
}
|
|
@@ -81,8 +69,14 @@ export default class NetworkManager implements Manager {
|
|
|
81
69
|
controller.getState().meta[action.meta.key]?.error;
|
|
82
70
|
// processing errors result in state meta having error, so we should reject the promise
|
|
83
71
|
if (error) {
|
|
84
|
-
|
|
85
|
-
|
|
72
|
+
this.handleReceive(
|
|
73
|
+
createSet(action.endpoint, {
|
|
74
|
+
args: action.meta.args as any,
|
|
75
|
+
response: error,
|
|
76
|
+
fetchedAt: action.meta.fetchedAt,
|
|
77
|
+
error: true,
|
|
78
|
+
}),
|
|
79
|
+
);
|
|
86
80
|
} else {
|
|
87
81
|
this.handleReceive(action);
|
|
88
82
|
}
|
|
@@ -148,10 +142,7 @@ export default class NetworkManager implements Manager {
|
|
|
148
142
|
|
|
149
143
|
protected getLastReset() {
|
|
150
144
|
if (this.cleanupDate) return this.cleanupDate;
|
|
151
|
-
|
|
152
|
-
if (lastReset instanceof Date) return lastReset.valueOf();
|
|
153
|
-
if (typeof lastReset !== 'number') return -Infinity;
|
|
154
|
-
return lastReset;
|
|
145
|
+
return this.controller.getState().lastReset;
|
|
155
146
|
}
|
|
156
147
|
|
|
157
148
|
/** Called when middleware intercepts 'rest-hooks/fetch' action.
|
|
@@ -162,18 +153,9 @@ export default class NetworkManager implements Manager {
|
|
|
162
153
|
* Uses throttle only when instructed by action meta. This is valuable
|
|
163
154
|
* for ensures mutation requests always go through.
|
|
164
155
|
*/
|
|
165
|
-
protected handleFetch(
|
|
166
|
-
action: FetchAction,
|
|
167
|
-
dispatch: (action: any) => Promise<void>,
|
|
168
|
-
controller: Controller,
|
|
169
|
-
) {
|
|
156
|
+
protected handleFetch(action: FetchAction) {
|
|
170
157
|
const fetch = action.payload;
|
|
171
|
-
const { key, throttle, resolve, reject } = action.meta;
|
|
172
|
-
// TODO(breaking): remove support for Date type in 'Receive' action
|
|
173
|
-
const createdAt =
|
|
174
|
-
typeof action.meta.createdAt !== 'number'
|
|
175
|
-
? action.meta.createdAt.getTime()
|
|
176
|
-
: action.meta.createdAt;
|
|
158
|
+
const { key, throttle, resolve, reject, createdAt } = action.meta;
|
|
177
159
|
|
|
178
160
|
const deferedFetch = () => {
|
|
179
161
|
let promise = fetch();
|
|
@@ -192,7 +174,7 @@ export default class NetworkManager implements Manager {
|
|
|
192
174
|
// schedule non-throttled resolutions in a microtask before receive
|
|
193
175
|
// this enables users awaiting their fetch to trigger any react updates needed to deal
|
|
194
176
|
// with upcoming changes because of the fetch (for instance avoiding suspense if something is deleted)
|
|
195
|
-
if (!throttle
|
|
177
|
+
if (!throttle) {
|
|
196
178
|
promise = resolvePromise(promise);
|
|
197
179
|
}
|
|
198
180
|
promise = promise
|
|
@@ -209,26 +191,11 @@ export default class NetworkManager implements Manager {
|
|
|
209
191
|
|
|
210
192
|
// don't update state with promises started before last clear
|
|
211
193
|
if (createdAt >= lastReset) {
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
fetchedAt: createdAt,
|
|
218
|
-
});
|
|
219
|
-
} else {
|
|
220
|
-
// TODO(breaking): is this branch still possible? remove in next major update
|
|
221
|
-
// does this throw if the reducer fails? - no because reducer is wrapped in try/catch
|
|
222
|
-
this.controller.dispatch(
|
|
223
|
-
createReceive(data, {
|
|
224
|
-
...action.meta,
|
|
225
|
-
fetchedAt: createdAt,
|
|
226
|
-
dataExpiryLength:
|
|
227
|
-
action.meta.options?.dataExpiryLength ??
|
|
228
|
-
this.dataExpiryLength,
|
|
229
|
-
}),
|
|
230
|
-
);
|
|
231
|
-
}
|
|
194
|
+
this.controller.resolve(action.endpoint, {
|
|
195
|
+
args: action.meta.args as any,
|
|
196
|
+
response: data,
|
|
197
|
+
fetchedAt: createdAt,
|
|
198
|
+
});
|
|
232
199
|
}
|
|
233
200
|
return data;
|
|
234
201
|
})
|
|
@@ -236,31 +203,15 @@ export default class NetworkManager implements Manager {
|
|
|
236
203
|
const lastReset = this.getLastReset();
|
|
237
204
|
// don't update state with promises started before last clear
|
|
238
205
|
if (createdAt >= lastReset) {
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
});
|
|
246
|
-
} else {
|
|
247
|
-
this.controller.dispatch(
|
|
248
|
-
createReceiveError(error, {
|
|
249
|
-
...action.meta,
|
|
250
|
-
errorExpiryLength:
|
|
251
|
-
action.meta.options?.errorExpiryLength ??
|
|
252
|
-
this.errorExpiryLength,
|
|
253
|
-
fetchedAt: createdAt,
|
|
254
|
-
}),
|
|
255
|
-
);
|
|
256
|
-
}
|
|
206
|
+
this.controller.resolve(action.endpoint, {
|
|
207
|
+
args: action.meta.args as any,
|
|
208
|
+
response: error,
|
|
209
|
+
fetchedAt: createdAt,
|
|
210
|
+
error: true,
|
|
211
|
+
});
|
|
257
212
|
}
|
|
258
213
|
throw error;
|
|
259
214
|
});
|
|
260
|
-
// legacy behavior schedules resolution after dispatch
|
|
261
|
-
if (!throttle && !action.endpoint) {
|
|
262
|
-
promise = resolvePromise(promise);
|
|
263
|
-
}
|
|
264
215
|
return promise;
|
|
265
216
|
};
|
|
266
217
|
|
|
@@ -277,7 +228,7 @@ export default class NetworkManager implements Manager {
|
|
|
277
228
|
*
|
|
278
229
|
* Will resolve the promise associated with receive key.
|
|
279
230
|
*/
|
|
280
|
-
protected handleReceive(action:
|
|
231
|
+
protected handleReceive(action: SetAction) {
|
|
281
232
|
// this can still turn out to be untrue since this is async
|
|
282
233
|
if (action.meta.key in this.fetched) {
|
|
283
234
|
let promiseHandler: (value?: any) => void;
|
|
@@ -1,45 +1,43 @@
|
|
|
1
|
-
import type { EndpointInterface
|
|
1
|
+
import type { EndpointInterface } from '@data-client/normalizr';
|
|
2
2
|
|
|
3
3
|
import ConnectionListener from './ConnectionListener.js';
|
|
4
4
|
import DefaultConnectionListener from './DefaultConnectionListener.js';
|
|
5
|
-
import { Subscription
|
|
6
|
-
import
|
|
7
|
-
import type {
|
|
5
|
+
import type { Subscription } from './SubscriptionManager.js';
|
|
6
|
+
import type Controller from '../controller/Controller.js';
|
|
7
|
+
import type { SubscribeAction } from '../types.js';
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* PollingSubscription keeps a given resource updated by
|
|
11
11
|
* dispatching a fetch at a rate equal to the minimum update
|
|
12
12
|
* interval requested.
|
|
13
13
|
*
|
|
14
|
-
* @see https://
|
|
14
|
+
* @see https://dataclient.io/docs/api/PollingSubscription
|
|
15
15
|
*/
|
|
16
16
|
export default class PollingSubscription implements Subscription {
|
|
17
|
-
protected declare readonly
|
|
18
|
-
protected declare readonly
|
|
17
|
+
protected declare readonly endpoint: EndpointInterface;
|
|
18
|
+
protected declare readonly args: readonly any[];
|
|
19
19
|
protected declare readonly key: string;
|
|
20
20
|
protected declare frequency: number;
|
|
21
21
|
protected frequencyHistogram: Map<number, number> = new Map();
|
|
22
|
-
protected declare
|
|
23
|
-
protected declare getState: () => State<unknown>;
|
|
22
|
+
protected declare controller: Controller;
|
|
24
23
|
protected declare intervalId?: ReturnType<typeof setInterval>;
|
|
25
24
|
protected declare lastIntervalId?: ReturnType<typeof setInterval>;
|
|
26
25
|
protected declare startId?: ReturnType<typeof setTimeout>;
|
|
27
26
|
private declare connectionListener: ConnectionListener;
|
|
28
27
|
|
|
29
28
|
constructor(
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
action: Omit<SubscribeAction, 'type'>,
|
|
30
|
+
controller: Controller,
|
|
32
31
|
connectionListener?: ConnectionListener,
|
|
33
32
|
) {
|
|
34
|
-
if (
|
|
33
|
+
if (action.endpoint.pollFrequency === undefined)
|
|
35
34
|
throw new Error('frequency needed for polling subscription');
|
|
36
|
-
this.
|
|
37
|
-
this.
|
|
38
|
-
this.
|
|
39
|
-
this.key = key;
|
|
35
|
+
this.endpoint = action.endpoint;
|
|
36
|
+
this.frequency = action.endpoint.pollFrequency;
|
|
37
|
+
this.args = action.meta.args;
|
|
38
|
+
this.key = action.meta.key;
|
|
40
39
|
this.frequencyHistogram.set(this.frequency, 1);
|
|
41
|
-
this.
|
|
42
|
-
this.getState = getState;
|
|
40
|
+
this.controller = controller;
|
|
43
41
|
this.connectionListener =
|
|
44
42
|
connectionListener || new DefaultConnectionListener();
|
|
45
43
|
|
|
@@ -123,16 +121,17 @@ export default class PollingSubscription implements Subscription {
|
|
|
123
121
|
|
|
124
122
|
/** Trigger request for latest resource */
|
|
125
123
|
protected update() {
|
|
126
|
-
const
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
(endpoint
|
|
124
|
+
const sup = this.endpoint;
|
|
125
|
+
const endpoint = function (this: any, ...args: any[]) {
|
|
126
|
+
return sup.call(this, ...args);
|
|
127
|
+
};
|
|
128
|
+
Object.assign(endpoint, this.endpoint);
|
|
129
|
+
endpoint.dataExpiryLength = this.frequency / 2;
|
|
130
|
+
endpoint.errorExpiryLength = this.frequency / 10;
|
|
131
131
|
endpoint.errorPolicy = () => 'soft' as const;
|
|
132
|
-
|
|
132
|
+
endpoint.key = () => this.key;
|
|
133
133
|
// stop any errors here from bubbling
|
|
134
|
-
|
|
135
|
-
this.dispatch(action);
|
|
134
|
+
this.controller.fetch(endpoint, ...this.args).catch(() => null);
|
|
136
135
|
}
|
|
137
136
|
|
|
138
137
|
/** What happens when browser goes offline */
|
|
@@ -146,17 +145,20 @@ export default class PollingSubscription implements Subscription {
|
|
|
146
145
|
protected onlineListener = () => {
|
|
147
146
|
this.connectionListener.removeOnlineListener(this.onlineListener);
|
|
148
147
|
const now = Date.now();
|
|
149
|
-
this.startId = setTimeout(
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
148
|
+
this.startId = setTimeout(
|
|
149
|
+
() => {
|
|
150
|
+
if (this.startId) {
|
|
151
|
+
delete this.startId;
|
|
152
|
+
this.update();
|
|
153
|
+
this.run();
|
|
154
|
+
} else if (process.env.NODE_ENV !== 'production') {
|
|
155
|
+
console.warn(
|
|
156
|
+
`Poll setTimeout for ${this.key} still running, but timeoutId deleted`,
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
},
|
|
160
|
+
Math.max(0, this.lastFetchTime() - now + this.frequency),
|
|
161
|
+
);
|
|
160
162
|
this.connectionListener.addOfflineListener(this.offlineListener);
|
|
161
163
|
};
|
|
162
164
|
|
|
@@ -185,6 +187,6 @@ export default class PollingSubscription implements Subscription {
|
|
|
185
187
|
|
|
186
188
|
/** Last fetch time */
|
|
187
189
|
protected lastFetchTime() {
|
|
188
|
-
return this.getState().meta[this.key]?.date ?? 0;
|
|
190
|
+
return this.controller.getState().meta[this.key]?.date ?? 0;
|
|
189
191
|
}
|
|
190
192
|
}
|
|
@@ -1,27 +1,15 @@
|
|
|
1
|
-
import type { Schema } from '@data-client/normalizr';
|
|
2
|
-
|
|
3
1
|
import { SUBSCRIBE_TYPE, UNSUBSCRIBE_TYPE } from '../actionTypes.js';
|
|
2
|
+
import Controller from '../controller/Controller.js';
|
|
4
3
|
import type {
|
|
5
4
|
Manager,
|
|
6
|
-
State,
|
|
7
5
|
MiddlewareAPI,
|
|
8
6
|
Middleware,
|
|
9
|
-
Dispatch,
|
|
10
7
|
UnsubscribeAction,
|
|
11
8
|
SubscribeAction,
|
|
12
9
|
} from '../types.js';
|
|
13
10
|
|
|
14
11
|
type Actions = UnsubscribeAction | SubscribeAction;
|
|
15
12
|
|
|
16
|
-
/** Properties sent to Subscription constructor */
|
|
17
|
-
export interface SubscriptionInit {
|
|
18
|
-
schema?: Schema | undefined;
|
|
19
|
-
fetch: () => Promise<any>;
|
|
20
|
-
key: string;
|
|
21
|
-
getState: () => State<unknown>;
|
|
22
|
-
frequency?: number | undefined;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
13
|
/** Interface handling a single resource subscription */
|
|
26
14
|
export interface Subscription {
|
|
27
15
|
add(frequency?: number): void;
|
|
@@ -31,7 +19,10 @@ export interface Subscription {
|
|
|
31
19
|
|
|
32
20
|
/** The static class that constructs Subscription */
|
|
33
21
|
export interface SubscriptionConstructable {
|
|
34
|
-
new (
|
|
22
|
+
new (
|
|
23
|
+
action: Omit<SubscribeAction, 'type'>,
|
|
24
|
+
controller: Controller,
|
|
25
|
+
): Subscription;
|
|
35
26
|
}
|
|
36
27
|
|
|
37
28
|
/** Handles subscription actions -> fetch or receive actions
|
|
@@ -39,10 +30,10 @@ export interface SubscriptionConstructable {
|
|
|
39
30
|
* Constructor takes a SubscriptionConstructable class to control how
|
|
40
31
|
* subscriptions are handled. (e.g., polling, websockets)
|
|
41
32
|
*
|
|
42
|
-
* @see https://
|
|
33
|
+
* @see https://dataclient.io/docs/api/SubscriptionManager
|
|
43
34
|
*/
|
|
44
35
|
export default class SubscriptionManager<S extends SubscriptionConstructable>
|
|
45
|
-
implements Manager
|
|
36
|
+
implements Manager<Actions>
|
|
46
37
|
{
|
|
47
38
|
protected subscriptions: {
|
|
48
39
|
[key: string]: InstanceType<S>;
|
|
@@ -50,23 +41,25 @@ export default class SubscriptionManager<S extends SubscriptionConstructable>
|
|
|
50
41
|
|
|
51
42
|
protected declare readonly Subscription: S;
|
|
52
43
|
protected declare middleware: Middleware;
|
|
44
|
+
protected controller: Controller = new Controller();
|
|
53
45
|
|
|
54
46
|
constructor(Subscription: S) {
|
|
55
47
|
this.Subscription = Subscription;
|
|
56
48
|
|
|
57
|
-
this.middleware = <C extends MiddlewareAPI>(
|
|
49
|
+
this.middleware = <C extends MiddlewareAPI>(controller: C) => {
|
|
50
|
+
this.controller = controller;
|
|
58
51
|
return (next: C['dispatch']): C['dispatch'] =>
|
|
59
52
|
action => {
|
|
60
53
|
switch (action.type) {
|
|
61
54
|
case SUBSCRIBE_TYPE:
|
|
62
55
|
try {
|
|
63
|
-
this.handleSubscribe(action
|
|
56
|
+
this.handleSubscribe(action);
|
|
64
57
|
} catch (e) {
|
|
65
58
|
console.error(e);
|
|
66
59
|
}
|
|
67
60
|
return Promise.resolve();
|
|
68
61
|
case UNSUBSCRIBE_TYPE:
|
|
69
|
-
this.handleUnsubscribe(action
|
|
62
|
+
this.handleUnsubscribe(action);
|
|
70
63
|
return Promise.resolve();
|
|
71
64
|
default:
|
|
72
65
|
return next(action);
|
|
@@ -85,38 +78,16 @@ export default class SubscriptionManager<S extends SubscriptionConstructable>
|
|
|
85
78
|
/** Called when middleware intercepts 'rest-hooks/subscribe' action.
|
|
86
79
|
*
|
|
87
80
|
*/
|
|
88
|
-
protected handleSubscribe(
|
|
89
|
-
action
|
|
90
|
-
dispatch: (action: any) => Promise<void>,
|
|
91
|
-
getState: () => State<unknown>,
|
|
92
|
-
) {
|
|
93
|
-
let options: SubscriptionInit;
|
|
94
|
-
if (action.endpoint) {
|
|
95
|
-
const { endpoint } = action;
|
|
96
|
-
const { args } = action.meta;
|
|
97
|
-
options = {
|
|
98
|
-
schema: endpoint.schema,
|
|
99
|
-
fetch: () => endpoint(...args),
|
|
100
|
-
frequency: endpoint.pollFrequency,
|
|
101
|
-
key: endpoint.key(...args),
|
|
102
|
-
getState,
|
|
103
|
-
};
|
|
104
|
-
} else {
|
|
105
|
-
options = {
|
|
106
|
-
key: action.meta.key,
|
|
107
|
-
frequency: action.meta.options?.pollFrequency,
|
|
108
|
-
schema: action.meta.schema,
|
|
109
|
-
fetch: action.meta.fetch,
|
|
110
|
-
getState,
|
|
111
|
-
};
|
|
112
|
-
}
|
|
81
|
+
protected handleSubscribe(action: SubscribeAction) {
|
|
82
|
+
const key = action.meta.key;
|
|
113
83
|
|
|
114
|
-
if (
|
|
115
|
-
|
|
84
|
+
if (key in this.subscriptions) {
|
|
85
|
+
const frequency = action.endpoint.pollFrequency;
|
|
86
|
+
this.subscriptions[key].add(frequency);
|
|
116
87
|
} else {
|
|
117
|
-
this.subscriptions[
|
|
118
|
-
|
|
119
|
-
|
|
88
|
+
this.subscriptions[key] = new this.Subscription(
|
|
89
|
+
action,
|
|
90
|
+
this.controller,
|
|
120
91
|
) as InstanceType<S>;
|
|
121
92
|
}
|
|
122
93
|
}
|
|
@@ -124,15 +95,12 @@ export default class SubscriptionManager<S extends SubscriptionConstructable>
|
|
|
124
95
|
/** Called when middleware intercepts 'rest-hooks/unsubscribe' action.
|
|
125
96
|
*
|
|
126
97
|
*/
|
|
127
|
-
protected handleUnsubscribe(
|
|
128
|
-
action: UnsubscribeAction,
|
|
129
|
-
dispatch: (action: any) => Promise<void>,
|
|
130
|
-
) {
|
|
98
|
+
protected handleUnsubscribe(action: UnsubscribeAction) {
|
|
131
99
|
const key = action.meta.key;
|
|
132
|
-
const frequency = action.meta.options?.pollFrequency;
|
|
133
100
|
|
|
134
101
|
/* istanbul ignore else */
|
|
135
102
|
if (key in this.subscriptions) {
|
|
103
|
+
const frequency = action.endpoint.pollFrequency;
|
|
136
104
|
const empty = this.subscriptions[key].remove(frequency);
|
|
137
105
|
if (empty) {
|
|
138
106
|
delete this.subscriptions[key];
|
|
@@ -1,19 +1,23 @@
|
|
|
1
1
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
2
|
|
|
3
|
-
exports[`PollingSubscription should
|
|
3
|
+
exports[`PollingSubscription fresh data cleanup() should not run even if interval not cancelled 1`] = `
|
|
4
|
+
[
|
|
5
|
+
"Poll intervalId for test.com2 still running, but intervalId deleted",
|
|
6
|
+
]
|
|
7
|
+
`;
|
|
8
|
+
|
|
9
|
+
exports[`PollingSubscription fresh data should call after period 1`] = `
|
|
4
10
|
[
|
|
5
11
|
{
|
|
6
12
|
"endpoint": [Function],
|
|
7
13
|
"meta": {
|
|
8
14
|
"args": [],
|
|
9
15
|
"key": "test.com",
|
|
10
|
-
"
|
|
16
|
+
"nm": false,
|
|
11
17
|
"promise": Promise {},
|
|
12
18
|
"reject": [Function],
|
|
13
19
|
"resolve": [Function],
|
|
14
|
-
"schema": [Function],
|
|
15
20
|
"throttle": true,
|
|
16
|
-
"type": "read",
|
|
17
21
|
},
|
|
18
22
|
"payload": [Function],
|
|
19
23
|
"type": "rest-hooks/fetch",
|
|
@@ -21,20 +25,18 @@ exports[`PollingSubscription should call after period 1`] = `
|
|
|
21
25
|
]
|
|
22
26
|
`;
|
|
23
27
|
|
|
24
|
-
exports[`PollingSubscription should call after period 2`] = `
|
|
28
|
+
exports[`PollingSubscription fresh data should call after period 2`] = `
|
|
25
29
|
[
|
|
26
30
|
{
|
|
27
31
|
"endpoint": [Function],
|
|
28
32
|
"meta": {
|
|
29
33
|
"args": [],
|
|
30
34
|
"key": "test.com",
|
|
31
|
-
"
|
|
35
|
+
"nm": false,
|
|
32
36
|
"promise": Promise {},
|
|
33
37
|
"reject": [Function],
|
|
34
38
|
"resolve": [Function],
|
|
35
|
-
"schema": [Function],
|
|
36
39
|
"throttle": true,
|
|
37
|
-
"type": "read",
|
|
38
40
|
},
|
|
39
41
|
"payload": [Function],
|
|
40
42
|
"type": "rest-hooks/fetch",
|