@data-client/core 0.1.0 → 0.2.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.
Files changed (243) hide show
  1. package/dist/index.js +133 -409
  2. package/dist/index.umd.min.js +1 -1
  3. package/dist/next.js +61 -101
  4. package/legacy/actionTypes.js +2 -2
  5. package/legacy/controller/Controller.js +276 -6
  6. package/legacy/controller/createFetch.js +3 -14
  7. package/legacy/controller/createInvalidate.js +1 -1
  8. package/legacy/controller/createInvalidateAll.js +1 -1
  9. package/legacy/controller/createOptimistic.js +1 -7
  10. package/legacy/controller/createReset.js +1 -1
  11. package/legacy/controller/createSet.js +31 -0
  12. package/legacy/controller/createSubscription.js +3 -7
  13. package/legacy/index.js +2 -5
  14. package/legacy/internal.js +2 -2
  15. package/legacy/manager/DevtoolsManager.js +2 -2
  16. package/legacy/manager/LogoutManager.js +2 -2
  17. package/legacy/manager/NetworkManager.js +28 -59
  18. package/legacy/manager/PollingSubscription.js +18 -27
  19. package/legacy/manager/SubscriptionManager.js +16 -42
  20. package/legacy/middlewareTypes.js +1 -1
  21. package/legacy/newActions.js +1 -1
  22. package/legacy/next/index.js +3 -3
  23. package/legacy/state/reducer/createReducer.js +2 -6
  24. package/legacy/state/reducer/fetchReducer.js +3 -13
  25. package/legacy/state/reducer/invalidateReducer.js +1 -1
  26. package/legacy/state/reducer/setReducer.js +9 -16
  27. package/legacy/types.js +2 -6
  28. package/lib/actionTypes.d.ts +1 -0
  29. package/lib/actionTypes.d.ts.map +1 -1
  30. package/lib/actionTypes.js +2 -2
  31. package/lib/controller/Controller.d.ts +126 -6
  32. package/lib/controller/Controller.d.ts.map +1 -1
  33. package/lib/controller/Controller.js +276 -6
  34. package/lib/controller/createFetch.d.ts +2 -2
  35. package/lib/controller/createFetch.d.ts.map +1 -1
  36. package/lib/controller/createFetch.js +3 -14
  37. package/lib/controller/createInvalidate.d.ts +1 -1
  38. package/lib/controller/createInvalidate.d.ts.map +1 -1
  39. package/lib/controller/createInvalidate.js +1 -1
  40. package/lib/controller/createInvalidateAll.d.ts +1 -1
  41. package/lib/controller/createInvalidateAll.d.ts.map +1 -1
  42. package/lib/controller/createInvalidateAll.js +1 -1
  43. package/lib/controller/createOptimistic.d.ts +2 -2
  44. package/lib/controller/createOptimistic.d.ts.map +1 -1
  45. package/lib/controller/createOptimistic.js +1 -7
  46. package/lib/controller/createReset.d.ts +1 -1
  47. package/lib/controller/createReset.d.ts.map +1 -1
  48. package/lib/controller/createReset.js +1 -1
  49. package/lib/controller/{createReceive.d.ts → createSet.d.ts} +6 -6
  50. package/lib/controller/createSet.d.ts.map +1 -0
  51. package/lib/controller/createSet.js +31 -0
  52. package/lib/controller/createSubscription.d.ts +3 -3
  53. package/lib/controller/createSubscription.d.ts.map +1 -1
  54. package/lib/controller/createSubscription.js +3 -7
  55. package/lib/index.d.ts +2 -6
  56. package/lib/index.d.ts.map +1 -1
  57. package/lib/index.js +2 -5
  58. package/lib/internal.d.ts +1 -1
  59. package/lib/internal.d.ts.map +1 -1
  60. package/lib/internal.js +2 -2
  61. package/lib/manager/DevtoolsManager.d.ts +1 -1
  62. package/lib/manager/DevtoolsManager.js +2 -2
  63. package/lib/manager/LogoutManager.d.ts +4 -5
  64. package/lib/manager/LogoutManager.d.ts.map +1 -1
  65. package/lib/manager/LogoutManager.js +2 -2
  66. package/lib/manager/NetworkManager.d.ts +4 -5
  67. package/lib/manager/NetworkManager.d.ts.map +1 -1
  68. package/lib/manager/NetworkManager.js +28 -61
  69. package/lib/manager/PollingSubscription.d.ts +9 -9
  70. package/lib/manager/PollingSubscription.d.ts.map +1 -1
  71. package/lib/manager/PollingSubscription.js +18 -27
  72. package/lib/manager/SubscriptionManager.d.ts +10 -15
  73. package/lib/manager/SubscriptionManager.d.ts.map +1 -1
  74. package/lib/manager/SubscriptionManager.js +16 -42
  75. package/lib/middlewareTypes.d.ts +5 -5
  76. package/lib/middlewareTypes.d.ts.map +1 -1
  77. package/lib/middlewareTypes.js +1 -1
  78. package/lib/newActions.d.ts +26 -18
  79. package/lib/newActions.d.ts.map +1 -1
  80. package/lib/newActions.js +1 -1
  81. package/lib/next/index.d.ts +2 -2
  82. package/lib/next/index.d.ts.map +1 -1
  83. package/lib/next/index.js +3 -3
  84. package/lib/state/reducer/createReducer.d.ts.map +1 -1
  85. package/lib/state/reducer/createReducer.js +2 -6
  86. package/lib/state/reducer/fetchReducer.d.ts +1 -2
  87. package/lib/state/reducer/fetchReducer.d.ts.map +1 -1
  88. package/lib/state/reducer/fetchReducer.js +3 -14
  89. package/lib/state/reducer/invalidateReducer.d.ts +3 -4
  90. package/lib/state/reducer/invalidateReducer.d.ts.map +1 -1
  91. package/lib/state/reducer/invalidateReducer.js +1 -1
  92. package/lib/state/reducer/setReducer.d.ts +2 -38
  93. package/lib/state/reducer/setReducer.d.ts.map +1 -1
  94. package/lib/state/reducer/setReducer.js +9 -17
  95. package/lib/types.d.ts +9 -30
  96. package/lib/types.d.ts.map +1 -1
  97. package/lib/types.js +2 -6
  98. package/package.json +3 -3
  99. package/src/actionTypes.ts +1 -1
  100. package/src/controller/Controller.ts +491 -10
  101. package/src/controller/createFetch.ts +4 -19
  102. package/src/controller/createInvalidate.ts +1 -1
  103. package/src/controller/createInvalidateAll.ts +1 -1
  104. package/src/controller/createOptimistic.ts +3 -9
  105. package/src/controller/createReset.ts +1 -1
  106. package/src/controller/{createReceive.ts → createSet.ts} +9 -17
  107. package/src/controller/createSubscription.ts +3 -10
  108. package/src/index.ts +2 -16
  109. package/src/internal.ts +1 -1
  110. package/src/manager/DevtoolsManager.ts +1 -1
  111. package/src/manager/LogoutManager.ts +4 -5
  112. package/src/manager/NetworkManager.ts +31 -80
  113. package/src/manager/PollingSubscription.ts +26 -27
  114. package/src/manager/SubscriptionManager.ts +22 -54
  115. package/src/manager/__tests__/__snapshots__/pollingSubscription.ts.snap +10 -8
  116. package/src/manager/__tests__/logoutManager.ts +5 -5
  117. package/src/manager/__tests__/manager.ts +2 -4
  118. package/src/manager/__tests__/networkManager.ts +8 -42
  119. package/src/manager/__tests__/pollingSubscription.ts +259 -151
  120. package/src/manager/__tests__/subscriptionManager.ts +7 -13
  121. package/src/middlewareTypes.ts +5 -10
  122. package/src/newActions.ts +33 -23
  123. package/src/next/index.ts +2 -2
  124. package/src/state/__tests__/reducer.ts +59 -297
  125. package/src/state/reducer/createReducer.ts +3 -11
  126. package/src/state/reducer/fetchReducer.ts +5 -18
  127. package/src/state/reducer/invalidateReducer.ts +2 -2
  128. package/src/state/reducer/setReducer.ts +10 -22
  129. package/src/types.ts +9 -78
  130. package/ts3.4/actionTypes.d.ts +1 -0
  131. package/ts3.4/controller/Controller.d.ts +168 -6
  132. package/ts3.4/controller/createFetch.d.ts +2 -2
  133. package/ts3.4/controller/createInvalidate.d.ts +1 -1
  134. package/ts3.4/controller/createInvalidateAll.d.ts +1 -1
  135. package/ts3.4/controller/createOptimistic.d.ts +1 -1
  136. package/ts3.4/controller/createReset.d.ts +1 -1
  137. package/ts3.4/controller/{createReceive.d.ts → createSet.d.ts} +6 -6
  138. package/ts3.4/controller/createSubscription.d.ts +3 -3
  139. package/ts3.4/index.d.ts +2 -7
  140. package/ts3.4/internal.d.ts +1 -1
  141. package/ts3.4/manager/DevtoolsManager.d.ts +1 -1
  142. package/ts3.4/manager/LogoutManager.d.ts +4 -5
  143. package/ts3.4/manager/NetworkManager.d.ts +4 -5
  144. package/ts3.4/manager/PollingSubscription.d.ts +9 -9
  145. package/ts3.4/manager/SubscriptionManager.d.ts +10 -15
  146. package/ts3.4/middlewareTypes.d.ts +5 -5
  147. package/ts3.4/newActions.d.ts +26 -18
  148. package/ts3.4/next/index.d.ts +2 -2
  149. package/ts3.4/state/reducer/fetchReducer.d.ts +1 -2
  150. package/ts3.4/state/reducer/invalidateReducer.d.ts +3 -4
  151. package/ts3.4/state/reducer/setReducer.d.ts +2 -38
  152. package/ts3.4/types.d.ts +8 -30
  153. package/legacy/compatibleActions.js +0 -2
  154. package/legacy/controller/BaseController.js +0 -289
  155. package/legacy/controller/createReceive.js +0 -36
  156. package/legacy/endpoint/index.js +0 -2
  157. package/legacy/endpoint/shapes.js +0 -2
  158. package/legacy/endpoint/types.js +0 -2
  159. package/legacy/legacyActions.js +0 -2
  160. package/legacy/next/Controller.js +0 -24
  161. package/legacy/previousActions.js +0 -2
  162. package/legacy/state/applyUpdatersToResults.js +0 -4
  163. package/legacy/state/legacy-actions/createFetch.js +0 -62
  164. package/legacy/state/legacy-actions/createReceive.js +0 -37
  165. package/legacy/state/legacy-actions/createReceiveError.js +0 -28
  166. package/legacy/state/legacy-actions/index.js +0 -4
  167. package/legacy/state/reducerInstance.js +0 -9
  168. package/lib/compatibleActions.d.ts +0 -47
  169. package/lib/compatibleActions.d.ts.map +0 -1
  170. package/lib/compatibleActions.js +0 -2
  171. package/lib/controller/BaseController.d.ts +0 -128
  172. package/lib/controller/BaseController.d.ts.map +0 -1
  173. package/lib/controller/BaseController.js +0 -289
  174. package/lib/controller/createReceive.d.ts.map +0 -1
  175. package/lib/controller/createReceive.js +0 -36
  176. package/lib/endpoint/index.d.ts +0 -3
  177. package/lib/endpoint/index.d.ts.map +0 -1
  178. package/lib/endpoint/index.js +0 -2
  179. package/lib/endpoint/shapes.d.ts +0 -25
  180. package/lib/endpoint/shapes.d.ts.map +0 -1
  181. package/lib/endpoint/shapes.js +0 -2
  182. package/lib/endpoint/types.d.ts +0 -45
  183. package/lib/endpoint/types.d.ts.map +0 -1
  184. package/lib/endpoint/types.js +0 -2
  185. package/lib/legacyActions.d.ts +0 -92
  186. package/lib/legacyActions.d.ts.map +0 -1
  187. package/lib/legacyActions.js +0 -2
  188. package/lib/next/Controller.d.ts +0 -14
  189. package/lib/next/Controller.d.ts.map +0 -1
  190. package/lib/next/Controller.js +0 -24
  191. package/lib/previousActions.d.ts +0 -91
  192. package/lib/previousActions.d.ts.map +0 -1
  193. package/lib/previousActions.js +0 -2
  194. package/lib/state/applyUpdatersToResults.d.ts +0 -13
  195. package/lib/state/applyUpdatersToResults.d.ts.map +0 -1
  196. package/lib/state/applyUpdatersToResults.js +0 -7
  197. package/lib/state/legacy-actions/createFetch.d.ts +0 -19
  198. package/lib/state/legacy-actions/createFetch.d.ts.map +0 -1
  199. package/lib/state/legacy-actions/createFetch.js +0 -62
  200. package/lib/state/legacy-actions/createReceive.d.ts +0 -14
  201. package/lib/state/legacy-actions/createReceive.d.ts.map +0 -1
  202. package/lib/state/legacy-actions/createReceive.js +0 -37
  203. package/lib/state/legacy-actions/createReceiveError.d.ts +0 -9
  204. package/lib/state/legacy-actions/createReceiveError.d.ts.map +0 -1
  205. package/lib/state/legacy-actions/createReceiveError.js +0 -28
  206. package/lib/state/legacy-actions/index.d.ts +0 -4
  207. package/lib/state/legacy-actions/index.d.ts.map +0 -1
  208. package/lib/state/legacy-actions/index.js +0 -4
  209. package/lib/state/reducerInstance.d.ts +0 -7
  210. package/lib/state/reducerInstance.d.ts.map +0 -1
  211. package/lib/state/reducerInstance.js +0 -9
  212. package/src/compatibleActions.ts +0 -96
  213. package/src/controller/BaseController.ts +0 -508
  214. package/src/endpoint/index.ts +0 -14
  215. package/src/endpoint/shapes.ts +0 -53
  216. package/src/endpoint/types.ts +0 -72
  217. package/src/legacyActions.ts +0 -163
  218. package/src/manager/__tests__/__snapshots__/pollingSubscription-endpoint.ts.snap +0 -49
  219. package/src/manager/__tests__/networkManager-legacy.ts +0 -394
  220. package/src/manager/__tests__/pollingSubscription-endpoint.ts +0 -423
  221. package/src/next/Controller.ts +0 -39
  222. package/src/previousActions.ts +0 -159
  223. package/src/state/__tests__/applyUpdatersToResults.ts +0 -40
  224. package/src/state/applyUpdatersToResults.ts +0 -29
  225. package/src/state/legacy-actions/createFetch.ts +0 -95
  226. package/src/state/legacy-actions/createReceive.ts +0 -68
  227. package/src/state/legacy-actions/createReceiveError.ts +0 -43
  228. package/src/state/legacy-actions/index.ts +0 -3
  229. package/src/state/reducerInstance.ts +0 -14
  230. package/ts3.4/compatibleActions.d.ts +0 -47
  231. package/ts3.4/controller/BaseController.d.ts +0 -170
  232. package/ts3.4/endpoint/index.d.ts +0 -3
  233. package/ts3.4/endpoint/shapes.d.ts +0 -25
  234. package/ts3.4/endpoint/types.d.ts +0 -45
  235. package/ts3.4/legacyActions.d.ts +0 -95
  236. package/ts3.4/next/Controller.d.ts +0 -14
  237. package/ts3.4/previousActions.d.ts +0 -94
  238. package/ts3.4/state/applyUpdatersToResults.d.ts +0 -13
  239. package/ts3.4/state/legacy-actions/createFetch.d.ts +0 -19
  240. package/ts3.4/state/legacy-actions/createReceive.d.ts +0 -14
  241. package/ts3.4/state/legacy-actions/createReceiveError.d.ts +0 -9
  242. package/ts3.4/state/legacy-actions/index.d.ts +0 -4
  243. 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
- ): CompatibleSubscribeAction<E> {
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
- ): CompatibleUnsubscribeAction<E> {
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
- CompatibleDispatch,
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/createReceive.js';
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
@@ -1,3 +1,3 @@
1
- export { inferResults, DELETED } from '@data-client/normalizr';
1
+ export { inferResults, DELETED, INVALID } from '@data-client/normalizr';
2
2
  export { default as RIC } from './state/RIC.js';
3
3
  export { initialState } from './state/reducer/createReducer.js';
@@ -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://resthooks.io/docs/api/DevToolsManager
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 type { CombinedActionTypes } from '../types.js';
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://resthooks.io/docs/api/LogoutManager
8
+ * @see https://dataclient.io/docs/api/LogoutManager
10
9
  */
11
- export default class LogoutManager implements Manager<CombinedActionTypes> {
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: CombinedActionTypes) => Promise<void>;
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 { initialState } from '../internal.js';
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
- State,
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://resthooks.io/docs/api/NetworkManager
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, dispatch, controller);
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.meta.optimisticResponse !== undefined ||
69
- (action.endpoint?.getOptimisticResponse !== undefined &&
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
- // TODO: use only new action types
85
- this.handleReceive(createReceiveError(error, action.meta));
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
- const lastReset = this.controller.getState().lastReset;
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 && action.endpoint) {
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
- // we still check for controller in case someone didn't have type protection since this didn't always exist
213
- if (action.endpoint && this.controller) {
214
- this.controller.resolve(action.endpoint, {
215
- args: action.meta.args as any,
216
- response: data,
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
- if (action.endpoint && this.controller) {
240
- this.controller.resolve(action.endpoint, {
241
- args: action.meta.args as any,
242
- response: error,
243
- fetchedAt: createdAt,
244
- error: true,
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: ReceiveAction) {
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, Schema } from '@data-client/normalizr';
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, SubscriptionInit } from './SubscriptionManager.js';
6
- import createFetch from '../controller/createFetch.js';
7
- import type { State, Dispatch } from '../types.js';
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://resthooks.io/docs/api/PollingSubscription
14
+ * @see https://dataclient.io/docs/api/PollingSubscription
15
15
  */
16
16
  export default class PollingSubscription implements Subscription {
17
- protected declare readonly schema: Schema | undefined;
18
- protected declare readonly fetch: () => Promise<any>;
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 dispatch: Dispatch<any>;
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
- { key, schema, fetch, frequency, getState }: SubscriptionInit,
31
- dispatch: Dispatch<any>,
29
+ action: Omit<SubscribeAction, 'type'>,
30
+ controller: Controller,
32
31
  connectionListener?: ConnectionListener,
33
32
  ) {
34
- if (frequency === undefined)
33
+ if (action.endpoint.pollFrequency === undefined)
35
34
  throw new Error('frequency needed for polling subscription');
36
- this.schema = schema;
37
- this.fetch = fetch;
38
- this.frequency = frequency;
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.dispatch = dispatch;
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 endpoint: EndpointInterface = () => this.fetch();
127
- (endpoint as any).schema = this.schema;
128
- endpoint.key = () => this.key;
129
- (endpoint as any).dataExpiryLength = this.frequency / 2;
130
- (endpoint as any).errorExpiryLength = this.frequency / 10;
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
- const action = createFetch(endpoint, { args: [] });
132
+ endpoint.key = () => this.key;
133
133
  // stop any errors here from bubbling
134
- (action.meta.promise as Promise<any>).catch(e => null);
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 */
@@ -185,6 +184,6 @@ export default class PollingSubscription implements Subscription {
185
184
 
186
185
  /** Last fetch time */
187
186
  protected lastFetchTime() {
188
- return this.getState().meta[this.key]?.date ?? 0;
187
+ return this.controller.getState().meta[this.key]?.date ?? 0;
189
188
  }
190
189
  }
@@ -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 (init: SubscriptionInit, dispatch: Dispatch<any>): Subscription;
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://resthooks.io/docs/api/SubscriptionManager
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>({ dispatch, getState }: C) => {
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, dispatch, getState);
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, dispatch);
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: SubscribeAction,
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 (options.key in this.subscriptions) {
115
- this.subscriptions[options.key].add(options.frequency);
84
+ if (key in this.subscriptions) {
85
+ const frequency = action.endpoint.pollFrequency;
86
+ this.subscriptions[key].add(frequency);
116
87
  } else {
117
- this.subscriptions[options.key] = new this.Subscription(
118
- options,
119
- dispatch,
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 call after period 1`] = `
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
- "options": [Function],
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
- "options": [Function],
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",
@@ -2,7 +2,7 @@ import { CoolerArticleResource } from '__tests__/new';
2
2
 
3
3
  import { Controller, initialState } from '../..';
4
4
  import { FETCH_TYPE, RESET_TYPE } from '../../actionTypes';
5
- import createReceive from '../../controller/createReceive';
5
+ import createSet from '../../controller/createSet';
6
6
  import LogoutManager from '../LogoutManager.js';
7
7
 
8
8
  function onError(e: any) {
@@ -44,7 +44,7 @@ describe('LogoutManager', () => {
44
44
  },
45
45
  );
46
46
  it('should ignore non-error receive', async () => {
47
- const action = createReceive(CoolerArticleResource.get, {
47
+ const action = createSet(CoolerArticleResource.get, {
48
48
  args: [{ id: 5 }],
49
49
  response: { id: 5, title: 'hi' },
50
50
  });
@@ -55,7 +55,7 @@ describe('LogoutManager', () => {
55
55
  it('should ignore non-401 receive', async () => {
56
56
  const error: any = new Error('network failed');
57
57
  error.status = 404;
58
- const action = createReceive(CoolerArticleResource.get, {
58
+ const action = createSet(CoolerArticleResource.get, {
59
59
  args: [{ id: 5 }],
60
60
  response: error,
61
61
  error: true,
@@ -68,7 +68,7 @@ describe('LogoutManager', () => {
68
68
  jest.setSystemTime(0);
69
69
  const error: any = new Error('network failed');
70
70
  error.status = 401;
71
- const action = createReceive(CoolerArticleResource.get, {
71
+ const action = createSet(CoolerArticleResource.get, {
72
72
  args: [{ id: 5 }],
73
73
  response: error,
74
74
  error: true,
@@ -90,7 +90,7 @@ describe('LogoutManager', () => {
90
90
  jest.setSystemTime(0);
91
91
  const error: any = new Error('network failed');
92
92
  error.status = 403;
93
- const action = createReceive(CoolerArticleResource.get, {
93
+ const action = createSet(CoolerArticleResource.get, {
94
94
  args: [{ id: 5 }],
95
95
  response: error,
96
96
  error: true,