@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.
Files changed (308) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +71 -0
  3. package/dist/index.js +1643 -0
  4. package/dist/index.umd.min.js +1 -0
  5. package/dist/next.js +461 -0
  6. package/dist/package.json +1 -0
  7. package/legacy/actionTypes.js +12 -0
  8. package/legacy/compatibleActions.js +2 -0
  9. package/legacy/controller/BaseController.js +289 -0
  10. package/legacy/controller/Controller.js +20 -0
  11. package/legacy/controller/createFetch.js +42 -0
  12. package/legacy/controller/createInvalidate.js +12 -0
  13. package/legacy/controller/createInvalidateAll.js +8 -0
  14. package/legacy/controller/createOptimistic.js +33 -0
  15. package/legacy/controller/createReceive.js +36 -0
  16. package/legacy/controller/createReset.js +8 -0
  17. package/legacy/controller/createSubscription.js +30 -0
  18. package/legacy/controller/types.js +2 -0
  19. package/legacy/endpoint/index.js +2 -0
  20. package/legacy/endpoint/shapes.js +2 -0
  21. package/legacy/endpoint/types.js +2 -0
  22. package/legacy/fsa.js +2 -0
  23. package/legacy/index.js +22 -0
  24. package/legacy/internal.js +4 -0
  25. package/legacy/legacyActions.js +2 -0
  26. package/legacy/manager/ConnectionListener.js +2 -0
  27. package/legacy/manager/DefaultConnectionListener.js +40 -0
  28. package/legacy/manager/DevtoolsManager.js +73 -0
  29. package/legacy/manager/LogoutManager.js +34 -0
  30. package/legacy/manager/NetworkManager.js +291 -0
  31. package/legacy/manager/PollingSubscription.js +159 -0
  32. package/legacy/manager/SubscriptionManager.js +117 -0
  33. package/legacy/manager/applyManager.js +23 -0
  34. package/legacy/manager/devtoolsTypes.js +2 -0
  35. package/legacy/manager/index.js +6 -0
  36. package/legacy/middlewareTypes.js +2 -0
  37. package/legacy/newActions.js +2 -0
  38. package/legacy/next/Controller.js +24 -0
  39. package/legacy/next/index.js +3 -0
  40. package/legacy/previousActions.js +2 -0
  41. package/legacy/state/RIC.js +3 -0
  42. package/legacy/state/applyUpdatersToResults.js +4 -0
  43. package/legacy/state/legacy-actions/createFetch.js +62 -0
  44. package/legacy/state/legacy-actions/createReceive.js +37 -0
  45. package/legacy/state/legacy-actions/createReceiveError.js +28 -0
  46. package/legacy/state/legacy-actions/index.js +4 -0
  47. package/legacy/state/reducer/createReducer.js +54 -0
  48. package/legacy/state/reducer/fetchReducer.js +32 -0
  49. package/legacy/state/reducer/invalidateReducer.js +28 -0
  50. package/legacy/state/reducer/setReducer.js +113 -0
  51. package/legacy/state/reducerInstance.js +9 -0
  52. package/legacy/state/selectMeta.js +4 -0
  53. package/legacy/types.js +8 -0
  54. package/lib/actionTypes.d.ts +11 -0
  55. package/lib/actionTypes.d.ts.map +1 -0
  56. package/lib/actionTypes.js +12 -0
  57. package/lib/compatibleActions.d.ts +47 -0
  58. package/lib/compatibleActions.d.ts.map +1 -0
  59. package/lib/compatibleActions.js +2 -0
  60. package/lib/controller/BaseController.d.ts +128 -0
  61. package/lib/controller/BaseController.d.ts.map +1 -0
  62. package/lib/controller/BaseController.js +289 -0
  63. package/lib/controller/Controller.d.ts +14 -0
  64. package/lib/controller/Controller.d.ts.map +1 -0
  65. package/lib/controller/Controller.js +20 -0
  66. package/lib/controller/createFetch.d.ts +12 -0
  67. package/lib/controller/createFetch.d.ts.map +1 -0
  68. package/lib/controller/createFetch.js +42 -0
  69. package/lib/controller/createInvalidate.d.ts +6 -0
  70. package/lib/controller/createInvalidate.d.ts.map +1 -0
  71. package/lib/controller/createInvalidate.js +12 -0
  72. package/lib/controller/createInvalidateAll.d.ts +3 -0
  73. package/lib/controller/createInvalidateAll.d.ts.map +1 -0
  74. package/lib/controller/createInvalidateAll.js +8 -0
  75. package/lib/controller/createOptimistic.d.ts +10 -0
  76. package/lib/controller/createOptimistic.d.ts.map +1 -0
  77. package/lib/controller/createOptimistic.js +33 -0
  78. package/lib/controller/createReceive.d.ts +20 -0
  79. package/lib/controller/createReceive.d.ts.map +1 -0
  80. package/lib/controller/createReceive.js +36 -0
  81. package/lib/controller/createReset.d.ts +3 -0
  82. package/lib/controller/createReset.d.ts.map +1 -0
  83. package/lib/controller/createReset.js +8 -0
  84. package/lib/controller/createSubscription.d.ts +9 -0
  85. package/lib/controller/createSubscription.d.ts.map +1 -0
  86. package/lib/controller/createSubscription.js +30 -0
  87. package/lib/controller/types.d.ts +6 -0
  88. package/lib/controller/types.d.ts.map +1 -0
  89. package/lib/controller/types.js +2 -0
  90. package/lib/endpoint/index.d.ts +3 -0
  91. package/lib/endpoint/index.d.ts.map +1 -0
  92. package/lib/endpoint/index.js +2 -0
  93. package/lib/endpoint/shapes.d.ts +25 -0
  94. package/lib/endpoint/shapes.d.ts.map +1 -0
  95. package/lib/endpoint/shapes.js +2 -0
  96. package/lib/endpoint/types.d.ts +45 -0
  97. package/lib/endpoint/types.d.ts.map +1 -0
  98. package/lib/endpoint/types.js +2 -0
  99. package/lib/fsa.d.ts +41 -0
  100. package/lib/fsa.d.ts.map +1 -0
  101. package/lib/fsa.js +2 -0
  102. package/lib/index.d.ts +19 -0
  103. package/lib/index.d.ts.map +1 -0
  104. package/lib/index.js +22 -0
  105. package/lib/internal.d.ts +4 -0
  106. package/lib/internal.d.ts.map +1 -0
  107. package/lib/internal.js +4 -0
  108. package/lib/legacyActions.d.ts +92 -0
  109. package/lib/legacyActions.d.ts.map +1 -0
  110. package/lib/legacyActions.js +2 -0
  111. package/lib/manager/ConnectionListener.d.ts +8 -0
  112. package/lib/manager/ConnectionListener.d.ts.map +1 -0
  113. package/lib/manager/ConnectionListener.js +2 -0
  114. package/lib/manager/DefaultConnectionListener.d.ts +20 -0
  115. package/lib/manager/DefaultConnectionListener.d.ts.map +1 -0
  116. package/lib/manager/DefaultConnectionListener.js +40 -0
  117. package/lib/manager/DevtoolsManager.d.ts +24 -0
  118. package/lib/manager/DevtoolsManager.d.ts.map +1 -0
  119. package/lib/manager/DevtoolsManager.js +74 -0
  120. package/lib/manager/LogoutManager.d.ts +25 -0
  121. package/lib/manager/LogoutManager.d.ts.map +1 -0
  122. package/lib/manager/LogoutManager.js +34 -0
  123. package/lib/manager/NetworkManager.d.ts +82 -0
  124. package/lib/manager/NetworkManager.d.ts.map +1 -0
  125. package/lib/manager/NetworkManager.js +295 -0
  126. package/lib/manager/PollingSubscription.d.ts +45 -0
  127. package/lib/manager/PollingSubscription.d.ts.map +1 -0
  128. package/lib/manager/PollingSubscription.js +159 -0
  129. package/lib/manager/SubscriptionManager.d.ts +55 -0
  130. package/lib/manager/SubscriptionManager.d.ts.map +1 -0
  131. package/lib/manager/SubscriptionManager.js +117 -0
  132. package/lib/manager/applyManager.d.ts +10 -0
  133. package/lib/manager/applyManager.d.ts.map +1 -0
  134. package/lib/manager/applyManager.js +23 -0
  135. package/lib/manager/devtoolsTypes.d.ts +205 -0
  136. package/lib/manager/devtoolsTypes.d.ts.map +1 -0
  137. package/lib/manager/devtoolsTypes.js +2 -0
  138. package/lib/manager/index.d.ts +8 -0
  139. package/lib/manager/index.d.ts.map +1 -0
  140. package/lib/manager/index.js +6 -0
  141. package/lib/middlewareTypes.d.ts +18 -0
  142. package/lib/middlewareTypes.d.ts.map +1 -0
  143. package/lib/middlewareTypes.js +2 -0
  144. package/lib/newActions.d.ts +85 -0
  145. package/lib/newActions.d.ts.map +1 -0
  146. package/lib/newActions.js +2 -0
  147. package/lib/next/Controller.d.ts +14 -0
  148. package/lib/next/Controller.d.ts.map +1 -0
  149. package/lib/next/Controller.js +24 -0
  150. package/lib/next/index.d.ts +3 -0
  151. package/lib/next/index.d.ts.map +1 -0
  152. package/lib/next/index.js +3 -0
  153. package/lib/previousActions.d.ts +91 -0
  154. package/lib/previousActions.d.ts.map +1 -0
  155. package/lib/previousActions.js +2 -0
  156. package/lib/state/RIC.d.ts +2 -0
  157. package/lib/state/RIC.js +3 -0
  158. package/lib/state/applyUpdatersToResults.d.ts +13 -0
  159. package/lib/state/applyUpdatersToResults.d.ts.map +1 -0
  160. package/lib/state/applyUpdatersToResults.js +7 -0
  161. package/lib/state/legacy-actions/createFetch.d.ts +19 -0
  162. package/lib/state/legacy-actions/createFetch.d.ts.map +1 -0
  163. package/lib/state/legacy-actions/createFetch.js +62 -0
  164. package/lib/state/legacy-actions/createReceive.d.ts +14 -0
  165. package/lib/state/legacy-actions/createReceive.d.ts.map +1 -0
  166. package/lib/state/legacy-actions/createReceive.js +37 -0
  167. package/lib/state/legacy-actions/createReceiveError.d.ts +9 -0
  168. package/lib/state/legacy-actions/createReceiveError.d.ts.map +1 -0
  169. package/lib/state/legacy-actions/createReceiveError.js +28 -0
  170. package/lib/state/legacy-actions/index.d.ts +4 -0
  171. package/lib/state/legacy-actions/index.d.ts.map +1 -0
  172. package/lib/state/legacy-actions/index.js +4 -0
  173. package/lib/state/reducer/createReducer.d.ts +7 -0
  174. package/lib/state/reducer/createReducer.d.ts.map +1 -0
  175. package/lib/state/reducer/createReducer.js +55 -0
  176. package/lib/state/reducer/fetchReducer.d.ts +4 -0
  177. package/lib/state/reducer/fetchReducer.d.ts.map +1 -0
  178. package/lib/state/reducer/fetchReducer.js +34 -0
  179. package/lib/state/reducer/invalidateReducer.d.ts +37 -0
  180. package/lib/state/reducer/invalidateReducer.d.ts.map +1 -0
  181. package/lib/state/reducer/invalidateReducer.js +34 -0
  182. package/lib/state/reducer/setReducer.d.ts +40 -0
  183. package/lib/state/reducer/setReducer.d.ts.map +1 -0
  184. package/lib/state/reducer/setReducer.js +119 -0
  185. package/lib/state/reducerInstance.d.ts +7 -0
  186. package/lib/state/reducerInstance.d.ts.map +1 -0
  187. package/lib/state/reducerInstance.js +9 -0
  188. package/lib/state/selectMeta.d.ts +3 -0
  189. package/lib/state/selectMeta.d.ts.map +1 -0
  190. package/lib/state/selectMeta.js +4 -0
  191. package/lib/types.d.ts +71 -0
  192. package/lib/types.d.ts.map +1 -0
  193. package/lib/types.js +8 -0
  194. package/node.mjs +1 -0
  195. package/package.json +127 -0
  196. package/src/actionTypes.ts +11 -0
  197. package/src/compatibleActions.ts +96 -0
  198. package/src/controller/BaseController.ts +508 -0
  199. package/src/controller/Controller.ts +32 -0
  200. package/src/controller/__tests__/Controller.ts +29 -0
  201. package/src/controller/__tests__/__snapshots__/getResponse.ts.snap +35 -0
  202. package/src/controller/__tests__/getResponse.ts +182 -0
  203. package/src/controller/createFetch.ts +54 -0
  204. package/src/controller/createInvalidate.ts +16 -0
  205. package/src/controller/createInvalidateAll.ts +11 -0
  206. package/src/controller/createOptimistic.ts +47 -0
  207. package/src/controller/createReceive.ts +85 -0
  208. package/src/controller/createReset.ts +9 -0
  209. package/src/controller/createSubscription.ts +39 -0
  210. package/src/controller/types.ts +22 -0
  211. package/src/endpoint/index.ts +14 -0
  212. package/src/endpoint/shapes.ts +53 -0
  213. package/src/endpoint/types.ts +72 -0
  214. package/src/fsa.ts +99 -0
  215. package/src/index.ts +61 -0
  216. package/src/internal.ts +3 -0
  217. package/src/legacyActions.ts +163 -0
  218. package/src/manager/ConnectionListener.ts +7 -0
  219. package/src/manager/DefaultConnectionListener.ts +54 -0
  220. package/src/manager/DevtoolsManager.ts +99 -0
  221. package/src/manager/LogoutManager.ts +57 -0
  222. package/src/manager/NetworkManager.ts +346 -0
  223. package/src/manager/PollingSubscription.ts +190 -0
  224. package/src/manager/SubscriptionManager.ts +156 -0
  225. package/src/manager/__tests__/__snapshots__/pollingSubscription-endpoint.ts.snap +49 -0
  226. package/src/manager/__tests__/__snapshots__/pollingSubscription.ts.snap +43 -0
  227. package/src/manager/__tests__/logoutManager.ts +112 -0
  228. package/src/manager/__tests__/manager.ts +44 -0
  229. package/src/manager/__tests__/networkManager-legacy.ts +394 -0
  230. package/src/manager/__tests__/networkManager.ts +426 -0
  231. package/src/manager/__tests__/pollingSubscription-endpoint.ts +423 -0
  232. package/src/manager/__tests__/pollingSubscription.ts +313 -0
  233. package/src/manager/__tests__/subscriptionManager.ts +208 -0
  234. package/src/manager/applyManager.ts +33 -0
  235. package/src/manager/devtoolsTypes.ts +210 -0
  236. package/src/manager/index.ts +7 -0
  237. package/src/middlewareTypes.ts +49 -0
  238. package/src/newActions.ts +140 -0
  239. package/src/next/Controller.ts +39 -0
  240. package/src/next/index.ts +2 -0
  241. package/src/package.json +1 -0
  242. package/src/previousActions.ts +159 -0
  243. package/src/state/RIC.d.ts +2 -0
  244. package/src/state/RIC.js +5 -0
  245. package/src/state/__tests__/RIC.web.ts +16 -0
  246. package/src/state/__tests__/__snapshots__/reducer.ts.snap +56 -0
  247. package/src/state/__tests__/applyUpdatersToResults.ts +40 -0
  248. package/src/state/__tests__/reducer.ts +868 -0
  249. package/src/state/applyUpdatersToResults.ts +29 -0
  250. package/src/state/legacy-actions/createFetch.ts +95 -0
  251. package/src/state/legacy-actions/createReceive.ts +68 -0
  252. package/src/state/legacy-actions/createReceiveError.ts +43 -0
  253. package/src/state/legacy-actions/index.ts +3 -0
  254. package/src/state/reducer/createReducer.ts +80 -0
  255. package/src/state/reducer/fetchReducer.ts +48 -0
  256. package/src/state/reducer/invalidateReducer.ts +39 -0
  257. package/src/state/reducer/setReducer.ts +157 -0
  258. package/src/state/reducerInstance.ts +14 -0
  259. package/src/state/selectMeta.ts +8 -0
  260. package/src/types.ts +125 -0
  261. package/ts3.4/actionTypes.d.ts +11 -0
  262. package/ts3.4/compatibleActions.d.ts +47 -0
  263. package/ts3.4/controller/BaseController.d.ts +170 -0
  264. package/ts3.4/controller/Controller.d.ts +14 -0
  265. package/ts3.4/controller/createFetch.d.ts +14 -0
  266. package/ts3.4/controller/createInvalidate.d.ts +8 -0
  267. package/ts3.4/controller/createInvalidateAll.d.ts +3 -0
  268. package/ts3.4/controller/createOptimistic.d.ts +12 -0
  269. package/ts3.4/controller/createReceive.d.ts +24 -0
  270. package/ts3.4/controller/createReset.d.ts +3 -0
  271. package/ts3.4/controller/createSubscription.d.ts +13 -0
  272. package/ts3.4/controller/types.d.ts +6 -0
  273. package/ts3.4/endpoint/index.d.ts +3 -0
  274. package/ts3.4/endpoint/shapes.d.ts +25 -0
  275. package/ts3.4/endpoint/types.d.ts +45 -0
  276. package/ts3.4/fsa.d.ts +41 -0
  277. package/ts3.4/index.d.ts +22 -0
  278. package/ts3.4/internal.d.ts +4 -0
  279. package/ts3.4/legacyActions.d.ts +95 -0
  280. package/ts3.4/manager/ConnectionListener.d.ts +8 -0
  281. package/ts3.4/manager/DefaultConnectionListener.d.ts +20 -0
  282. package/ts3.4/manager/DevtoolsManager.d.ts +24 -0
  283. package/ts3.4/manager/LogoutManager.d.ts +25 -0
  284. package/ts3.4/manager/NetworkManager.d.ts +82 -0
  285. package/ts3.4/manager/PollingSubscription.d.ts +45 -0
  286. package/ts3.4/manager/SubscriptionManager.d.ts +55 -0
  287. package/ts3.4/manager/applyManager.d.ts +10 -0
  288. package/ts3.4/manager/devtoolsTypes.d.ts +205 -0
  289. package/ts3.4/manager/index.d.ts +8 -0
  290. package/ts3.4/middlewareTypes.d.ts +18 -0
  291. package/ts3.4/newActions.d.ts +88 -0
  292. package/ts3.4/next/Controller.d.ts +14 -0
  293. package/ts3.4/next/index.d.ts +3 -0
  294. package/ts3.4/previousActions.d.ts +94 -0
  295. package/ts3.4/state/RIC.d.ts +2 -0
  296. package/ts3.4/state/applyUpdatersToResults.d.ts +13 -0
  297. package/ts3.4/state/legacy-actions/createFetch.d.ts +19 -0
  298. package/ts3.4/state/legacy-actions/createReceive.d.ts +14 -0
  299. package/ts3.4/state/legacy-actions/createReceiveError.d.ts +9 -0
  300. package/ts3.4/state/legacy-actions/index.d.ts +4 -0
  301. package/ts3.4/state/reducer/createReducer.d.ts +7 -0
  302. package/ts3.4/state/reducer/fetchReducer.d.ts +4 -0
  303. package/ts3.4/state/reducer/invalidateReducer.d.ts +37 -0
  304. package/ts3.4/state/reducer/setReducer.d.ts +40 -0
  305. package/ts3.4/state/reducerInstance.d.ts +7 -0
  306. package/ts3.4/state/selectMeta.d.ts +3 -0
  307. package/ts3.4/types.d.ts +73 -0
  308. package/typescript.svg +8 -0
package/dist/index.js ADDED
@@ -0,0 +1,1643 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var normalizr = require('@data-client/normalizr');
6
+
7
+ const RIC = typeof requestIdleCallback === 'function' ? requestIdleCallback : cb => setTimeout(cb, 0);
8
+ var RIC$1 = RIC;
9
+
10
+ const FETCH_TYPE = 'rest-hooks/fetch';
11
+ // TODO(breaking): deprecate this
12
+ const RECEIVE_TYPE = 'rest-hooks/receive';
13
+ const SET_TYPE = RECEIVE_TYPE;
14
+ const OPTIMISTIC_TYPE = 'rest-hooks/optimistic';
15
+ const RESET_TYPE = 'rest-hooks/reset';
16
+ const SUBSCRIBE_TYPE = 'rest-hooks/subscribe';
17
+ const UNSUBSCRIBE_TYPE = 'rest-hook/unsubscribe';
18
+ const INVALIDATE_TYPE = 'rest-hooks/invalidate';
19
+ const INVALIDATEALL_TYPE = 'rest-hooks/invalidateall';
20
+ const GC_TYPE = 'rest-hooks/gc';
21
+
22
+ var actionTypes = /*#__PURE__*/Object.freeze({
23
+ __proto__: null,
24
+ FETCH_TYPE: FETCH_TYPE,
25
+ RECEIVE_TYPE: RECEIVE_TYPE,
26
+ SET_TYPE: SET_TYPE,
27
+ OPTIMISTIC_TYPE: OPTIMISTIC_TYPE,
28
+ RESET_TYPE: RESET_TYPE,
29
+ SUBSCRIBE_TYPE: SUBSCRIBE_TYPE,
30
+ UNSUBSCRIBE_TYPE: UNSUBSCRIBE_TYPE,
31
+ INVALIDATE_TYPE: INVALIDATE_TYPE,
32
+ INVALIDATEALL_TYPE: INVALIDATEALL_TYPE,
33
+ GC_TYPE: GC_TYPE
34
+ });
35
+
36
+ function createOptimistic(endpoint, {
37
+ args,
38
+ fetchedAt
39
+ }) {
40
+ var _endpoint$dataExpiryL;
41
+ const expiryLength = (_endpoint$dataExpiryL = endpoint.dataExpiryLength) != null ? _endpoint$dataExpiryL : 60000;
42
+ /* istanbul ignore next */
43
+ if (process.env.NODE_ENV === 'development' && expiryLength < 0) {
44
+ throw new Error('Negative expiry length are not allowed.');
45
+ }
46
+ const now = Date.now();
47
+ // TODO: Use correct type once we no longer need backcompat
48
+ const meta = {
49
+ args,
50
+ fetchedAt,
51
+ date: now,
52
+ expiresAt: now + expiryLength,
53
+ // For legacy support; TODO: remove
54
+ schema: endpoint.schema,
55
+ key: endpoint.key(...args)
56
+ };
57
+ // For legacy support; TODO: remove
58
+ if (endpoint.update) meta.update = endpoint.update;
59
+ if (endpoint.errorPolicy) meta.errorPolicy = endpoint.errorPolicy;
60
+ const action = {
61
+ type: OPTIMISTIC_TYPE,
62
+ endpoint,
63
+ meta
64
+ };
65
+ return action;
66
+ }
67
+
68
+ // TODO(breaking): remove file - not used
69
+ /** Requesting a fetch to begin
70
+ *
71
+ * @param fetchShape
72
+ * @param param1 { params, body, throttle, updateParams }
73
+ */
74
+ function createFetch$1(fetchShape, {
75
+ params,
76
+ body,
77
+ throttle,
78
+ updateParams
79
+ }) {
80
+ const {
81
+ schema,
82
+ type,
83
+ getFetchKey,
84
+ options
85
+ } = fetchShape;
86
+ const key = getFetchKey(params);
87
+ let resolve = 0;
88
+ let reject = 0;
89
+ const promise = new Promise((a, b) => {
90
+ [resolve, reject] = [a, b];
91
+ });
92
+ const meta = {
93
+ schema,
94
+ type,
95
+ args: [params, body],
96
+ key,
97
+ throttle,
98
+ options,
99
+ resolve,
100
+ reject,
101
+ promise,
102
+ createdAt: Date.now()
103
+ };
104
+ if (fetchShape.update) {
105
+ meta.update = fetchShape.update;
106
+ }
107
+
108
+ // for simplicity we simply override if updateParams are defined - usage together is silly to support as we are migrating
109
+ if (updateParams) {
110
+ meta.update = newresult => {
111
+ const updateMap = {};
112
+ updateParams.forEach(([toShape, toParams, updateFn]) => {
113
+ updateMap[toShape.getFetchKey(toParams)] = existing => updateFn(newresult, existing);
114
+ });
115
+ return updateMap;
116
+ };
117
+ }
118
+ if (options != null && options.optimisticUpdate) {
119
+ meta.optimisticResponse = options.optimisticUpdate(params, body);
120
+ }
121
+ return {
122
+ type: FETCH_TYPE,
123
+ payload: () => fetchShape.fetch(params, body),
124
+ meta
125
+ };
126
+ }
127
+
128
+ /** Update state with data
129
+ *
130
+ * @param data
131
+ * @param param1 { schema, key, type, updaters, dataExpiryLength }
132
+ */
133
+ function createReceive$1(data, {
134
+ schema,
135
+ key,
136
+ args,
137
+ updaters,
138
+ fetchedAt = 0,
139
+ update,
140
+ dataExpiryLength
141
+ }) {
142
+ /* istanbul ignore next */
143
+ if (process.env.NODE_ENV === 'development' && dataExpiryLength < 0) {
144
+ throw new Error('Negative dataExpiryLength are not allowed.');
145
+ }
146
+ const now = Date.now();
147
+ const meta = {
148
+ schema,
149
+ key,
150
+ args,
151
+ date: now,
152
+ fetchedAt,
153
+ expiresAt: now + dataExpiryLength
154
+ };
155
+ meta.updaters = updaters;
156
+ meta.update = update;
157
+ return {
158
+ type: RECEIVE_TYPE,
159
+ payload: data,
160
+ meta
161
+ };
162
+ }
163
+
164
+ function createReceiveError(error, {
165
+ schema,
166
+ key,
167
+ options,
168
+ errorExpiryLength = 60000,
169
+ fetchedAt = 0
170
+ }) {
171
+ /* istanbul ignore next */
172
+ if (process.env.NODE_ENV === 'development' && errorExpiryLength < 0) {
173
+ throw new Error('Negative errorExpiryLength are not allowed.');
174
+ }
175
+ const now = Date.now();
176
+ return {
177
+ type: RECEIVE_TYPE,
178
+ payload: error,
179
+ meta: {
180
+ schema,
181
+ key,
182
+ date: now,
183
+ fetchedAt,
184
+ expiresAt: now + errorExpiryLength,
185
+ errorPolicy: options == null ? void 0 : options.errorPolicy
186
+ },
187
+ error: true
188
+ };
189
+ }
190
+
191
+ var index = /*#__PURE__*/Object.freeze({
192
+ __proto__: null,
193
+ createFetch: createFetch$1,
194
+ createReceive: createReceive$1,
195
+ createReceiveError: createReceiveError
196
+ });
197
+
198
+ function fetchReducer(state, action) {
199
+ var _action$endpoint;
200
+ const optimisticResponse = action.meta.optimisticResponse;
201
+ const getOptimisticResponse = (_action$endpoint = action.endpoint) == null ? void 0 : _action$endpoint.getOptimisticResponse;
202
+ let receiveAction;
203
+ if (getOptimisticResponse && action.endpoint && action.endpoint.sideEffect) {
204
+ receiveAction = createOptimistic(action.endpoint, {
205
+ args: action.meta.args,
206
+ fetchedAt: typeof action.meta.createdAt !== 'number' ? action.meta.createdAt.getTime() : action.meta.createdAt
207
+ });
208
+ } /* istanbul ignore if */else if (optimisticResponse) {
209
+ // TODO(breaking): this is no longer used, remove this branch
210
+ /* istanbul ignore next */
211
+ receiveAction = createReceive$1(optimisticResponse, {
212
+ ...action.meta,
213
+ dataExpiryLength: Infinity
214
+ });
215
+ } else {
216
+ // If 'fetch' action reaches the reducer there are no middlewares installed to handle it
217
+ /* istanbul ignore next */
218
+ if (process.env.NODE_ENV !== 'production') {
219
+ console.warn('Fetch appears unhandled - you are likely missing the NetworkManager middleware');
220
+ console.warn('See https://resthooks.io/docs/guides/redux#indextsx for hooking up redux');
221
+ }
222
+ return state;
223
+ }
224
+ return {
225
+ ...state,
226
+ optimistic: [...state.optimistic, receiveAction]
227
+ };
228
+ }
229
+
230
+ function invalidateReducer(state, action) {
231
+ const results = {
232
+ ...state.results
233
+ };
234
+ const meta = {
235
+ ...state.meta
236
+ };
237
+ const invalidateKey = key => {
238
+ delete results[key];
239
+ const itemMeta = {
240
+ ...meta[key],
241
+ expiresAt: 0,
242
+ invalidated: true
243
+ };
244
+ delete itemMeta.error;
245
+ meta[key] = itemMeta;
246
+ };
247
+ if (action.type === INVALIDATE_TYPE) {
248
+ invalidateKey(action.meta.key);
249
+ } else {
250
+ Object.keys(results).forEach(key => {
251
+ if (action.testKey(key)) {
252
+ invalidateKey(key);
253
+ }
254
+ });
255
+ }
256
+ return {
257
+ ...state,
258
+ results,
259
+ meta
260
+ };
261
+ }
262
+
263
+ function applyUpdatersToResults(results, result, updaters) {
264
+ return {
265
+ ...results,
266
+ ...Object.fromEntries(Object.entries(updaters).map(([fetchKey, updater]) => [fetchKey, updater(result, results[fetchKey])]))
267
+ };
268
+ }
269
+
270
+ function setReducer(state, action, controller) {
271
+ if (action.error) {
272
+ return reduceError(state, action, action.payload);
273
+ }
274
+ try {
275
+ var _state$meta$action$me;
276
+ let payload;
277
+ // for true receives payload is contained in action
278
+ if (action.type === OPTIMISTIC_TYPE) {
279
+ if (!action.endpoint.getOptimisticResponse) return state;
280
+ try {
281
+ // compute optimistic response based on current state
282
+ payload = action.endpoint.getOptimisticResponse.call(action.endpoint, controller.snapshot(state, action.meta.fetchedAt),
283
+ // if endpoint exists, so must args; TODO: fix typing
284
+ ...action.meta.args);
285
+ } catch (e) {
286
+ var _e$constructor;
287
+ // AbortOptimistic means 'do nothing', otherwise we count the exception as endpoint failure
288
+ if (((_e$constructor = e.constructor) == null ? void 0 : _e$constructor.name) === 'AbortOptimistic') {
289
+ return state;
290
+ }
291
+ throw e;
292
+ }
293
+ } else {
294
+ payload = action.payload;
295
+ }
296
+ const {
297
+ result,
298
+ entities,
299
+ indexes,
300
+ entityMeta
301
+ } = normalizr.normalize(payload, action.meta.schema, action.meta.args, state.entities, state.indexes, state.entityMeta, {
302
+ fetchedAt: action.meta.date,
303
+ ...action.meta
304
+ });
305
+ let results = {
306
+ ...state.results,
307
+ [action.meta.key]: result
308
+ };
309
+ try {
310
+ if ('updaters' in action.meta && action.meta.updaters) {
311
+ results = applyUpdatersToResults(results, result, action.meta.updaters);
312
+ }
313
+ if (action.meta.update) {
314
+ const updaters = action.meta.update(result, ...(action.meta.args || []));
315
+ Object.keys(updaters).forEach(key => {
316
+ results[key] = updaters[key](results[key]);
317
+ });
318
+ }
319
+ // no reason to completely fail because of user-code error
320
+ // integrity of this state update is still guaranteed
321
+ } catch (error) {
322
+ console.error(`The following error occured during Endpoint.update() for ${action.meta.key}`);
323
+ console.error(error);
324
+ }
325
+ return {
326
+ entities,
327
+ indexes,
328
+ results,
329
+ entityMeta,
330
+ meta: {
331
+ ...state.meta,
332
+ [action.meta.key]: {
333
+ date: action.meta.date,
334
+ expiresAt: action.meta.expiresAt,
335
+ prevExpiresAt: (_state$meta$action$me = state.meta[action.meta.key]) == null ? void 0 : _state$meta$action$me.expiresAt
336
+ }
337
+ },
338
+ optimistic: filterOptimistic(state, action),
339
+ lastReset: state.lastReset
340
+ };
341
+ // reducer must update the state, so in case of processing errors we simply compute the results inline
342
+ } catch (error) {
343
+ if (typeof error === 'object') {
344
+ error.message = `Error processing ${action.meta.key}\n\nFull Schema: ${JSON.stringify(action.meta.schema, undefined, 2)}\n\nError:\n${error.message}`;
345
+ if ('payload' in action) error.payload = action.payload;
346
+ error.status = 400;
347
+ }
348
+
349
+ // this is not always bubbled up, so let's double sure this doesn't fail silently
350
+ /* istanbul ignore else */
351
+ if (process.env.NODE_ENV !== 'production') {
352
+ console.error(error);
353
+ }
354
+ return reduceError(state, action, error);
355
+ }
356
+ }
357
+ function reduceError(state, action, error) {
358
+ if (error.name === 'AbortError') {
359
+ // In case we abort simply undo the optimistic update and act like no fetch even occured
360
+ // We still want those watching promises from fetch directly to observed the abort, but we don't want to
361
+ // Trigger errors in this case. This means theoretically improperly built abortes useResource() could suspend forever.
362
+ return {
363
+ ...state,
364
+ optimistic: filterOptimistic(state, action)
365
+ };
366
+ }
367
+ return {
368
+ ...state,
369
+ meta: {
370
+ ...state.meta,
371
+ [action.meta.key]: {
372
+ date: action.meta.date,
373
+ error,
374
+ expiresAt: action.meta.expiresAt,
375
+ errorPolicy: action.meta.errorPolicy == null ? void 0 : action.meta.errorPolicy(error)
376
+ }
377
+ },
378
+ optimistic: filterOptimistic(state, action)
379
+ };
380
+ }
381
+ /** Filter all requests with same serialization that did not start after the resolving request */
382
+ function filterOptimistic(state, resolvingAction) {
383
+ return state.optimistic.filter(optimisticAction => optimisticAction.meta.key !== resolvingAction.meta.key || (optimisticAction.type === OPTIMISTIC_TYPE ? optimisticAction.meta.fetchedAt !== resolvingAction.meta.fetchedAt : optimisticAction.meta.date > resolvingAction.meta.date));
384
+ }
385
+
386
+ function createReducer(controller) {
387
+ return function reducer(state, action) {
388
+ var _action$date;
389
+ if (!state) state = initialState;
390
+ switch (action.type) {
391
+ case GC_TYPE:
392
+ // inline deletes are fine as these should have 0 refcounts
393
+ action.entities.forEach(([key, pk]) => {
394
+ var _entities$key, _entityMeta$key;
395
+ (_entities$key = state.entities[key]) == null ? true : delete _entities$key[pk];
396
+ (_entityMeta$key = state.entityMeta[key]) == null ? true : delete _entityMeta$key[pk];
397
+ });
398
+ action.results.forEach(fetchKey => {
399
+ delete state.results[fetchKey];
400
+ delete state.meta[fetchKey];
401
+ });
402
+ return state;
403
+ case FETCH_TYPE:
404
+ return fetchReducer(state, action);
405
+ case OPTIMISTIC_TYPE:
406
+ // eslint-disable-next-line no-fallthrough
407
+ case SET_TYPE:
408
+ return setReducer(state, action, controller);
409
+ case INVALIDATEALL_TYPE:
410
+ case INVALIDATE_TYPE:
411
+ return invalidateReducer(state, action);
412
+ case RESET_TYPE:
413
+ if (process.env.NODE_ENV !== 'production' && action.date === undefined) {
414
+ console.warn(`${RESET_TYPE} sent without 'date' member. This is deprecated. Please use createReset() action creator to ensure correct action shape.`);
415
+ }
416
+ return {
417
+ ...initialState,
418
+ lastReset: (_action$date = action.date) != null ? _action$date : Date.now()
419
+ };
420
+ default:
421
+ // A reducer must always return a valid state.
422
+ // Alternatively you can throw an error if an invalid action is dispatched.
423
+ return state;
424
+ }
425
+ };
426
+ }
427
+ const initialState = {
428
+ entities: {},
429
+ indexes: {},
430
+ results: {},
431
+ meta: {},
432
+ entityMeta: {},
433
+ optimistic: [],
434
+ lastReset: 0
435
+ };
436
+
437
+ var internal = /*#__PURE__*/Object.freeze({
438
+ __proto__: null,
439
+ inferResults: normalizr.inferResults,
440
+ DELETED: normalizr.DELETED,
441
+ RIC: RIC$1,
442
+ initialState: initialState
443
+ });
444
+
445
+ function createInvalidate(endpoint, {
446
+ args
447
+ }) {
448
+ return {
449
+ type: INVALIDATE_TYPE,
450
+ meta: {
451
+ key: endpoint.key(...args)
452
+ }
453
+ };
454
+ }
455
+
456
+ function createInvalidateAll(testKey) {
457
+ return {
458
+ type: INVALIDATEALL_TYPE,
459
+ testKey
460
+ };
461
+ }
462
+
463
+ function createReceive(endpoint, {
464
+ args,
465
+ fetchedAt,
466
+ response,
467
+ error = false
468
+ }) {
469
+ var _endpoint$errorExpiry, _endpoint$dataExpiryL;
470
+ const expiryLength = error ? (_endpoint$errorExpiry = endpoint.errorExpiryLength) != null ? _endpoint$errorExpiry : 1000 : (_endpoint$dataExpiryL = endpoint.dataExpiryLength) != null ? _endpoint$dataExpiryL : 60000;
471
+ /* istanbul ignore next */
472
+ if (process.env.NODE_ENV === 'development' && expiryLength < 0) {
473
+ throw new Error('Negative expiry length are not allowed.');
474
+ }
475
+ const now = Date.now();
476
+ const meta = {
477
+ args,
478
+ fetchedAt: fetchedAt != null ? fetchedAt : now,
479
+ date: now,
480
+ expiresAt: now + expiryLength,
481
+ // For legacy support; TODO: remove
482
+ schema: endpoint.schema,
483
+ key: endpoint.key(...args)
484
+ };
485
+ // For legacy support; TODO: remove
486
+ if (endpoint.update) meta.update = endpoint.update;
487
+ if (endpoint.errorPolicy) meta.errorPolicy = endpoint.errorPolicy;
488
+ const action = {
489
+ type: SET_TYPE,
490
+ payload: response,
491
+ endpoint: endpoint,
492
+ meta
493
+ };
494
+ if (error) action.error = true;
495
+ return action;
496
+ }
497
+
498
+ function createReset() {
499
+ return {
500
+ type: RESET_TYPE,
501
+ date: Date.now()
502
+ };
503
+ }
504
+
505
+ function createSubscription(endpoint, {
506
+ args
507
+ }) {
508
+ return {
509
+ type: SUBSCRIBE_TYPE,
510
+ endpoint,
511
+ meta: {
512
+ args,
513
+ key: endpoint.key(...args),
514
+ fetch: () => endpoint(...args),
515
+ schema: endpoint.schema,
516
+ options: endpoint
517
+ }
518
+ };
519
+ }
520
+ function createUnsubscription(endpoint, {
521
+ args
522
+ }) {
523
+ return {
524
+ type: UNSUBSCRIBE_TYPE,
525
+ endpoint,
526
+ meta: {
527
+ args,
528
+ key: endpoint.key(...args),
529
+ options: endpoint
530
+ }
531
+ };
532
+ }
533
+
534
+ function selectMeta(state, fetchKey) {
535
+ return state.meta[fetchKey];
536
+ }
537
+
538
+ const unsetDispatch = action => {
539
+ throw new Error(`Dispatching while constructing your middleware is not allowed. ` + `Other middleware would not be applied to this dispatch.`);
540
+ };
541
+ const unsetState = () => {
542
+ // This is only the value until it is set by the CacheProvider
543
+ /* istanbul ignore next */
544
+ return initialState;
545
+ };
546
+
547
+ /**
548
+ * Imperative control of Rest Hooks store
549
+ * @see https://resthooks.io/docs/api/Controller
550
+ */
551
+ class Controller$1 {
552
+ /**
553
+ * Dispatches an action to Rest Hooks reducer.
554
+ *
555
+ * @see https://resthooks.io/docs/api/Controller#dispatch
556
+ */
557
+
558
+ /**
559
+ * Gets the latest state snapshot that is fully committed.
560
+ *
561
+ * This can be useful for imperative use-cases like event handlers.
562
+ * This should *not* be used to render; instead useSuspense() or useCache()
563
+ * @see https://resthooks.io/docs/api/Controller#getState
564
+ */
565
+
566
+ constructor({
567
+ dispatch = unsetDispatch,
568
+ getState = unsetState,
569
+ globalCache = {
570
+ entities: {},
571
+ results: {}
572
+ }
573
+ } = {}) {
574
+ /*************** Action Dispatchers ***************/
575
+ /**
576
+ * Forces refetching and suspense on useSuspense with the same Endpoint and parameters.
577
+ * @see https://resthooks.io/docs/api/Controller#invalidate
578
+ */
579
+ this.invalidate = (endpoint, ...args) => args[0] !== null ? this.dispatch(createInvalidate(endpoint, {
580
+ args: args
581
+ })) : Promise.resolve();
582
+ /**
583
+ * Forces refetching and suspense on useSuspense on all matching endpoint result keys.
584
+ * @see https://resthooks.io/docs/api/Controller#invalidateAll
585
+ */
586
+ this.invalidateAll = options => this.dispatch(createInvalidateAll(key => options.testKey(key)));
587
+ /**
588
+ * Resets the entire Rest Hooks cache. All inflight requests will not resolve.
589
+ * @see https://resthooks.io/docs/api/Controller#resetEntireStore
590
+ */
591
+ this.resetEntireStore = () => this.dispatch(createReset());
592
+ /**
593
+ * Stores response in cache for given Endpoint and args.
594
+ * @see https://resthooks.io/docs/api/Controller#set
595
+ */
596
+ this.setResponse = (endpoint, ...rest) => {
597
+ const response = rest[rest.length - 1];
598
+ const action = createReceive(endpoint, {
599
+ args: rest.slice(0, rest.length - 1),
600
+ response
601
+ });
602
+ return this.dispatch(action);
603
+ };
604
+ // TODO: deprecate
605
+ /**
606
+ * Another name for setResponse
607
+ * @see https://resthooks.io/docs/api/Controller#setResponse
608
+ */
609
+ /* istanbul ignore next */
610
+ this.receive = (endpoint, ...rest) => {
611
+ /* istanbul ignore next */
612
+ return this.setResponse(endpoint, ...rest);
613
+ };
614
+ /**
615
+ * Stores the result of Endpoint and args as the error provided.
616
+ * @see https://resthooks.io/docs/api/Controller#setError
617
+ */
618
+ this.setError = (endpoint, ...rest) => {
619
+ const response = rest[rest.length - 1];
620
+ const action = createReceive(endpoint, {
621
+ args: rest.slice(0, rest.length - 1),
622
+ response,
623
+ error: true
624
+ });
625
+ return this.dispatch(action);
626
+ };
627
+ // TODO: deprecate
628
+ /**
629
+ * Another name for setError
630
+ * @see https://resthooks.io/docs/api/Controller#setError
631
+ */
632
+ /* istanbul ignore next */
633
+ this.receiveError = (endpoint, ...rest) => {
634
+ /* istanbul ignore next */
635
+ return this.setError(endpoint, ...rest);
636
+ };
637
+ /**
638
+ * Resolves an inflight fetch. `fetchedAt` should `fetch`'s `createdAt`
639
+ * @see https://resthooks.io/docs/api/Controller#resolve
640
+ */
641
+ this.resolve = (endpoint, meta) => {
642
+ return this.dispatch(createReceive(endpoint, meta));
643
+ };
644
+ /**
645
+ * Marks a new subscription to a given Endpoint.
646
+ * @see https://resthooks.io/docs/api/Controller#subscribe
647
+ */
648
+ this.subscribe = (endpoint, ...args) => args[0] !== null ? this.dispatch(createSubscription(endpoint, {
649
+ args: args
650
+ })) : Promise.resolve();
651
+ /**
652
+ * Marks completion of subscription to a given Endpoint.
653
+ * @see https://resthooks.io/docs/api/Controller#unsubscribe
654
+ */
655
+ this.unsubscribe = (endpoint, ...args) => args[0] !== null ? this.dispatch(createUnsubscription(endpoint, {
656
+ args: args
657
+ })) : Promise.resolve();
658
+ /*************** More ***************/
659
+ /* TODO:
660
+ abort = <E extends EndpointInterface>(
661
+ endpoint: E,
662
+ ...args: readonly [...Parameters<E>]
663
+ ): Promise<void>
664
+ */
665
+ /**
666
+ * Gets a snapshot (https://resthooks.io/docs/api/Snapshot)
667
+ * @see https://resthooks.io/docs/api/Controller#snapshot
668
+ */
669
+ this.snapshot = (state, fetchedAt) => {
670
+ return new Snapshot(this, state, fetchedAt);
671
+ };
672
+ /**
673
+ * Gets the error, if any, for a given endpoint. Returns undefined for no errors.
674
+ * @see https://resthooks.io/docs/api/Controller#getError
675
+ */
676
+ this.getError = (endpoint, ...rest) => {
677
+ if (rest[0] === null) return;
678
+ const state = rest[rest.length - 1];
679
+ // this is typescript generics breaking
680
+ const args = rest.slice(0, rest.length - 1);
681
+ const key = endpoint.key(...args);
682
+ const meta = selectMeta(state, key);
683
+ const results = state.results[key];
684
+ if (results !== undefined && (meta == null ? void 0 : meta.errorPolicy) === 'soft') return;
685
+ return meta == null ? void 0 : meta.error;
686
+ };
687
+ /**
688
+ * Gets the (globally referentially stable) response for a given endpoint/args pair from state given.
689
+ * @see https://resthooks.io/docs/api/Controller#getResponse
690
+ */
691
+ this.getResponse = (endpoint, ...rest) => {
692
+ const state = rest[rest.length - 1];
693
+ // this is typescript generics breaking
694
+ const args = rest.slice(0, rest.length - 1);
695
+ const isActive = args.length !== 1 || args[0] !== null;
696
+ const key = isActive ? endpoint.key(...args) : '';
697
+ const cacheResults = isActive ? state.results[key] : undefined;
698
+ const schema = endpoint.schema;
699
+ const meta = selectMeta(state, key);
700
+ let expiresAt = meta == null ? void 0 : meta.expiresAt;
701
+ let invalidResults = false;
702
+ let results;
703
+ if (cacheResults === undefined && endpoint.schema !== undefined) {
704
+ results = normalizr.inferResults(endpoint.schema, args, state.indexes, state.entities);
705
+ invalidResults = !normalizr.validateInference(results);
706
+ if (!expiresAt && invalidResults) expiresAt = 1;
707
+ } else {
708
+ results = cacheResults;
709
+ }
710
+ if (!isActive) {
711
+ return {
712
+ data: results,
713
+ expiryStatus: normalizr.ExpiryStatus.Valid,
714
+ expiresAt: Infinity
715
+ };
716
+ }
717
+ if (!endpoint.schema || !schemaHasEntity(endpoint.schema)) {
718
+ return {
719
+ data: results,
720
+ expiryStatus: meta != null && meta.invalidated ? normalizr.ExpiryStatus.Invalid : cacheResults && !endpoint.invalidIfStale ? normalizr.ExpiryStatus.Valid : normalizr.ExpiryStatus.InvalidIfStale,
721
+ expiresAt: expiresAt || 0
722
+ };
723
+ }
724
+
725
+ // Warn users with bad configurations
726
+ /* istanbul ignore next */
727
+ if (process.env.NODE_ENV !== 'production' && schema && normalizr.isEntity(schema)) {
728
+ if (Array.isArray(results)) {
729
+ throw new Error(`fetch key ${key} has list results when single result is expected`);
730
+ }
731
+ if (typeof results === 'object') {
732
+ throw new Error(`fetch key ${key} has object results when entity's primary key (string) result is expected`);
733
+ }
734
+ }
735
+ if (!this.globalCache.results[key]) this.globalCache.results[key] = new normalizr.WeakEntityMap();
736
+
737
+ // second argument is false if any entities are missing
738
+ // eslint-disable-next-line prefer-const
739
+ const {
740
+ data,
741
+ paths
742
+ } = normalizr.denormalizeCached(results, schema, state.entities, this.globalCache.entities, this.globalCache.results[key], args);
743
+ const invalidDenormalize = typeof data === 'symbol';
744
+
745
+ // fallback to entity expiry time
746
+ if (!expiresAt) {
747
+ expiresAt = entityExpiresAt(paths, state.entityMeta);
748
+ }
749
+
750
+ // https://resthooks.io/docs/concepts/expiry-policy#expiry-status
751
+ // we don't track the difference between stale or fresh because that is tied to triggering
752
+ // conditions
753
+ const expiryStatus = meta != null && meta.invalidated || invalidDenormalize && !(meta != null && meta.error) ? normalizr.ExpiryStatus.Invalid : invalidDenormalize || endpoint.invalidIfStale || invalidResults ? normalizr.ExpiryStatus.InvalidIfStale : normalizr.ExpiryStatus.Valid;
754
+ return {
755
+ data,
756
+ expiryStatus,
757
+ expiresAt
758
+ };
759
+ };
760
+ this.dispatch = dispatch;
761
+ this.getState = getState;
762
+ this.globalCache = globalCache;
763
+ }
764
+ }
765
+
766
+ // benchmark: https://www.measurethat.net/Benchmarks/Show/24691/0/min-reducer-vs-imperative-with-paths
767
+ // earliest expiry dictates age
768
+ function entityExpiresAt(paths, entityMeta) {
769
+ let expiresAt = Infinity;
770
+ for (const {
771
+ pk,
772
+ key
773
+ } of paths) {
774
+ var _entityMeta$key, _entityMeta$key$pk;
775
+ const entityExpiry = (_entityMeta$key = entityMeta[key]) == null ? void 0 : (_entityMeta$key$pk = _entityMeta$key[pk]) == null ? void 0 : _entityMeta$key$pk.expiresAt;
776
+ // expiresAt will always resolve to false with any comparison
777
+ if (entityExpiry < expiresAt) expiresAt = entityExpiry;
778
+ }
779
+ return expiresAt;
780
+ }
781
+
782
+ /** Determine whether the schema has any entities.
783
+ *
784
+ * Without entities, denormalization is not needed, and results should not be inferred.
785
+ */
786
+ function schemaHasEntity(schema) {
787
+ if (normalizr.isEntity(schema)) return true;
788
+ if (Array.isArray(schema)) return schema.length !== 0 && schemaHasEntity(schema[0]);
789
+ if (schema && (typeof schema === 'object' || typeof schema === 'function')) {
790
+ const nestedSchema = 'schema' in schema ? schema.schema : schema;
791
+ if (typeof nestedSchema === 'function') {
792
+ return schemaHasEntity(nestedSchema);
793
+ }
794
+ return Object.values(nestedSchema).some(x => schemaHasEntity(x));
795
+ }
796
+ return false;
797
+ }
798
+ class Snapshot {
799
+ constructor(controller, state, fetchedAt = 0) {
800
+ this.state = void 0;
801
+ this.controller = void 0;
802
+ this.fetchedAt = void 0;
803
+ /*************** Data Access ***************/
804
+ /** @see https://resthooks.io/docs/api/Snapshot#getResponse */
805
+ this.getResponse = (endpoint, ...args) => {
806
+ return this.controller.getResponse(endpoint, ...args, this.state);
807
+ };
808
+ /** @see https://resthooks.io/docs/api/Snapshot#getError */
809
+ this.getError = (endpoint, ...args) => {
810
+ return this.controller.getError(endpoint, ...args, this.state);
811
+ };
812
+ this.state = state;
813
+ this.controller = controller;
814
+ this.fetchedAt = fetchedAt;
815
+ }
816
+ }
817
+
818
+ /**
819
+ * Requesting a fetch to begin
820
+ */
821
+ function createFetch(endpoint, {
822
+ args
823
+ }) {
824
+ const key = endpoint.key(...args);
825
+ let resolve = 0;
826
+ let reject = 0;
827
+ const promise = new Promise((a, b) => {
828
+ [resolve, reject] = [a, b];
829
+ });
830
+ const meta = {
831
+ schema: endpoint.schema,
832
+ type: endpoint.sideEffect ? 'mutate' : 'read',
833
+ args,
834
+ key,
835
+ throttle: !endpoint.sideEffect,
836
+ options: endpoint,
837
+ resolve,
838
+ reject,
839
+ promise,
840
+ createdAt: Date.now()
841
+ };
842
+ if (endpoint.update) {
843
+ meta.update = endpoint.update;
844
+ }
845
+
846
+ // TODO: Remove once EOL on this deprecated piece
847
+ /* istanbul ignore if */
848
+ if (endpoint.optimisticUpdate) {
849
+ meta.optimisticResponse = endpoint.optimisticUpdate(...args);
850
+ }
851
+ return {
852
+ type: FETCH_TYPE,
853
+ payload: () => endpoint(...args),
854
+ meta,
855
+ endpoint
856
+ };
857
+ }
858
+
859
+ class Controller extends Controller$1 {
860
+ constructor(..._args) {
861
+ super(..._args);
862
+ /**
863
+ * Fetches the endpoint with given args, updating the Rest Hooks cache with the response or error upon completion.
864
+ * @see https://resthooks.io/docs/api/Controller#fetch
865
+ */
866
+ this.fetch = (endpoint, ...args) => {
867
+ const action = createFetch(endpoint, {
868
+ args
869
+ });
870
+ this.dispatch(action);
871
+ return action.meta.promise;
872
+ };
873
+ }
874
+ }
875
+
876
+ class ResetError extends Error {
877
+ constructor() {
878
+ super('Aborted due to RESET');
879
+ this.name = 'ResetError';
880
+ }
881
+ }
882
+
883
+ /** Handles all async network dispatches
884
+ *
885
+ * Dedupes concurrent requests by keeping track of all fetches in flight
886
+ * and returning existing promises for requests already in flight.
887
+ *
888
+ * Interfaces with store via a redux-compatible middleware.
889
+ *
890
+ * @see https://resthooks.io/docs/api/NetworkManager
891
+ */
892
+ class NetworkManager {
893
+ constructor(dataExpiryLength = 60000, errorExpiryLength = 1000) {
894
+ this.fetched = Object.create(null);
895
+ this.resolvers = {};
896
+ this.rejectors = {};
897
+ this.fetchedAt = {};
898
+ this.getState = () => initialState;
899
+ this.controller = new Controller();
900
+ this.dataExpiryLength = dataExpiryLength;
901
+ this.errorExpiryLength = errorExpiryLength;
902
+ this.middleware = ({
903
+ dispatch,
904
+ getState,
905
+ controller
906
+ }) => {
907
+ this.getState = getState;
908
+ this.controller = controller;
909
+ return next => action => {
910
+ var _action$endpoint;
911
+ switch (action.type) {
912
+ case FETCH_TYPE:
913
+ this.handleFetch(action, dispatch, controller);
914
+ // This is the only case that causes any state change
915
+ // It's important to intercept other fetches as we don't want to trigger reducers during
916
+ // render - so we need to stop 'readonly' fetches which can be triggered in render
917
+ if (action.meta.optimisticResponse !== undefined || ((_action$endpoint = action.endpoint) == null ? void 0 : _action$endpoint.getOptimisticResponse) !== undefined && action.endpoint.sideEffect) {
918
+ return next(action);
919
+ }
920
+ return Promise.resolve();
921
+ case SET_TYPE:
922
+ // only receive after new state is computed
923
+ return next(action).then(() => {
924
+ if (action.meta.key in this.fetched) {
925
+ var _controller$getState$;
926
+ // Note: meta *must* be set by reducer so this should be safe
927
+ const error = (_controller$getState$ = controller.getState().meta[action.meta.key]) == null ? void 0 : _controller$getState$.error;
928
+ // processing errors result in state meta having error, so we should reject the promise
929
+ if (error) {
930
+ // TODO: use only new action types
931
+ this.handleReceive(createReceiveError(error, action.meta));
932
+ } else {
933
+ this.handleReceive(action);
934
+ }
935
+ }
936
+ });
937
+ case RESET_TYPE:
938
+ {
939
+ const rejectors = {
940
+ ...this.rejectors
941
+ };
942
+ this.clearAll();
943
+ return next(action).then(() => {
944
+ // there could be external listeners to the promise
945
+ // this must happen after commit so our own rejector knows not to dispatch an error based on this
946
+ for (const k in rejectors) {
947
+ rejectors[k](new ResetError());
948
+ }
949
+ });
950
+ }
951
+ default:
952
+ return next(action);
953
+ }
954
+ };
955
+ };
956
+ }
957
+
958
+ /** Used by DevtoolsManager to determine whether to log an action */
959
+ skipLogging(action) {
960
+ /* istanbul ignore next */
961
+ return action.type === FETCH_TYPE && action.meta.key in this.fetched;
962
+ }
963
+
964
+ /** On mount */
965
+ init() {
966
+ delete this.cleanupDate;
967
+ }
968
+
969
+ /** Ensures all promises are completed by rejecting remaining. */
970
+ cleanup() {
971
+ // ensure no dispatches after unmount
972
+ // this must be reversible (done in init) so useEffect() remains symmetric
973
+ this.cleanupDate = Date.now();
974
+ }
975
+ allSettled() {
976
+ const fetches = Object.values(this.fetched);
977
+ if (fetches.length) return Promise.allSettled(fetches);
978
+ }
979
+
980
+ /** Clear all promise state */
981
+ clearAll() {
982
+ for (const k in this.rejectors) {
983
+ this.clear(k);
984
+ }
985
+ }
986
+
987
+ /** Clear promise state for a given key */
988
+ clear(key) {
989
+ this.fetched[key].catch(() => {});
990
+ delete this.resolvers[key];
991
+ delete this.rejectors[key];
992
+ delete this.fetched[key];
993
+ delete this.fetchedAt[key];
994
+ }
995
+ getLastReset() {
996
+ if (this.cleanupDate) return this.cleanupDate;
997
+ const lastReset = this.controller.getState().lastReset;
998
+ if (lastReset instanceof Date) return lastReset.valueOf();
999
+ if (typeof lastReset !== 'number') return -Infinity;
1000
+ return lastReset;
1001
+ }
1002
+
1003
+ /** Called when middleware intercepts 'rest-hooks/fetch' action.
1004
+ *
1005
+ * Will then start a promise for a key and potentially start the network
1006
+ * fetch.
1007
+ *
1008
+ * Uses throttle only when instructed by action meta. This is valuable
1009
+ * for ensures mutation requests always go through.
1010
+ */
1011
+ handleFetch(action, dispatch, controller) {
1012
+ const fetch = action.payload;
1013
+ const {
1014
+ key,
1015
+ throttle,
1016
+ resolve,
1017
+ reject
1018
+ } = action.meta;
1019
+ // TODO(breaking): remove support for Date type in 'Receive' action
1020
+ const createdAt = typeof action.meta.createdAt !== 'number' ? action.meta.createdAt.getTime() : action.meta.createdAt;
1021
+ const deferedFetch = () => {
1022
+ let promise = fetch();
1023
+ const resolvePromise = promise => promise.then(data => {
1024
+ resolve(data);
1025
+ return data;
1026
+ }).catch(error => {
1027
+ reject(error);
1028
+ throw error;
1029
+ });
1030
+ // schedule non-throttled resolutions in a microtask before receive
1031
+ // this enables users awaiting their fetch to trigger any react updates needed to deal
1032
+ // with upcoming changes because of the fetch (for instance avoiding suspense if something is deleted)
1033
+ if (!throttle && action.endpoint) {
1034
+ promise = resolvePromise(promise);
1035
+ }
1036
+ promise = promise.then(data => {
1037
+ let lastReset = this.getLastReset();
1038
+
1039
+ /* istanbul ignore else */
1040
+ if (process.env.NODE_ENV !== 'production' && isNaN(lastReset)) {
1041
+ console.error('state.lastReset is NaN. Only positive timestamps are valid.');
1042
+ lastReset = 0;
1043
+ }
1044
+
1045
+ // don't update state with promises started before last clear
1046
+ if (createdAt >= lastReset) {
1047
+ // we still check for controller in case someone didn't have type protection since this didn't always exist
1048
+ if (action.endpoint && this.controller) {
1049
+ this.controller.resolve(action.endpoint, {
1050
+ args: action.meta.args,
1051
+ response: data,
1052
+ fetchedAt: createdAt
1053
+ });
1054
+ } else {
1055
+ var _action$meta$options$, _action$meta$options;
1056
+ // TODO(breaking): is this branch still possible? remove in next major update
1057
+ // does this throw if the reducer fails? - no because reducer is wrapped in try/catch
1058
+ this.controller.dispatch(createReceive$1(data, {
1059
+ ...action.meta,
1060
+ fetchedAt: createdAt,
1061
+ dataExpiryLength: (_action$meta$options$ = (_action$meta$options = action.meta.options) == null ? void 0 : _action$meta$options.dataExpiryLength) != null ? _action$meta$options$ : this.dataExpiryLength
1062
+ }));
1063
+ }
1064
+ }
1065
+ return data;
1066
+ }).catch(error => {
1067
+ const lastReset = this.getLastReset();
1068
+ // don't update state with promises started before last clear
1069
+ if (createdAt >= lastReset) {
1070
+ if (action.endpoint && this.controller) {
1071
+ this.controller.resolve(action.endpoint, {
1072
+ args: action.meta.args,
1073
+ response: error,
1074
+ fetchedAt: createdAt,
1075
+ error: true
1076
+ });
1077
+ } else {
1078
+ var _action$meta$options$2, _action$meta$options2;
1079
+ this.controller.dispatch(createReceiveError(error, {
1080
+ ...action.meta,
1081
+ errorExpiryLength: (_action$meta$options$2 = (_action$meta$options2 = action.meta.options) == null ? void 0 : _action$meta$options2.errorExpiryLength) != null ? _action$meta$options$2 : this.errorExpiryLength,
1082
+ fetchedAt: createdAt
1083
+ }));
1084
+ }
1085
+ }
1086
+ throw error;
1087
+ });
1088
+ // legacy behavior schedules resolution after dispatch
1089
+ if (!throttle && !action.endpoint) {
1090
+ promise = resolvePromise(promise);
1091
+ }
1092
+ return promise;
1093
+ };
1094
+ if (throttle) {
1095
+ return this.throttle(key, deferedFetch, createdAt).then(data => resolve(data)).catch(error => reject(error));
1096
+ } else {
1097
+ return deferedFetch().catch(() => {});
1098
+ }
1099
+ }
1100
+
1101
+ /** Called when middleware intercepts a receive action.
1102
+ *
1103
+ * Will resolve the promise associated with receive key.
1104
+ */
1105
+ handleReceive(action) {
1106
+ // this can still turn out to be untrue since this is async
1107
+ if (action.meta.key in this.fetched) {
1108
+ let promiseHandler;
1109
+ if (action.error) {
1110
+ promiseHandler = this.rejectors[action.meta.key];
1111
+ } else {
1112
+ promiseHandler = this.resolvers[action.meta.key];
1113
+ }
1114
+ promiseHandler(action.payload);
1115
+ // since we're resolved we no longer need to keep track of this promise
1116
+ this.clear(action.meta.key);
1117
+ }
1118
+ }
1119
+
1120
+ /** Attaches NetworkManager to store
1121
+ *
1122
+ * Intercepts 'rest-hooks/fetch' actions to start requests.
1123
+ *
1124
+ * Resolve/rejects a request when matching 'rest-hooks/receive' event
1125
+ * is seen.
1126
+ */
1127
+ getMiddleware() {
1128
+ return this.middleware;
1129
+ }
1130
+
1131
+ /** Ensures only one request for a given key is in flight at any time
1132
+ *
1133
+ * Uses key to either retrieve in-flight promise, or if not
1134
+ * create a new promise and call fetch.
1135
+ *
1136
+ * Note: The new promise is not actually tied to fetch at all,
1137
+ * but is resolved when the expected 'recieve' action is processed.
1138
+ * This ensures promises are resolved only once their data is processed
1139
+ * by the reducer.
1140
+ */
1141
+ throttle(key, fetch, createdAt) {
1142
+ const lastReset = this.getLastReset();
1143
+ // we're already fetching so reuse the promise
1144
+ // fetches after reset do not count
1145
+ if (key in this.fetched && this.fetchedAt[key] > lastReset) {
1146
+ return this.fetched[key];
1147
+ }
1148
+ this.fetched[key] = new Promise((resolve, reject) => {
1149
+ this.resolvers[key] = resolve;
1150
+ this.rejectors[key] = reject;
1151
+ });
1152
+ this.fetchedAt[key] = createdAt;
1153
+
1154
+ // since our real promise is resolved via the wrapReducer(),
1155
+ // we should just stop all errors here.
1156
+ // TODO: decouple this from useFetcher() (that's what's dispatching the error the resolves in here)
1157
+ RIC$1(() => {
1158
+ fetch().catch(() => null);
1159
+ }, {
1160
+ timeout: 500
1161
+ });
1162
+ return this.fetched[key];
1163
+ }
1164
+ }
1165
+
1166
+ /* istanbul ignore file */
1167
+ /**
1168
+ * @deprecated use createReducer instead
1169
+ */
1170
+ const reducer = createReducer(new Controller());
1171
+ var reducer$1 = reducer;
1172
+
1173
+ function applyManager(managers, controller) {
1174
+ return managers.map(manager => {
1175
+ const middleware = manager.getMiddleware();
1176
+ return ({
1177
+ dispatch,
1178
+ getState
1179
+ }) => {
1180
+ controller.dispatch = dispatch;
1181
+ controller.getState = getState;
1182
+ // this is needed for backwards compatibility as we added 'controller' prop previously
1183
+ const API = Object.create(controller, {
1184
+ controller: {
1185
+ value: controller
1186
+ }
1187
+ });
1188
+ // controller is a superset of the middleware API
1189
+ return middleware(API);
1190
+ };
1191
+ });
1192
+ }
1193
+
1194
+ /* These should be compatible with redux */
1195
+
1196
+ var newActions = /*#__PURE__*/Object.freeze({
1197
+ __proto__: null
1198
+ });
1199
+
1200
+ class BrowserConnectionListener {
1201
+ isOnline() {
1202
+ if (navigator.onLine !== undefined) {
1203
+ return navigator.onLine;
1204
+ }
1205
+ return true;
1206
+ }
1207
+ addOnlineListener(handler) {
1208
+ addEventListener('online', handler);
1209
+ }
1210
+ removeOnlineListener(handler) {
1211
+ removeEventListener('online', handler);
1212
+ }
1213
+ addOfflineListener(handler) {
1214
+ addEventListener('offline', handler);
1215
+ }
1216
+ removeOfflineListener(handler) {
1217
+ removeEventListener('offline', handler);
1218
+ }
1219
+ }
1220
+ class AlwaysOnlineConnectionListener {
1221
+ isOnline() {
1222
+ /* istanbul ignore next */
1223
+ return true;
1224
+ }
1225
+ addOnlineListener() {}
1226
+ removeOnlineListener() {}
1227
+ addOfflineListener() {}
1228
+ removeOfflineListener() {}
1229
+ }
1230
+ let DefaultConnectionListener;
1231
+ /* istanbul ignore if */
1232
+ if (typeof navigator !== 'undefined' && typeof addEventListener === 'function') {
1233
+ DefaultConnectionListener = BrowserConnectionListener;
1234
+ } else {
1235
+ /* istanbul ignore next */
1236
+ DefaultConnectionListener = AlwaysOnlineConnectionListener;
1237
+ }
1238
+ var DefaultConnectionListener$1 = DefaultConnectionListener;
1239
+
1240
+ /**
1241
+ * PollingSubscription keeps a given resource updated by
1242
+ * dispatching a fetch at a rate equal to the minimum update
1243
+ * interval requested.
1244
+ *
1245
+ * @see https://resthooks.io/docs/api/PollingSubscription
1246
+ */
1247
+ class PollingSubscription {
1248
+ constructor({
1249
+ key,
1250
+ schema,
1251
+ fetch,
1252
+ frequency,
1253
+ getState
1254
+ }, dispatch, connectionListener) {
1255
+ this.frequencyHistogram = new Map();
1256
+ /** What happens when browser goes offline */
1257
+ this.offlineListener = () => {
1258
+ // this clears existing listeners, so no need to clear offline listener
1259
+ this.cleanup();
1260
+ this.connectionListener.addOnlineListener(this.onlineListener);
1261
+ };
1262
+ /** What happens when browser comes online */
1263
+ this.onlineListener = () => {
1264
+ this.connectionListener.removeOnlineListener(this.onlineListener);
1265
+ const now = Date.now();
1266
+ this.startId = setTimeout(() => {
1267
+ if (this.startId) {
1268
+ delete this.startId;
1269
+ this.update();
1270
+ this.run();
1271
+ } else if (process.env.NODE_ENV !== 'production') {
1272
+ console.warn(`Poll setTimeout for ${this.key} still running, but timeoutId deleted`);
1273
+ }
1274
+ }, Math.max(0, this.lastFetchTime() - now + this.frequency));
1275
+ this.connectionListener.addOfflineListener(this.offlineListener);
1276
+ };
1277
+ if (frequency === undefined) throw new Error('frequency needed for polling subscription');
1278
+ this.schema = schema;
1279
+ this.fetch = fetch;
1280
+ this.frequency = frequency;
1281
+ this.key = key;
1282
+ this.frequencyHistogram.set(this.frequency, 1);
1283
+ this.dispatch = dispatch;
1284
+ this.getState = getState;
1285
+ this.connectionListener = connectionListener || new DefaultConnectionListener$1();
1286
+
1287
+ // Kickstart running since this is initialized after the online notif is sent
1288
+ if (this.connectionListener.isOnline()) {
1289
+ this.onlineListener();
1290
+ } else {
1291
+ this.offlineListener();
1292
+ }
1293
+ }
1294
+
1295
+ /** Subscribe to a frequency */
1296
+ add(frequency) {
1297
+ if (frequency === undefined) return;
1298
+ if (this.frequencyHistogram.has(frequency)) {
1299
+ this.frequencyHistogram.set(frequency, this.frequencyHistogram.get(frequency) + 1);
1300
+ } else {
1301
+ this.frequencyHistogram.set(frequency, 1);
1302
+
1303
+ // new min so restart service
1304
+ if (frequency < this.frequency) {
1305
+ this.frequency = frequency;
1306
+ this.run();
1307
+ }
1308
+ }
1309
+ }
1310
+
1311
+ /** Unsubscribe from a frequency */
1312
+ remove(frequency) {
1313
+ if (frequency === undefined) return false;
1314
+ if (this.frequencyHistogram.has(frequency)) {
1315
+ this.frequencyHistogram.set(frequency, this.frequencyHistogram.get(frequency) - 1);
1316
+ if (this.frequencyHistogram.get(frequency) < 1) {
1317
+ this.frequencyHistogram.delete(frequency);
1318
+
1319
+ // nothing subscribed to this anymore...it is invalid
1320
+ if (this.frequencyHistogram.size === 0) {
1321
+ this.cleanup();
1322
+ return true;
1323
+ }
1324
+
1325
+ // this was the min, so find the next size
1326
+ if (frequency <= this.frequency) {
1327
+ this.frequency = Math.min(...this.frequencyHistogram.keys());
1328
+ this.run();
1329
+ }
1330
+ }
1331
+ } /* istanbul ignore next */else if (process.env.NODE_ENV !== 'production') {
1332
+ console.error(`Mismatched remove: ${frequency} is not subscribed for ${this.key}`);
1333
+ }
1334
+ return false;
1335
+ }
1336
+
1337
+ /** Cleanup means clearing out background interval. */
1338
+ cleanup() {
1339
+ if (this.intervalId) {
1340
+ clearInterval(this.intervalId);
1341
+ delete this.intervalId;
1342
+ }
1343
+ if (this.lastIntervalId) {
1344
+ clearInterval(this.lastIntervalId);
1345
+ delete this.lastIntervalId;
1346
+ }
1347
+ if (this.startId) {
1348
+ clearTimeout(this.startId);
1349
+ delete this.startId;
1350
+ }
1351
+ this.connectionListener.removeOnlineListener(this.onlineListener);
1352
+ this.connectionListener.removeOfflineListener(this.offlineListener);
1353
+ }
1354
+
1355
+ /** Trigger request for latest resource */
1356
+ update() {
1357
+ const endpoint = () => this.fetch();
1358
+ endpoint.schema = this.schema;
1359
+ endpoint.key = () => this.key;
1360
+ endpoint.dataExpiryLength = this.frequency / 2;
1361
+ endpoint.errorExpiryLength = this.frequency / 10;
1362
+ endpoint.errorPolicy = () => 'soft';
1363
+ const action = createFetch(endpoint, {
1364
+ args: []
1365
+ });
1366
+ // stop any errors here from bubbling
1367
+ action.meta.promise.catch(e => null);
1368
+ this.dispatch(action);
1369
+ }
1370
+ /** Run polling process with current frequency
1371
+ *
1372
+ * Will clean up old poll interval on next run
1373
+ */
1374
+ run() {
1375
+ if (this.startId) return;
1376
+ if (this.intervalId) this.lastIntervalId = this.intervalId;
1377
+ this.intervalId = setInterval(() => {
1378
+ // since we don't know how long into the last poll it was before resetting
1379
+ // we wait til the next fetch to clear old intervals
1380
+ if (this.lastIntervalId) {
1381
+ clearInterval(this.lastIntervalId);
1382
+ delete this.lastIntervalId;
1383
+ }
1384
+ if (this.intervalId) this.update();else if (process.env.NODE_ENV !== 'production') {
1385
+ console.warn(`Poll intervalId for ${this.key} still running, but intervalId deleted`);
1386
+ }
1387
+ }, this.frequency);
1388
+ }
1389
+
1390
+ /** Last fetch time */
1391
+ lastFetchTime() {
1392
+ var _this$getState$meta$t, _this$getState$meta$t2;
1393
+ return (_this$getState$meta$t = (_this$getState$meta$t2 = this.getState().meta[this.key]) == null ? void 0 : _this$getState$meta$t2.date) != null ? _this$getState$meta$t : 0;
1394
+ }
1395
+ }
1396
+
1397
+ /** Properties sent to Subscription constructor */
1398
+
1399
+ /** Interface handling a single resource subscription */
1400
+
1401
+ /** The static class that constructs Subscription */
1402
+
1403
+ /** Handles subscription actions -> fetch or receive actions
1404
+ *
1405
+ * Constructor takes a SubscriptionConstructable class to control how
1406
+ * subscriptions are handled. (e.g., polling, websockets)
1407
+ *
1408
+ * @see https://resthooks.io/docs/api/SubscriptionManager
1409
+ */
1410
+ class SubscriptionManager {
1411
+ constructor(Subscription) {
1412
+ this.subscriptions = {};
1413
+ this.Subscription = Subscription;
1414
+ this.middleware = ({
1415
+ dispatch,
1416
+ getState
1417
+ }) => {
1418
+ return next => action => {
1419
+ switch (action.type) {
1420
+ case SUBSCRIBE_TYPE:
1421
+ try {
1422
+ this.handleSubscribe(action, dispatch, getState);
1423
+ } catch (e) {
1424
+ console.error(e);
1425
+ }
1426
+ return Promise.resolve();
1427
+ case UNSUBSCRIBE_TYPE:
1428
+ this.handleUnsubscribe(action, dispatch);
1429
+ return Promise.resolve();
1430
+ default:
1431
+ return next(action);
1432
+ }
1433
+ };
1434
+ };
1435
+ }
1436
+
1437
+ /** Ensures all subscriptions are cleaned up. */
1438
+ cleanup() {
1439
+ for (const key in this.subscriptions) {
1440
+ this.subscriptions[key].cleanup();
1441
+ }
1442
+ }
1443
+
1444
+ /** Called when middleware intercepts 'rest-hooks/subscribe' action.
1445
+ *
1446
+ */
1447
+ handleSubscribe(action, dispatch, getState) {
1448
+ let options;
1449
+ if (action.endpoint) {
1450
+ const {
1451
+ endpoint
1452
+ } = action;
1453
+ const {
1454
+ args
1455
+ } = action.meta;
1456
+ options = {
1457
+ schema: endpoint.schema,
1458
+ fetch: () => endpoint(...args),
1459
+ frequency: endpoint.pollFrequency,
1460
+ key: endpoint.key(...args),
1461
+ getState
1462
+ };
1463
+ } else {
1464
+ var _action$meta$options;
1465
+ options = {
1466
+ key: action.meta.key,
1467
+ frequency: (_action$meta$options = action.meta.options) == null ? void 0 : _action$meta$options.pollFrequency,
1468
+ schema: action.meta.schema,
1469
+ fetch: action.meta.fetch,
1470
+ getState
1471
+ };
1472
+ }
1473
+ if (options.key in this.subscriptions) {
1474
+ this.subscriptions[options.key].add(options.frequency);
1475
+ } else {
1476
+ this.subscriptions[options.key] = new this.Subscription(options, dispatch);
1477
+ }
1478
+ }
1479
+
1480
+ /** Called when middleware intercepts 'rest-hooks/unsubscribe' action.
1481
+ *
1482
+ */
1483
+ handleUnsubscribe(action, dispatch) {
1484
+ var _action$meta$options2;
1485
+ const key = action.meta.key;
1486
+ const frequency = (_action$meta$options2 = action.meta.options) == null ? void 0 : _action$meta$options2.pollFrequency;
1487
+
1488
+ /* istanbul ignore else */
1489
+ if (key in this.subscriptions) {
1490
+ const empty = this.subscriptions[key].remove(frequency);
1491
+ if (empty) {
1492
+ delete this.subscriptions[key];
1493
+ }
1494
+ } else if (process.env.NODE_ENV !== 'production') {
1495
+ console.error(`Mismatched unsubscribe: ${key} is not subscribed`);
1496
+ }
1497
+ }
1498
+
1499
+ /** Attaches Manager to store
1500
+ *
1501
+ * Intercepts 'rest-hooks/subscribe'/'rest-hooks/unsubscribe' to register resources that
1502
+ * need to be kept up to date.
1503
+ *
1504
+ * Will possibly dispatch 'rest-hooks/fetch' or 'rest-hooks/receive' to keep resources fresh
1505
+ *
1506
+ */
1507
+ getMiddleware() {
1508
+ return this.middleware;
1509
+ }
1510
+ }
1511
+
1512
+ var _globalThis$document;
1513
+ const HASINTL = typeof Intl !== 'undefined';
1514
+ const DEFAULT_CONFIG = {
1515
+ name: `Rest Hooks: ${(_globalThis$document = globalThis.document) == null ? void 0 : _globalThis$document.title}`,
1516
+ autoPause: true,
1517
+ serialize: {
1518
+ options: undefined,
1519
+ /* istanbul ignore next */
1520
+ replacer: HASINTL ? (key, value) => {
1521
+ if (typeof value === 'number' && typeof key === 'string' && isFinite(value) && (key === 'date' || key.endsWith('At'))) {
1522
+ return Intl.DateTimeFormat('en-US', {
1523
+ hour: 'numeric',
1524
+ minute: 'numeric',
1525
+ second: 'numeric',
1526
+ fractionalSecondDigits: 3
1527
+ }).format(value);
1528
+ }
1529
+ return value;
1530
+ } : undefined
1531
+ }
1532
+ };
1533
+
1534
+ /** Integrates with https://github.com/reduxjs/redux-devtools
1535
+ *
1536
+ * Options: https://github.com/reduxjs/redux-devtools/blob/main/extension/docs/API/Arguments.md
1537
+ *
1538
+ * @see https://resthooks.io/docs/api/DevToolsManager
1539
+ */
1540
+ class DevToolsManager {
1541
+ constructor(config, skipLogging) {
1542
+ /* istanbul ignore next */
1543
+ this.devTools = typeof window !== 'undefined' && window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__.connect({
1544
+ ...DEFAULT_CONFIG,
1545
+ config
1546
+ });
1547
+
1548
+ /* istanbul ignore if */
1549
+ /* istanbul ignore next */
1550
+ if (this.devTools) {
1551
+ this.middleware = controller => {
1552
+ const reducer = createReducer(controller);
1553
+ return next => action => {
1554
+ const ret = next(action);
1555
+ ret.then(() => {
1556
+ if (skipLogging != null && skipLogging(action)) return;
1557
+ const state = controller.getState();
1558
+ this.devTools.send(action, state.optimistic.reduce(reducer, state), undefined, 'REST_HOOKS');
1559
+ });
1560
+ return ret;
1561
+ };
1562
+ };
1563
+ } else {
1564
+ this.middleware = () => next => action => next(action);
1565
+ }
1566
+ }
1567
+
1568
+ /** Called when initial state is ready */
1569
+ init(state) {
1570
+ /* istanbul ignore if */
1571
+ if (this.devTools) this.devTools.init(state);
1572
+ }
1573
+
1574
+ /** Ensures all subscriptions are cleaned up. */
1575
+ cleanup() {}
1576
+
1577
+ /** Attaches Manager to store
1578
+ *
1579
+ */
1580
+ getMiddleware() {
1581
+ return this.middleware;
1582
+ }
1583
+ }
1584
+
1585
+ /** Handling network unauthorized indicators like HTTP 401
1586
+ *
1587
+ * @see https://resthooks.io/docs/api/LogoutManager
1588
+ */
1589
+ class LogoutManager {
1590
+ constructor({
1591
+ handleLogout,
1592
+ shouldLogout
1593
+ } = {}) {
1594
+ if (handleLogout) this.handleLogout = handleLogout;
1595
+ if (shouldLogout) this.shouldLogout = shouldLogout;
1596
+ this.middleware = controller => next => async action => {
1597
+ await next(action);
1598
+ if (action.type === SET_TYPE && action.error && this.shouldLogout(action.payload)) {
1599
+ this.handleLogout(controller);
1600
+ }
1601
+ };
1602
+ }
1603
+ cleanup() {}
1604
+ getMiddleware() {
1605
+ return this.middleware;
1606
+ }
1607
+ shouldLogout(error) {
1608
+ // 401 indicates reauthorization is needed
1609
+ return error.status === 401;
1610
+ }
1611
+ handleLogout(controller) {
1612
+ controller.resetEntireStore();
1613
+ }
1614
+ }
1615
+
1616
+ // this further restricts the types to be future compatible
1617
+
1618
+ Object.hasOwn = Object.hasOwn || /* istanbul ignore next */function hasOwn(it, key) {
1619
+ return Object.prototype.hasOwnProperty.call(it, key);
1620
+ };
1621
+
1622
+ Object.defineProperty(exports, 'ExpiryStatus', {
1623
+ enumerable: true,
1624
+ get: function () { return normalizr.ExpiryStatus; }
1625
+ });
1626
+ exports.Controller = Controller;
1627
+ exports.DefaultConnectionListener = DefaultConnectionListener$1;
1628
+ exports.DevToolsManager = DevToolsManager;
1629
+ exports.LogoutManager = LogoutManager;
1630
+ exports.NetworkManager = NetworkManager;
1631
+ exports.PollingSubscription = PollingSubscription;
1632
+ exports.ResetError = ResetError;
1633
+ exports.SubscriptionManager = SubscriptionManager;
1634
+ exports.__INTERNAL__ = internal;
1635
+ exports.actionTypes = actionTypes;
1636
+ exports.applyManager = applyManager;
1637
+ exports.createFetch = createFetch;
1638
+ exports.createReceive = createReceive;
1639
+ exports.createReducer = createReducer;
1640
+ exports.initialState = initialState;
1641
+ exports.legacyActions = index;
1642
+ exports.newActions = newActions;
1643
+ exports.reducer = reducer$1;