@data-client/core 0.1.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/LICENSE +201 -0
- package/README.md +71 -0
- package/dist/index.js +1643 -0
- package/dist/index.umd.min.js +1 -0
- package/dist/next.js +461 -0
- package/dist/package.json +1 -0
- package/legacy/actionTypes.js +12 -0
- package/legacy/compatibleActions.js +2 -0
- package/legacy/controller/BaseController.js +289 -0
- package/legacy/controller/Controller.js +20 -0
- package/legacy/controller/createFetch.js +42 -0
- package/legacy/controller/createInvalidate.js +12 -0
- package/legacy/controller/createInvalidateAll.js +8 -0
- package/legacy/controller/createOptimistic.js +33 -0
- package/legacy/controller/createReceive.js +36 -0
- package/legacy/controller/createReset.js +8 -0
- package/legacy/controller/createSubscription.js +30 -0
- package/legacy/controller/types.js +2 -0
- package/legacy/endpoint/index.js +2 -0
- package/legacy/endpoint/shapes.js +2 -0
- package/legacy/endpoint/types.js +2 -0
- package/legacy/fsa.js +2 -0
- package/legacy/index.js +22 -0
- package/legacy/internal.js +4 -0
- package/legacy/legacyActions.js +2 -0
- package/legacy/manager/ConnectionListener.js +2 -0
- package/legacy/manager/DefaultConnectionListener.js +40 -0
- package/legacy/manager/DevtoolsManager.js +73 -0
- package/legacy/manager/LogoutManager.js +34 -0
- package/legacy/manager/NetworkManager.js +291 -0
- package/legacy/manager/PollingSubscription.js +159 -0
- package/legacy/manager/SubscriptionManager.js +117 -0
- package/legacy/manager/applyManager.js +23 -0
- package/legacy/manager/devtoolsTypes.js +2 -0
- package/legacy/manager/index.js +6 -0
- package/legacy/middlewareTypes.js +2 -0
- package/legacy/newActions.js +2 -0
- package/legacy/next/Controller.js +24 -0
- package/legacy/next/index.js +3 -0
- package/legacy/previousActions.js +2 -0
- package/legacy/state/RIC.js +3 -0
- package/legacy/state/applyUpdatersToResults.js +4 -0
- package/legacy/state/legacy-actions/createFetch.js +62 -0
- package/legacy/state/legacy-actions/createReceive.js +37 -0
- package/legacy/state/legacy-actions/createReceiveError.js +28 -0
- package/legacy/state/legacy-actions/index.js +4 -0
- package/legacy/state/reducer/createReducer.js +54 -0
- package/legacy/state/reducer/fetchReducer.js +32 -0
- package/legacy/state/reducer/invalidateReducer.js +28 -0
- package/legacy/state/reducer/setReducer.js +113 -0
- package/legacy/state/reducerInstance.js +9 -0
- package/legacy/state/selectMeta.js +4 -0
- package/legacy/types.js +8 -0
- package/lib/actionTypes.d.ts +11 -0
- package/lib/actionTypes.d.ts.map +1 -0
- package/lib/actionTypes.js +12 -0
- package/lib/compatibleActions.d.ts +47 -0
- package/lib/compatibleActions.d.ts.map +1 -0
- package/lib/compatibleActions.js +2 -0
- package/lib/controller/BaseController.d.ts +128 -0
- package/lib/controller/BaseController.d.ts.map +1 -0
- package/lib/controller/BaseController.js +289 -0
- package/lib/controller/Controller.d.ts +14 -0
- package/lib/controller/Controller.d.ts.map +1 -0
- package/lib/controller/Controller.js +20 -0
- package/lib/controller/createFetch.d.ts +12 -0
- package/lib/controller/createFetch.d.ts.map +1 -0
- package/lib/controller/createFetch.js +42 -0
- package/lib/controller/createInvalidate.d.ts +6 -0
- package/lib/controller/createInvalidate.d.ts.map +1 -0
- package/lib/controller/createInvalidate.js +12 -0
- package/lib/controller/createInvalidateAll.d.ts +3 -0
- package/lib/controller/createInvalidateAll.d.ts.map +1 -0
- package/lib/controller/createInvalidateAll.js +8 -0
- package/lib/controller/createOptimistic.d.ts +10 -0
- package/lib/controller/createOptimistic.d.ts.map +1 -0
- package/lib/controller/createOptimistic.js +33 -0
- package/lib/controller/createReceive.d.ts +20 -0
- package/lib/controller/createReceive.d.ts.map +1 -0
- package/lib/controller/createReceive.js +36 -0
- package/lib/controller/createReset.d.ts +3 -0
- package/lib/controller/createReset.d.ts.map +1 -0
- package/lib/controller/createReset.js +8 -0
- package/lib/controller/createSubscription.d.ts +9 -0
- package/lib/controller/createSubscription.d.ts.map +1 -0
- package/lib/controller/createSubscription.js +30 -0
- package/lib/controller/types.d.ts +6 -0
- package/lib/controller/types.d.ts.map +1 -0
- package/lib/controller/types.js +2 -0
- package/lib/endpoint/index.d.ts +3 -0
- package/lib/endpoint/index.d.ts.map +1 -0
- package/lib/endpoint/index.js +2 -0
- package/lib/endpoint/shapes.d.ts +25 -0
- package/lib/endpoint/shapes.d.ts.map +1 -0
- package/lib/endpoint/shapes.js +2 -0
- package/lib/endpoint/types.d.ts +45 -0
- package/lib/endpoint/types.d.ts.map +1 -0
- package/lib/endpoint/types.js +2 -0
- package/lib/fsa.d.ts +41 -0
- package/lib/fsa.d.ts.map +1 -0
- package/lib/fsa.js +2 -0
- package/lib/index.d.ts +19 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +22 -0
- package/lib/internal.d.ts +4 -0
- package/lib/internal.d.ts.map +1 -0
- package/lib/internal.js +4 -0
- package/lib/legacyActions.d.ts +92 -0
- package/lib/legacyActions.d.ts.map +1 -0
- package/lib/legacyActions.js +2 -0
- package/lib/manager/ConnectionListener.d.ts +8 -0
- package/lib/manager/ConnectionListener.d.ts.map +1 -0
- package/lib/manager/ConnectionListener.js +2 -0
- package/lib/manager/DefaultConnectionListener.d.ts +20 -0
- package/lib/manager/DefaultConnectionListener.d.ts.map +1 -0
- package/lib/manager/DefaultConnectionListener.js +40 -0
- package/lib/manager/DevtoolsManager.d.ts +24 -0
- package/lib/manager/DevtoolsManager.d.ts.map +1 -0
- package/lib/manager/DevtoolsManager.js +74 -0
- package/lib/manager/LogoutManager.d.ts +25 -0
- package/lib/manager/LogoutManager.d.ts.map +1 -0
- package/lib/manager/LogoutManager.js +34 -0
- package/lib/manager/NetworkManager.d.ts +82 -0
- package/lib/manager/NetworkManager.d.ts.map +1 -0
- package/lib/manager/NetworkManager.js +295 -0
- package/lib/manager/PollingSubscription.d.ts +45 -0
- package/lib/manager/PollingSubscription.d.ts.map +1 -0
- package/lib/manager/PollingSubscription.js +159 -0
- package/lib/manager/SubscriptionManager.d.ts +55 -0
- package/lib/manager/SubscriptionManager.d.ts.map +1 -0
- package/lib/manager/SubscriptionManager.js +117 -0
- package/lib/manager/applyManager.d.ts +10 -0
- package/lib/manager/applyManager.d.ts.map +1 -0
- package/lib/manager/applyManager.js +23 -0
- package/lib/manager/devtoolsTypes.d.ts +205 -0
- package/lib/manager/devtoolsTypes.d.ts.map +1 -0
- package/lib/manager/devtoolsTypes.js +2 -0
- package/lib/manager/index.d.ts +8 -0
- package/lib/manager/index.d.ts.map +1 -0
- package/lib/manager/index.js +6 -0
- package/lib/middlewareTypes.d.ts +18 -0
- package/lib/middlewareTypes.d.ts.map +1 -0
- package/lib/middlewareTypes.js +2 -0
- package/lib/newActions.d.ts +85 -0
- package/lib/newActions.d.ts.map +1 -0
- package/lib/newActions.js +2 -0
- package/lib/next/Controller.d.ts +14 -0
- package/lib/next/Controller.d.ts.map +1 -0
- package/lib/next/Controller.js +24 -0
- package/lib/next/index.d.ts +3 -0
- package/lib/next/index.d.ts.map +1 -0
- package/lib/next/index.js +3 -0
- package/lib/previousActions.d.ts +91 -0
- package/lib/previousActions.d.ts.map +1 -0
- package/lib/previousActions.js +2 -0
- package/lib/state/RIC.d.ts +2 -0
- package/lib/state/RIC.js +3 -0
- package/lib/state/applyUpdatersToResults.d.ts +13 -0
- package/lib/state/applyUpdatersToResults.d.ts.map +1 -0
- package/lib/state/applyUpdatersToResults.js +7 -0
- package/lib/state/legacy-actions/createFetch.d.ts +19 -0
- package/lib/state/legacy-actions/createFetch.d.ts.map +1 -0
- package/lib/state/legacy-actions/createFetch.js +62 -0
- package/lib/state/legacy-actions/createReceive.d.ts +14 -0
- package/lib/state/legacy-actions/createReceive.d.ts.map +1 -0
- package/lib/state/legacy-actions/createReceive.js +37 -0
- package/lib/state/legacy-actions/createReceiveError.d.ts +9 -0
- package/lib/state/legacy-actions/createReceiveError.d.ts.map +1 -0
- package/lib/state/legacy-actions/createReceiveError.js +28 -0
- package/lib/state/legacy-actions/index.d.ts +4 -0
- package/lib/state/legacy-actions/index.d.ts.map +1 -0
- package/lib/state/legacy-actions/index.js +4 -0
- package/lib/state/reducer/createReducer.d.ts +7 -0
- package/lib/state/reducer/createReducer.d.ts.map +1 -0
- package/lib/state/reducer/createReducer.js +55 -0
- package/lib/state/reducer/fetchReducer.d.ts +4 -0
- package/lib/state/reducer/fetchReducer.d.ts.map +1 -0
- package/lib/state/reducer/fetchReducer.js +34 -0
- package/lib/state/reducer/invalidateReducer.d.ts +37 -0
- package/lib/state/reducer/invalidateReducer.d.ts.map +1 -0
- package/lib/state/reducer/invalidateReducer.js +34 -0
- package/lib/state/reducer/setReducer.d.ts +40 -0
- package/lib/state/reducer/setReducer.d.ts.map +1 -0
- package/lib/state/reducer/setReducer.js +119 -0
- package/lib/state/reducerInstance.d.ts +7 -0
- package/lib/state/reducerInstance.d.ts.map +1 -0
- package/lib/state/reducerInstance.js +9 -0
- package/lib/state/selectMeta.d.ts +3 -0
- package/lib/state/selectMeta.d.ts.map +1 -0
- package/lib/state/selectMeta.js +4 -0
- package/lib/types.d.ts +71 -0
- package/lib/types.d.ts.map +1 -0
- package/lib/types.js +8 -0
- package/node.mjs +1 -0
- package/package.json +127 -0
- package/src/actionTypes.ts +11 -0
- package/src/compatibleActions.ts +96 -0
- package/src/controller/BaseController.ts +508 -0
- package/src/controller/Controller.ts +32 -0
- package/src/controller/__tests__/Controller.ts +29 -0
- package/src/controller/__tests__/__snapshots__/getResponse.ts.snap +35 -0
- package/src/controller/__tests__/getResponse.ts +182 -0
- package/src/controller/createFetch.ts +54 -0
- package/src/controller/createInvalidate.ts +16 -0
- package/src/controller/createInvalidateAll.ts +11 -0
- package/src/controller/createOptimistic.ts +47 -0
- package/src/controller/createReceive.ts +85 -0
- package/src/controller/createReset.ts +9 -0
- package/src/controller/createSubscription.ts +39 -0
- package/src/controller/types.ts +22 -0
- package/src/endpoint/index.ts +14 -0
- package/src/endpoint/shapes.ts +53 -0
- package/src/endpoint/types.ts +72 -0
- package/src/fsa.ts +99 -0
- package/src/index.ts +61 -0
- package/src/internal.ts +3 -0
- package/src/legacyActions.ts +163 -0
- package/src/manager/ConnectionListener.ts +7 -0
- package/src/manager/DefaultConnectionListener.ts +54 -0
- package/src/manager/DevtoolsManager.ts +99 -0
- package/src/manager/LogoutManager.ts +57 -0
- package/src/manager/NetworkManager.ts +346 -0
- package/src/manager/PollingSubscription.ts +190 -0
- package/src/manager/SubscriptionManager.ts +156 -0
- package/src/manager/__tests__/__snapshots__/pollingSubscription-endpoint.ts.snap +49 -0
- package/src/manager/__tests__/__snapshots__/pollingSubscription.ts.snap +43 -0
- package/src/manager/__tests__/logoutManager.ts +112 -0
- package/src/manager/__tests__/manager.ts +44 -0
- package/src/manager/__tests__/networkManager-legacy.ts +394 -0
- package/src/manager/__tests__/networkManager.ts +426 -0
- package/src/manager/__tests__/pollingSubscription-endpoint.ts +423 -0
- package/src/manager/__tests__/pollingSubscription.ts +313 -0
- package/src/manager/__tests__/subscriptionManager.ts +208 -0
- package/src/manager/applyManager.ts +33 -0
- package/src/manager/devtoolsTypes.ts +210 -0
- package/src/manager/index.ts +7 -0
- package/src/middlewareTypes.ts +49 -0
- package/src/newActions.ts +140 -0
- package/src/next/Controller.ts +39 -0
- package/src/next/index.ts +2 -0
- package/src/package.json +1 -0
- package/src/previousActions.ts +159 -0
- package/src/state/RIC.d.ts +2 -0
- package/src/state/RIC.js +5 -0
- package/src/state/__tests__/RIC.web.ts +16 -0
- package/src/state/__tests__/__snapshots__/reducer.ts.snap +56 -0
- package/src/state/__tests__/applyUpdatersToResults.ts +40 -0
- package/src/state/__tests__/reducer.ts +868 -0
- package/src/state/applyUpdatersToResults.ts +29 -0
- package/src/state/legacy-actions/createFetch.ts +95 -0
- package/src/state/legacy-actions/createReceive.ts +68 -0
- package/src/state/legacy-actions/createReceiveError.ts +43 -0
- package/src/state/legacy-actions/index.ts +3 -0
- package/src/state/reducer/createReducer.ts +80 -0
- package/src/state/reducer/fetchReducer.ts +48 -0
- package/src/state/reducer/invalidateReducer.ts +39 -0
- package/src/state/reducer/setReducer.ts +157 -0
- package/src/state/reducerInstance.ts +14 -0
- package/src/state/selectMeta.ts +8 -0
- package/src/types.ts +125 -0
- package/ts3.4/actionTypes.d.ts +11 -0
- package/ts3.4/compatibleActions.d.ts +47 -0
- package/ts3.4/controller/BaseController.d.ts +170 -0
- package/ts3.4/controller/Controller.d.ts +14 -0
- package/ts3.4/controller/createFetch.d.ts +14 -0
- package/ts3.4/controller/createInvalidate.d.ts +8 -0
- package/ts3.4/controller/createInvalidateAll.d.ts +3 -0
- package/ts3.4/controller/createOptimistic.d.ts +12 -0
- package/ts3.4/controller/createReceive.d.ts +24 -0
- package/ts3.4/controller/createReset.d.ts +3 -0
- package/ts3.4/controller/createSubscription.d.ts +13 -0
- package/ts3.4/controller/types.d.ts +6 -0
- package/ts3.4/endpoint/index.d.ts +3 -0
- package/ts3.4/endpoint/shapes.d.ts +25 -0
- package/ts3.4/endpoint/types.d.ts +45 -0
- package/ts3.4/fsa.d.ts +41 -0
- package/ts3.4/index.d.ts +22 -0
- package/ts3.4/internal.d.ts +4 -0
- package/ts3.4/legacyActions.d.ts +95 -0
- package/ts3.4/manager/ConnectionListener.d.ts +8 -0
- package/ts3.4/manager/DefaultConnectionListener.d.ts +20 -0
- package/ts3.4/manager/DevtoolsManager.d.ts +24 -0
- package/ts3.4/manager/LogoutManager.d.ts +25 -0
- package/ts3.4/manager/NetworkManager.d.ts +82 -0
- package/ts3.4/manager/PollingSubscription.d.ts +45 -0
- package/ts3.4/manager/SubscriptionManager.d.ts +55 -0
- package/ts3.4/manager/applyManager.d.ts +10 -0
- package/ts3.4/manager/devtoolsTypes.d.ts +205 -0
- package/ts3.4/manager/index.d.ts +8 -0
- package/ts3.4/middlewareTypes.d.ts +18 -0
- package/ts3.4/newActions.d.ts +88 -0
- package/ts3.4/next/Controller.d.ts +14 -0
- package/ts3.4/next/index.d.ts +3 -0
- package/ts3.4/previousActions.d.ts +94 -0
- package/ts3.4/state/RIC.d.ts +2 -0
- package/ts3.4/state/applyUpdatersToResults.d.ts +13 -0
- package/ts3.4/state/legacy-actions/createFetch.d.ts +19 -0
- package/ts3.4/state/legacy-actions/createReceive.d.ts +14 -0
- package/ts3.4/state/legacy-actions/createReceiveError.d.ts +9 -0
- package/ts3.4/state/legacy-actions/index.d.ts +4 -0
- package/ts3.4/state/reducer/createReducer.d.ts +7 -0
- package/ts3.4/state/reducer/fetchReducer.d.ts +4 -0
- package/ts3.4/state/reducer/invalidateReducer.d.ts +37 -0
- package/ts3.4/state/reducer/setReducer.d.ts +40 -0
- package/ts3.4/state/reducerInstance.d.ts +7 -0
- package/ts3.4/state/selectMeta.d.ts +3 -0
- package/ts3.4/types.d.ts +73 -0
- package/typescript.svg +8 -0
|
@@ -0,0 +1,508 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ErrorTypes,
|
|
3
|
+
SnapshotInterface,
|
|
4
|
+
DenormalizeCache,
|
|
5
|
+
Schema,
|
|
6
|
+
} from '@data-client/normalizr';
|
|
7
|
+
import {
|
|
8
|
+
WeakEntityMap,
|
|
9
|
+
ExpiryStatus,
|
|
10
|
+
EndpointInterface,
|
|
11
|
+
FetchFunction,
|
|
12
|
+
ResolveType,
|
|
13
|
+
DenormalizeNullable,
|
|
14
|
+
Path,
|
|
15
|
+
denormalizeCached,
|
|
16
|
+
isEntity,
|
|
17
|
+
} from '@data-client/normalizr';
|
|
18
|
+
import { inferResults, validateInference } from '@data-client/normalizr';
|
|
19
|
+
|
|
20
|
+
import createInvalidate from './createInvalidate.js';
|
|
21
|
+
import createInvalidateAll from './createInvalidateAll.js';
|
|
22
|
+
import createReceive from './createReceive.js';
|
|
23
|
+
import createReset from './createReset.js';
|
|
24
|
+
import {
|
|
25
|
+
createUnsubscription,
|
|
26
|
+
createSubscription,
|
|
27
|
+
} from './createSubscription.js';
|
|
28
|
+
import type { EndpointUpdateFunction } from './types.js';
|
|
29
|
+
import { initialState } from '../state/reducer/createReducer.js';
|
|
30
|
+
import selectMeta from '../state/selectMeta.js';
|
|
31
|
+
import type {
|
|
32
|
+
ActionTypes as BroadActionTypes,
|
|
33
|
+
CombinedActionTypes,
|
|
34
|
+
State,
|
|
35
|
+
} from '../types.js';
|
|
36
|
+
|
|
37
|
+
export type GenericDispatch = (value: any) => Promise<void>;
|
|
38
|
+
export type CompatibleDispatch = (value: CombinedActionTypes) => Promise<void>;
|
|
39
|
+
type PreviousDispatch = (value: BroadActionTypes) => Promise<void>;
|
|
40
|
+
|
|
41
|
+
interface ConstructorProps<D extends GenericDispatch = CompatibleDispatch> {
|
|
42
|
+
dispatch?: D;
|
|
43
|
+
getState?: () => State<unknown>;
|
|
44
|
+
globalCache?: DenormalizeCache;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const unsetDispatch = (action: unknown): Promise<void> => {
|
|
48
|
+
throw new Error(
|
|
49
|
+
`Dispatching while constructing your middleware is not allowed. ` +
|
|
50
|
+
`Other middleware would not be applied to this dispatch.`,
|
|
51
|
+
);
|
|
52
|
+
};
|
|
53
|
+
const unsetState = (): State<unknown> => {
|
|
54
|
+
// This is only the value until it is set by the CacheProvider
|
|
55
|
+
/* istanbul ignore next */
|
|
56
|
+
return initialState;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Imperative control of Rest Hooks store
|
|
61
|
+
* @see https://resthooks.io/docs/api/Controller
|
|
62
|
+
*/
|
|
63
|
+
export default class Controller<
|
|
64
|
+
D extends GenericDispatch = CompatibleDispatch,
|
|
65
|
+
> {
|
|
66
|
+
/**
|
|
67
|
+
* Dispatches an action to Rest Hooks reducer.
|
|
68
|
+
*
|
|
69
|
+
* @see https://resthooks.io/docs/api/Controller#dispatch
|
|
70
|
+
*/
|
|
71
|
+
declare readonly dispatch: D;
|
|
72
|
+
/**
|
|
73
|
+
* Gets the latest state snapshot that is fully committed.
|
|
74
|
+
*
|
|
75
|
+
* This can be useful for imperative use-cases like event handlers.
|
|
76
|
+
* This should *not* be used to render; instead useSuspense() or useCache()
|
|
77
|
+
* @see https://resthooks.io/docs/api/Controller#getState
|
|
78
|
+
*/
|
|
79
|
+
declare readonly getState: () => State<unknown>;
|
|
80
|
+
declare readonly globalCache: DenormalizeCache;
|
|
81
|
+
|
|
82
|
+
constructor({
|
|
83
|
+
dispatch = unsetDispatch as any,
|
|
84
|
+
getState = unsetState,
|
|
85
|
+
globalCache = {
|
|
86
|
+
entities: {},
|
|
87
|
+
results: {},
|
|
88
|
+
},
|
|
89
|
+
}: ConstructorProps<D> = {}) {
|
|
90
|
+
this.dispatch = dispatch;
|
|
91
|
+
this.getState = getState;
|
|
92
|
+
this.globalCache = globalCache;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/*************** Action Dispatchers ***************/
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Forces refetching and suspense on useSuspense with the same Endpoint and parameters.
|
|
99
|
+
* @see https://resthooks.io/docs/api/Controller#invalidate
|
|
100
|
+
*/
|
|
101
|
+
invalidate = <E extends EndpointInterface>(
|
|
102
|
+
endpoint: E,
|
|
103
|
+
...args: readonly [...Parameters<E>] | readonly [null]
|
|
104
|
+
): Promise<void> =>
|
|
105
|
+
args[0] !== null
|
|
106
|
+
? this.dispatch(
|
|
107
|
+
createInvalidate(endpoint, {
|
|
108
|
+
args: args as readonly [...Parameters<E>],
|
|
109
|
+
}),
|
|
110
|
+
)
|
|
111
|
+
: Promise.resolve();
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Forces refetching and suspense on useSuspense on all matching endpoint result keys.
|
|
115
|
+
* @see https://resthooks.io/docs/api/Controller#invalidateAll
|
|
116
|
+
*/
|
|
117
|
+
invalidateAll = (options: { testKey: (key: string) => boolean }) =>
|
|
118
|
+
this.dispatch(createInvalidateAll((key: string) => options.testKey(key)));
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Resets the entire Rest Hooks cache. All inflight requests will not resolve.
|
|
122
|
+
* @see https://resthooks.io/docs/api/Controller#resetEntireStore
|
|
123
|
+
*/
|
|
124
|
+
resetEntireStore = (): Promise<void> => this.dispatch(createReset());
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Stores response in cache for given Endpoint and args.
|
|
128
|
+
* @see https://resthooks.io/docs/api/Controller#set
|
|
129
|
+
*/
|
|
130
|
+
setResponse = <
|
|
131
|
+
E extends EndpointInterface & {
|
|
132
|
+
update?: EndpointUpdateFunction<E>;
|
|
133
|
+
},
|
|
134
|
+
>(
|
|
135
|
+
endpoint: E,
|
|
136
|
+
...rest: readonly [...Parameters<E>, any]
|
|
137
|
+
): Promise<void> => {
|
|
138
|
+
const response: ResolveType<E> = rest[rest.length - 1];
|
|
139
|
+
const action = createReceive(endpoint, {
|
|
140
|
+
args: rest.slice(0, rest.length - 1) as Parameters<E>,
|
|
141
|
+
response,
|
|
142
|
+
});
|
|
143
|
+
return this.dispatch(action);
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
// TODO: deprecate
|
|
147
|
+
/**
|
|
148
|
+
* Another name for setResponse
|
|
149
|
+
* @see https://resthooks.io/docs/api/Controller#setResponse
|
|
150
|
+
*/
|
|
151
|
+
/* istanbul ignore next */ receive = <
|
|
152
|
+
E extends EndpointInterface & {
|
|
153
|
+
update?: EndpointUpdateFunction<E>;
|
|
154
|
+
},
|
|
155
|
+
>(
|
|
156
|
+
endpoint: E,
|
|
157
|
+
...rest: readonly [...Parameters<E>, any]
|
|
158
|
+
): Promise<void> => {
|
|
159
|
+
/* istanbul ignore next */
|
|
160
|
+
return this.setResponse(endpoint, ...rest);
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Stores the result of Endpoint and args as the error provided.
|
|
165
|
+
* @see https://resthooks.io/docs/api/Controller#setError
|
|
166
|
+
*/
|
|
167
|
+
setError = <
|
|
168
|
+
E extends EndpointInterface & {
|
|
169
|
+
update?: EndpointUpdateFunction<E>;
|
|
170
|
+
},
|
|
171
|
+
>(
|
|
172
|
+
endpoint: E,
|
|
173
|
+
...rest: readonly [...Parameters<E>, Error]
|
|
174
|
+
): Promise<void> => {
|
|
175
|
+
const response: Error = rest[rest.length - 1];
|
|
176
|
+
const action = createReceive(endpoint, {
|
|
177
|
+
args: rest.slice(0, rest.length - 1) as Parameters<E>,
|
|
178
|
+
response,
|
|
179
|
+
error: true,
|
|
180
|
+
});
|
|
181
|
+
return this.dispatch(action);
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
// TODO: deprecate
|
|
185
|
+
/**
|
|
186
|
+
* Another name for setError
|
|
187
|
+
* @see https://resthooks.io/docs/api/Controller#setError
|
|
188
|
+
*/
|
|
189
|
+
/* istanbul ignore next */ receiveError = <
|
|
190
|
+
E extends EndpointInterface & {
|
|
191
|
+
update?: EndpointUpdateFunction<E>;
|
|
192
|
+
},
|
|
193
|
+
>(
|
|
194
|
+
endpoint: E,
|
|
195
|
+
...rest: readonly [...Parameters<E>, Error]
|
|
196
|
+
): Promise<void> => {
|
|
197
|
+
/* istanbul ignore next */
|
|
198
|
+
return this.setError(endpoint, ...rest);
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Resolves an inflight fetch. `fetchedAt` should `fetch`'s `createdAt`
|
|
203
|
+
* @see https://resthooks.io/docs/api/Controller#resolve
|
|
204
|
+
*/
|
|
205
|
+
resolve = <
|
|
206
|
+
E extends EndpointInterface & {
|
|
207
|
+
update?: EndpointUpdateFunction<E>;
|
|
208
|
+
},
|
|
209
|
+
>(
|
|
210
|
+
endpoint: E,
|
|
211
|
+
meta:
|
|
212
|
+
| {
|
|
213
|
+
args: readonly [...Parameters<E>];
|
|
214
|
+
response: Error;
|
|
215
|
+
fetchedAt: number;
|
|
216
|
+
error: true;
|
|
217
|
+
}
|
|
218
|
+
| {
|
|
219
|
+
args: readonly [...Parameters<E>];
|
|
220
|
+
response: any;
|
|
221
|
+
fetchedAt: number;
|
|
222
|
+
error?: false;
|
|
223
|
+
},
|
|
224
|
+
): Promise<void> => {
|
|
225
|
+
return this.dispatch(createReceive(endpoint, meta as any));
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Marks a new subscription to a given Endpoint.
|
|
230
|
+
* @see https://resthooks.io/docs/api/Controller#subscribe
|
|
231
|
+
*/
|
|
232
|
+
subscribe = <
|
|
233
|
+
E extends EndpointInterface<
|
|
234
|
+
FetchFunction,
|
|
235
|
+
Schema | undefined,
|
|
236
|
+
undefined | false
|
|
237
|
+
>,
|
|
238
|
+
>(
|
|
239
|
+
endpoint: E,
|
|
240
|
+
...args: readonly [...Parameters<E>] | readonly [null]
|
|
241
|
+
): Promise<void> =>
|
|
242
|
+
args[0] !== null
|
|
243
|
+
? this.dispatch(
|
|
244
|
+
createSubscription(endpoint, {
|
|
245
|
+
args: args as readonly [...Parameters<E>],
|
|
246
|
+
}),
|
|
247
|
+
)
|
|
248
|
+
: Promise.resolve();
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Marks completion of subscription to a given Endpoint.
|
|
252
|
+
* @see https://resthooks.io/docs/api/Controller#unsubscribe
|
|
253
|
+
*/
|
|
254
|
+
unsubscribe = <
|
|
255
|
+
E extends EndpointInterface<
|
|
256
|
+
FetchFunction,
|
|
257
|
+
Schema | undefined,
|
|
258
|
+
undefined | false
|
|
259
|
+
>,
|
|
260
|
+
>(
|
|
261
|
+
endpoint: E,
|
|
262
|
+
...args: readonly [...Parameters<E>] | readonly [null]
|
|
263
|
+
): Promise<void> =>
|
|
264
|
+
args[0] !== null
|
|
265
|
+
? this.dispatch(
|
|
266
|
+
createUnsubscription(endpoint, {
|
|
267
|
+
args: args as readonly [...Parameters<E>],
|
|
268
|
+
}),
|
|
269
|
+
)
|
|
270
|
+
: Promise.resolve();
|
|
271
|
+
|
|
272
|
+
/*************** More ***************/
|
|
273
|
+
|
|
274
|
+
/* TODO:
|
|
275
|
+
abort = <E extends EndpointInterface>(
|
|
276
|
+
endpoint: E,
|
|
277
|
+
...args: readonly [...Parameters<E>]
|
|
278
|
+
): Promise<void>
|
|
279
|
+
*/
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Gets a snapshot (https://resthooks.io/docs/api/Snapshot)
|
|
283
|
+
* @see https://resthooks.io/docs/api/Controller#snapshot
|
|
284
|
+
*/
|
|
285
|
+
snapshot = (state: State<unknown>, fetchedAt?: number): SnapshotInterface => {
|
|
286
|
+
return new Snapshot(this, state, fetchedAt);
|
|
287
|
+
};
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* Gets the error, if any, for a given endpoint. Returns undefined for no errors.
|
|
291
|
+
* @see https://resthooks.io/docs/api/Controller#getError
|
|
292
|
+
*/
|
|
293
|
+
getError = <
|
|
294
|
+
E extends Pick<EndpointInterface, 'key'>,
|
|
295
|
+
Args extends readonly [...Parameters<E['key']>] | readonly [null],
|
|
296
|
+
>(
|
|
297
|
+
endpoint: E,
|
|
298
|
+
...rest: [...Args, State<unknown>]
|
|
299
|
+
): ErrorTypes | undefined => {
|
|
300
|
+
if (rest[0] === null) return;
|
|
301
|
+
const state = rest[rest.length - 1] as State<unknown>;
|
|
302
|
+
// this is typescript generics breaking
|
|
303
|
+
const args: any = rest.slice(0, rest.length - 1) as Parameters<E['key']>;
|
|
304
|
+
const key = endpoint.key(...args);
|
|
305
|
+
|
|
306
|
+
const meta = selectMeta(state, key);
|
|
307
|
+
const results = state.results[key];
|
|
308
|
+
|
|
309
|
+
if (results !== undefined && meta?.errorPolicy === 'soft') return;
|
|
310
|
+
|
|
311
|
+
return meta?.error as any;
|
|
312
|
+
};
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Gets the (globally referentially stable) response for a given endpoint/args pair from state given.
|
|
316
|
+
* @see https://resthooks.io/docs/api/Controller#getResponse
|
|
317
|
+
*/
|
|
318
|
+
getResponse = <
|
|
319
|
+
E extends Pick<EndpointInterface, 'key' | 'schema' | 'invalidIfStale'>,
|
|
320
|
+
Args extends readonly [...Parameters<E['key']>] | readonly [null],
|
|
321
|
+
>(
|
|
322
|
+
endpoint: E,
|
|
323
|
+
...rest: [...Args, State<unknown>]
|
|
324
|
+
): {
|
|
325
|
+
data: DenormalizeNullable<E['schema']>;
|
|
326
|
+
expiryStatus: ExpiryStatus;
|
|
327
|
+
expiresAt: number;
|
|
328
|
+
} => {
|
|
329
|
+
const state = rest[rest.length - 1] as State<unknown>;
|
|
330
|
+
// this is typescript generics breaking
|
|
331
|
+
const args: any = rest.slice(0, rest.length - 1) as Parameters<E['key']>;
|
|
332
|
+
const isActive = args.length !== 1 || args[0] !== null;
|
|
333
|
+
const key = isActive ? endpoint.key(...args) : '';
|
|
334
|
+
const cacheResults = isActive ? state.results[key] : undefined;
|
|
335
|
+
const schema = endpoint.schema;
|
|
336
|
+
const meta = selectMeta(state, key);
|
|
337
|
+
let expiresAt = meta?.expiresAt;
|
|
338
|
+
|
|
339
|
+
let invalidResults = false;
|
|
340
|
+
let results;
|
|
341
|
+
if (cacheResults === undefined && endpoint.schema !== undefined) {
|
|
342
|
+
results = inferResults(
|
|
343
|
+
endpoint.schema,
|
|
344
|
+
args,
|
|
345
|
+
state.indexes,
|
|
346
|
+
state.entities,
|
|
347
|
+
);
|
|
348
|
+
invalidResults = !validateInference(results);
|
|
349
|
+
if (!expiresAt && invalidResults) expiresAt = 1;
|
|
350
|
+
} else {
|
|
351
|
+
results = cacheResults;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
if (!isActive) {
|
|
355
|
+
return {
|
|
356
|
+
data: results as any,
|
|
357
|
+
expiryStatus: ExpiryStatus.Valid,
|
|
358
|
+
expiresAt: Infinity,
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
if (!endpoint.schema || !schemaHasEntity(endpoint.schema)) {
|
|
363
|
+
return {
|
|
364
|
+
data: results,
|
|
365
|
+
expiryStatus: meta?.invalidated
|
|
366
|
+
? ExpiryStatus.Invalid
|
|
367
|
+
: cacheResults && !endpoint.invalidIfStale
|
|
368
|
+
? ExpiryStatus.Valid
|
|
369
|
+
: ExpiryStatus.InvalidIfStale,
|
|
370
|
+
expiresAt: expiresAt || 0,
|
|
371
|
+
} as {
|
|
372
|
+
data: DenormalizeNullable<E['schema']>;
|
|
373
|
+
expiryStatus: ExpiryStatus;
|
|
374
|
+
expiresAt: number;
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
// Warn users with bad configurations
|
|
379
|
+
/* istanbul ignore next */
|
|
380
|
+
if (process.env.NODE_ENV !== 'production' && schema && isEntity(schema)) {
|
|
381
|
+
if (Array.isArray(results)) {
|
|
382
|
+
throw new Error(
|
|
383
|
+
`fetch key ${key} has list results when single result is expected`,
|
|
384
|
+
);
|
|
385
|
+
}
|
|
386
|
+
if (typeof results === 'object') {
|
|
387
|
+
throw new Error(
|
|
388
|
+
`fetch key ${key} has object results when entity's primary key (string) result is expected`,
|
|
389
|
+
);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
if (!this.globalCache.results[key])
|
|
394
|
+
this.globalCache.results[key] = new WeakEntityMap();
|
|
395
|
+
|
|
396
|
+
// second argument is false if any entities are missing
|
|
397
|
+
// eslint-disable-next-line prefer-const
|
|
398
|
+
const { data, paths } = denormalizeCached(
|
|
399
|
+
results,
|
|
400
|
+
schema,
|
|
401
|
+
state.entities,
|
|
402
|
+
this.globalCache.entities,
|
|
403
|
+
this.globalCache.results[key],
|
|
404
|
+
args,
|
|
405
|
+
) as { data: DenormalizeNullable<E['schema']>; paths: Path[] };
|
|
406
|
+
const invalidDenormalize = typeof data === 'symbol';
|
|
407
|
+
|
|
408
|
+
// fallback to entity expiry time
|
|
409
|
+
if (!expiresAt) {
|
|
410
|
+
expiresAt = entityExpiresAt(paths, state.entityMeta);
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
// https://resthooks.io/docs/concepts/expiry-policy#expiry-status
|
|
414
|
+
// we don't track the difference between stale or fresh because that is tied to triggering
|
|
415
|
+
// conditions
|
|
416
|
+
const expiryStatus =
|
|
417
|
+
meta?.invalidated || (invalidDenormalize && !meta?.error)
|
|
418
|
+
? ExpiryStatus.Invalid
|
|
419
|
+
: invalidDenormalize || endpoint.invalidIfStale || invalidResults
|
|
420
|
+
? ExpiryStatus.InvalidIfStale
|
|
421
|
+
: ExpiryStatus.Valid;
|
|
422
|
+
|
|
423
|
+
return { data, expiryStatus, expiresAt };
|
|
424
|
+
};
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
// benchmark: https://www.measurethat.net/Benchmarks/Show/24691/0/min-reducer-vs-imperative-with-paths
|
|
428
|
+
// earliest expiry dictates age
|
|
429
|
+
function entityExpiresAt(
|
|
430
|
+
paths: Path[],
|
|
431
|
+
entityMeta: {
|
|
432
|
+
readonly [entityKey: string]: {
|
|
433
|
+
readonly [pk: string]: {
|
|
434
|
+
readonly date: number;
|
|
435
|
+
readonly expiresAt: number;
|
|
436
|
+
readonly fetchedAt: number; // This is only the value until it is set by the CacheProvider
|
|
437
|
+
};
|
|
438
|
+
};
|
|
439
|
+
},
|
|
440
|
+
) {
|
|
441
|
+
let expiresAt = Infinity;
|
|
442
|
+
for (const { pk, key } of paths) {
|
|
443
|
+
const entityExpiry = entityMeta[key]?.[pk]?.expiresAt;
|
|
444
|
+
// expiresAt will always resolve to false with any comparison
|
|
445
|
+
if (entityExpiry < expiresAt) expiresAt = entityExpiry;
|
|
446
|
+
}
|
|
447
|
+
return expiresAt;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
/** Determine whether the schema has any entities.
|
|
451
|
+
*
|
|
452
|
+
* Without entities, denormalization is not needed, and results should not be inferred.
|
|
453
|
+
*/
|
|
454
|
+
function schemaHasEntity(schema: Schema): boolean {
|
|
455
|
+
if (isEntity(schema)) return true;
|
|
456
|
+
if (Array.isArray(schema))
|
|
457
|
+
return schema.length !== 0 && schemaHasEntity(schema[0]);
|
|
458
|
+
if (schema && (typeof schema === 'object' || typeof schema === 'function')) {
|
|
459
|
+
const nestedSchema =
|
|
460
|
+
'schema' in schema ? (schema.schema as Record<string, Schema>) : schema;
|
|
461
|
+
if (typeof nestedSchema === 'function') {
|
|
462
|
+
return schemaHasEntity(nestedSchema);
|
|
463
|
+
}
|
|
464
|
+
return Object.values(nestedSchema).some(x => schemaHasEntity(x));
|
|
465
|
+
}
|
|
466
|
+
return false;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
export type { ErrorTypes };
|
|
470
|
+
|
|
471
|
+
class Snapshot<T = unknown> implements SnapshotInterface {
|
|
472
|
+
private state: State<T>;
|
|
473
|
+
private controller: Controller;
|
|
474
|
+
readonly fetchedAt: number;
|
|
475
|
+
|
|
476
|
+
constructor(controller: Controller, state: State<T>, fetchedAt = 0) {
|
|
477
|
+
this.state = state;
|
|
478
|
+
this.controller = controller;
|
|
479
|
+
this.fetchedAt = fetchedAt;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
/*************** Data Access ***************/
|
|
483
|
+
/** @see https://resthooks.io/docs/api/Snapshot#getResponse */
|
|
484
|
+
getResponse = <
|
|
485
|
+
E extends Pick<EndpointInterface, 'key' | 'schema' | 'invalidIfStale'>,
|
|
486
|
+
Args extends readonly [...Parameters<E['key']>],
|
|
487
|
+
>(
|
|
488
|
+
endpoint: E,
|
|
489
|
+
...args: Args
|
|
490
|
+
): {
|
|
491
|
+
data: DenormalizeNullable<E['schema']>;
|
|
492
|
+
expiryStatus: ExpiryStatus;
|
|
493
|
+
expiresAt: number;
|
|
494
|
+
} => {
|
|
495
|
+
return this.controller.getResponse(endpoint, ...args, this.state);
|
|
496
|
+
};
|
|
497
|
+
|
|
498
|
+
/** @see https://resthooks.io/docs/api/Snapshot#getError */
|
|
499
|
+
getError = <
|
|
500
|
+
E extends Pick<EndpointInterface, 'key'>,
|
|
501
|
+
Args extends readonly [...Parameters<E['key']>],
|
|
502
|
+
>(
|
|
503
|
+
endpoint: E,
|
|
504
|
+
...args: Args
|
|
505
|
+
): ErrorTypes | undefined => {
|
|
506
|
+
return this.controller.getError(endpoint, ...args, this.state);
|
|
507
|
+
};
|
|
508
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { EndpointInterface } from '@data-client/normalizr';
|
|
2
|
+
|
|
3
|
+
import BaseController, {
|
|
4
|
+
CompatibleDispatch,
|
|
5
|
+
GenericDispatch,
|
|
6
|
+
} from './BaseController.js';
|
|
7
|
+
import createFetch from './createFetch.js';
|
|
8
|
+
import type { EndpointUpdateFunction } from './types.js';
|
|
9
|
+
|
|
10
|
+
export default class Controller<
|
|
11
|
+
D extends GenericDispatch = CompatibleDispatch,
|
|
12
|
+
> extends BaseController<D> {
|
|
13
|
+
/**
|
|
14
|
+
* Fetches the endpoint with given args, updating the Rest Hooks cache with the response or error upon completion.
|
|
15
|
+
* @see https://resthooks.io/docs/api/Controller#fetch
|
|
16
|
+
*/
|
|
17
|
+
fetch = <
|
|
18
|
+
E extends EndpointInterface & { update?: EndpointUpdateFunction<E> },
|
|
19
|
+
>(
|
|
20
|
+
endpoint: E,
|
|
21
|
+
...args: readonly [...Parameters<E>]
|
|
22
|
+
): ReturnType<E> => {
|
|
23
|
+
const action = createFetch(endpoint, {
|
|
24
|
+
args,
|
|
25
|
+
});
|
|
26
|
+
this.dispatch(action);
|
|
27
|
+
|
|
28
|
+
return action.meta.promise as ReturnType<E>;
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export * from './BaseController.js';
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Endpoint, Entity } from '@data-client/endpoint';
|
|
2
|
+
import { CoolerArticleResource } from '__tests__/new';
|
|
3
|
+
|
|
4
|
+
import { ExpiryStatus } from '../..';
|
|
5
|
+
import { initialState } from '../../state/reducer/createReducer';
|
|
6
|
+
import Contoller from '../Controller';
|
|
7
|
+
|
|
8
|
+
function ignoreError(e: Event) {
|
|
9
|
+
e.preventDefault();
|
|
10
|
+
}
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
if (typeof addEventListener === 'function')
|
|
13
|
+
addEventListener('error', ignoreError);
|
|
14
|
+
});
|
|
15
|
+
afterEach(() => {
|
|
16
|
+
if (typeof removeEventListener === 'function')
|
|
17
|
+
removeEventListener('error', ignoreError);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
describe('Controller', () => {
|
|
21
|
+
it('warns when dispatching during middleware setup', () => {
|
|
22
|
+
const controller = new Contoller();
|
|
23
|
+
expect(() =>
|
|
24
|
+
controller.fetch(CoolerArticleResource.get, { id: 5 }),
|
|
25
|
+
).toThrowErrorMatchingInlineSnapshot(
|
|
26
|
+
`"Dispatching while constructing your middleware is not allowed. Other middleware would not be applied to this dispatch."`,
|
|
27
|
+
);
|
|
28
|
+
});
|
|
29
|
+
});
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
+
|
|
3
|
+
exports[`Controller.getResponse() denormalizes schema with extra members but not set 1`] = `
|
|
4
|
+
{
|
|
5
|
+
"data": [
|
|
6
|
+
Tacos {
|
|
7
|
+
"id": "1",
|
|
8
|
+
"type": "foo",
|
|
9
|
+
},
|
|
10
|
+
Tacos {
|
|
11
|
+
"id": "2",
|
|
12
|
+
"type": "bar",
|
|
13
|
+
},
|
|
14
|
+
],
|
|
15
|
+
}
|
|
16
|
+
`;
|
|
17
|
+
|
|
18
|
+
exports[`Controller.getResponse() infers schema with extra members but not set 1`] = `
|
|
19
|
+
{
|
|
20
|
+
"data": Tacos {
|
|
21
|
+
"id": "1",
|
|
22
|
+
"type": "foo",
|
|
23
|
+
},
|
|
24
|
+
"extra": "",
|
|
25
|
+
"page": {
|
|
26
|
+
"complex": {
|
|
27
|
+
"complex": true,
|
|
28
|
+
"next": false,
|
|
29
|
+
},
|
|
30
|
+
"first": null,
|
|
31
|
+
"second": "",
|
|
32
|
+
"third": 0,
|
|
33
|
+
},
|
|
34
|
+
}
|
|
35
|
+
`;
|