ropegeo-common 1.12.11 → 1.12.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/RopeGeoCursorPaginationHttpRequest.d.ts +6 -0
- package/dist/components/RopeGeoCursorPaginationHttpRequest.d.ts.map +1 -1
- package/dist/components/RopeGeoCursorPaginationHttpRequest.js +33 -5
- package/dist/components/RopeGeoHttpRequest.d.ts +6 -0
- package/dist/components/RopeGeoHttpRequest.d.ts.map +1 -1
- package/dist/components/RopeGeoHttpRequest.js +24 -5
- package/dist/components/RopeGeoPaginationHttpRequest.d.ts +6 -0
- package/dist/components/RopeGeoPaginationHttpRequest.d.ts.map +1 -1
- package/dist/components/RopeGeoPaginationHttpRequest.js +30 -5
- package/dist/helpers/network/index.d.ts +1 -1
- package/dist/helpers/network/index.d.ts.map +1 -1
- package/dist/helpers/network/index.js +3 -1
- package/dist/helpers/network/networkRequestPolicy.d.ts +10 -0
- package/dist/helpers/network/networkRequestPolicy.d.ts.map +1 -1
- package/dist/helpers/network/networkRequestPolicy.js +55 -0
- package/package.json +1 -1
|
@@ -44,6 +44,12 @@ export type RopeGeoCursorPaginationHttpRequestProps<T = unknown> = {
|
|
|
44
44
|
loadMore: () => void;
|
|
45
45
|
hasMore: boolean;
|
|
46
46
|
timeoutCountdown: number | null;
|
|
47
|
+
/**
|
|
48
|
+
* Re-runs from the first page while online: aborts any `loadMore`, resets the cursor to the
|
|
49
|
+
* initial `queryParams`, sets `loading` to `true`, clears `errors`, and clears `data` until the
|
|
50
|
+
* new first page resolves. No-op when `isOnline` is `false`.
|
|
51
|
+
*/
|
|
52
|
+
reload: () => void;
|
|
47
53
|
}) => ReactNode;
|
|
48
54
|
};
|
|
49
55
|
export declare function RopeGeoCursorPaginationHttpRequest<T = unknown>({ service, method, path, pathParams, queryParams, timeoutAfterSeconds, isOnline, refreshOnReconnect, children, }: RopeGeoCursorPaginationHttpRequestProps<T>): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RopeGeoCursorPaginationHttpRequest.d.ts","sourceRoot":"","sources":["../../src/components/RopeGeoCursorPaginationHttpRequest.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"RopeGeoCursorPaginationHttpRequest.d.ts","sourceRoot":"","sources":["../../src/components/RopeGeoCursorPaginationHttpRequest.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAWvC,OAAO,EACL,KAAK,sBAAsB,EAE5B,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,MAAM,EAAE,OAAO,EAAoB,MAAM,sBAAsB,CAAC;AAsCzE,MAAM,MAAM,uCAAuC,CAAC,CAAC,GAAG,OAAO,IAAI;IACjE,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,CAAC,OAAO,MAAM,CAAC,CAAC,MAAM,OAAO,MAAM,CAAC,CAAC;IAC9C,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,WAAW,EAAE,sBAAsB,CAAC;IACpC;;;OAGG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;;;OAMG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B;;;;;OAKG;IACH,QAAQ,EAAE,CAAC,IAAI,EAAE;QACf,OAAO,EAAE,OAAO,CAAC;QACjB,WAAW,EAAE,OAAO,CAAC;QACrB;;;WAGG;QACH,UAAU,EAAE,OAAO,CAAC;QACpB,IAAI,EAAE,CAAC,EAAE,GAAG,IAAI,CAAC;QACjB,MAAM,EAAE,KAAK,GAAG,IAAI,CAAC;QACrB,QAAQ,EAAE,MAAM,IAAI,CAAC;QACrB,OAAO,EAAE,OAAO,CAAC;QACjB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;QAChC;;;;WAIG;QACH,MAAM,EAAE,MAAM,IAAI,CAAC;KACpB,KAAK,SAAS,CAAC;CACjB,CAAC;AAEF,wBAAgB,kCAAkC,CAAC,CAAC,GAAG,OAAO,EAAE,EAC9D,OAAO,EACP,MAAmB,EACnB,IAAI,EACJ,UAAU,EACV,WAAW,EACX,mBAAmB,EACnB,QAAQ,EACR,kBAA0B,EAC1B,QAAQ,GACT,EAAE,uCAAuC,CAAC,CAAC,CAAC,2CAkX5C"}
|
|
@@ -38,6 +38,8 @@ function RopeGeoCursorPaginationHttpRequest({ service, method = RopeGeoHttpReque
|
|
|
38
38
|
const [errors, setErrors] = (0, react_1.useState)(null);
|
|
39
39
|
const [timeoutCountdown, setTimeoutCountdown] = (0, react_1.useState)(null);
|
|
40
40
|
const [hasCommittedOnce, setHasCommittedOnce] = (0, react_1.useState)(false);
|
|
41
|
+
const [reloadTick, setReloadTick] = (0, react_1.useState)(0);
|
|
42
|
+
const pendingReloadRef = (0, react_1.useRef)(false);
|
|
41
43
|
const errorsRef = (0, react_1.useRef)(errors);
|
|
42
44
|
const hasCommittedRef = (0, react_1.useRef)(hasCommittedOnce);
|
|
43
45
|
errorsRef.current = errors;
|
|
@@ -57,12 +59,27 @@ function RopeGeoCursorPaginationHttpRequest({ service, method = RopeGeoHttpReque
|
|
|
57
59
|
const fullPath = queryString ? `${resolvedPath}?${queryString}` : resolvedPath;
|
|
58
60
|
return new URL(fullPath, baseUrl).toString();
|
|
59
61
|
}, [service, path, pathParams]);
|
|
62
|
+
const reload = (0, react_1.useCallback)(() => {
|
|
63
|
+
if (isOnline === false)
|
|
64
|
+
return;
|
|
65
|
+
pendingReloadRef.current = true;
|
|
66
|
+
setReloadTick((n) => n + 1);
|
|
67
|
+
}, [isOnline]);
|
|
60
68
|
(0, react_1.useEffect)(() => {
|
|
61
69
|
const online = isOnline !== false;
|
|
62
70
|
const prevOnline = prevIsOnlineRef.current;
|
|
63
71
|
const reconnecting = prevOnline === false && online;
|
|
64
72
|
const keyChanged = lastRequestKeyRef.current !== requestKey;
|
|
73
|
+
const isManualReload = pendingReloadRef.current;
|
|
74
|
+
if (isManualReload) {
|
|
75
|
+
pendingReloadRef.current = false;
|
|
76
|
+
loadMoreAbortRef.current?.abort();
|
|
77
|
+
loadMoreAbortRef.current = null;
|
|
78
|
+
loadingMoreRef.current = false;
|
|
79
|
+
setLoadingMore(false);
|
|
80
|
+
}
|
|
65
81
|
if (!online) {
|
|
82
|
+
pendingReloadRef.current = false;
|
|
66
83
|
if (keyChanged) {
|
|
67
84
|
lastRequestKeyRef.current = requestKey;
|
|
68
85
|
setData(null);
|
|
@@ -87,9 +104,18 @@ function RopeGeoCursorPaginationHttpRequest({ service, method = RopeGeoHttpReque
|
|
|
87
104
|
setParams(queryParams);
|
|
88
105
|
setErrors(null);
|
|
89
106
|
}
|
|
107
|
+
else if (isManualReload) {
|
|
108
|
+
setHasCommittedOnce(false);
|
|
109
|
+
setData(null);
|
|
110
|
+
setParams(queryParams);
|
|
111
|
+
setErrors(null);
|
|
112
|
+
}
|
|
90
113
|
if (!keyChanged && reconnecting) {
|
|
91
114
|
const onlyNoNetwork = errorsRef.current?.message === network_1.NO_NETWORK_MESSAGE;
|
|
92
|
-
if (
|
|
115
|
+
if (!isManualReload &&
|
|
116
|
+
hasCommittedRef.current &&
|
|
117
|
+
onlyNoNetwork &&
|
|
118
|
+
!refreshOnReconnect) {
|
|
93
119
|
setErrors(null);
|
|
94
120
|
setLoading(false);
|
|
95
121
|
prevIsOnlineRef.current = true;
|
|
@@ -109,7 +135,7 @@ function RopeGeoCursorPaginationHttpRequest({ service, method = RopeGeoHttpReque
|
|
|
109
135
|
hasCommittedRef.current &&
|
|
110
136
|
errorsRef.current?.message === network_1.NO_NETWORK_MESSAGE &&
|
|
111
137
|
refreshOnReconnect;
|
|
112
|
-
if (!keyChanged && !keepStaleDuringFetch) {
|
|
138
|
+
if (!keyChanged && !keepStaleDuringFetch && !isManualReload) {
|
|
113
139
|
setData(null);
|
|
114
140
|
setParams(queryParams);
|
|
115
141
|
}
|
|
@@ -142,7 +168,7 @@ function RopeGeoCursorPaginationHttpRequest({ service, method = RopeGeoHttpReque
|
|
|
142
168
|
return;
|
|
143
169
|
const text = await res.text();
|
|
144
170
|
if (!res.ok) {
|
|
145
|
-
setErrors(new Error(
|
|
171
|
+
setErrors(new Error((0, network_1.formatHttpStatusMessage)(res.status, text || res.statusText)));
|
|
146
172
|
setData(null);
|
|
147
173
|
setHasCommittedOnce(false);
|
|
148
174
|
return;
|
|
@@ -184,7 +210,7 @@ function RopeGeoCursorPaginationHttpRequest({ service, method = RopeGeoHttpReque
|
|
|
184
210
|
if (cancelled)
|
|
185
211
|
return;
|
|
186
212
|
if (timedOutRef.current) {
|
|
187
|
-
setErrors(new Error(network_1.NETWORK_REQUEST_TIMED_OUT_MESSAGE));
|
|
213
|
+
setErrors(new Error((0, network_1.formatNetworkRequestErrorMessage)(new Error(network_1.NETWORK_REQUEST_TIMED_OUT_MESSAGE))));
|
|
188
214
|
setData(null);
|
|
189
215
|
setHasCommittedOnce(false);
|
|
190
216
|
return;
|
|
@@ -195,7 +221,7 @@ function RopeGeoCursorPaginationHttpRequest({ service, method = RopeGeoHttpReque
|
|
|
195
221
|
url,
|
|
196
222
|
error: err instanceof Error ? err.message : String(err),
|
|
197
223
|
});
|
|
198
|
-
setErrors(
|
|
224
|
+
setErrors(new Error((0, network_1.formatNetworkRequestErrorMessage)(err)));
|
|
199
225
|
setData(null);
|
|
200
226
|
setHasCommittedOnce(false);
|
|
201
227
|
})
|
|
@@ -222,6 +248,7 @@ function RopeGeoCursorPaginationHttpRequest({ service, method = RopeGeoHttpReque
|
|
|
222
248
|
isOnline,
|
|
223
249
|
refreshOnReconnect,
|
|
224
250
|
requestKey,
|
|
251
|
+
reloadTick,
|
|
225
252
|
]);
|
|
226
253
|
(0, react_1.useEffect)(() => {
|
|
227
254
|
return () => {
|
|
@@ -325,5 +352,6 @@ function RopeGeoCursorPaginationHttpRequest({ service, method = RopeGeoHttpReque
|
|
|
325
352
|
loadMore,
|
|
326
353
|
hasMore,
|
|
327
354
|
timeoutCountdown,
|
|
355
|
+
reload,
|
|
328
356
|
}) }));
|
|
329
357
|
}
|
|
@@ -56,6 +56,12 @@ export type RopeGeoHttpRequestProps<T = unknown> = {
|
|
|
56
56
|
* after `NETWORK_REQUEST_SLOW_THRESHOLD_MS` from `ropegeo-common/helpers`).
|
|
57
57
|
*/
|
|
58
58
|
timeoutCountdown: number | null;
|
|
59
|
+
/**
|
|
60
|
+
* Re-runs the current request while online. Sets `loading` to `true`, clears `errors`, and
|
|
61
|
+
* keeps existing `data` visible until the new response resolves (when data was already
|
|
62
|
+
* committed). No-op when `isOnline` is `false`.
|
|
63
|
+
*/
|
|
64
|
+
reload: () => void;
|
|
59
65
|
}) => ReactNode;
|
|
60
66
|
};
|
|
61
67
|
export declare function RopeGeoHttpRequest<T = unknown>({ service, method, path, pathParams, queryParams, body, timeoutAfterSeconds, isOnline, refreshOnReconnect, children, }: RopeGeoHttpRequestProps<T>): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RopeGeoHttpRequest.d.ts","sourceRoot":"","sources":["../../src/components/RopeGeoHttpRequest.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"RopeGeoHttpRequest.d.ts","sourceRoot":"","sources":["../../src/components/RopeGeoHttpRequest.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAavC,eAAO,MAAM,OAAO;;CAEV,CAAC;AACX,MAAM,MAAM,OAAO,GAAG,CAAC,OAAO,OAAO,CAAC,CAAC,MAAM,OAAO,OAAO,CAAC,CAAC;AAE7D,eAAO,MAAM,MAAM;;;;;CAKT,CAAC;AACX,MAAM,MAAM,MAAM,GAAG,CAAC,OAAO,MAAM,CAAC,CAAC,MAAM,OAAO,MAAM,CAAC,CAAC;AAE1D,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,OAAO,EAAE,MAAM,CAEpD,CAAC;AAmCF,MAAM,MAAM,uBAAuB,CAAC,CAAC,GAAG,OAAO,IAAI;IACjD,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC,CAAC;IACpE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;;;OAMG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B;;;OAGG;IACH,QAAQ,EAAE,CAAC,IAAI,EAAE;QACf,OAAO,EAAE,OAAO,CAAC;QACjB;;;WAGG;QACH,UAAU,EAAE,OAAO,CAAC;QACpB,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC;QACf,MAAM,EAAE,KAAK,GAAG,IAAI,CAAC;QACrB;;;;WAIG;QACH,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;QAChC;;;;WAIG;QACH,MAAM,EAAE,MAAM,IAAI,CAAC;KACpB,KAAK,SAAS,CAAC;CACjB,CAAC;AAEF,wBAAgB,kBAAkB,CAAC,CAAC,GAAG,OAAO,EAAE,EAC9C,OAAO,EACP,MAAM,EACN,IAAI,EACJ,UAAU,EACV,WAAW,EACX,IAAI,EACJ,mBAAmB,EACnB,QAAQ,EACR,kBAA0B,EAC1B,QAAQ,GACT,EAAE,uBAAuB,CAAC,CAAC,CAAC,2CAuP5B"}
|
|
@@ -46,10 +46,18 @@ function RopeGeoHttpRequest({ service, method, path, pathParams, queryParams, bo
|
|
|
46
46
|
const [errors, setErrors] = (0, react_1.useState)(null);
|
|
47
47
|
const [timeoutCountdown, setTimeoutCountdown] = (0, react_1.useState)(null);
|
|
48
48
|
const [hasCommittedOnce, setHasCommittedOnce] = (0, react_1.useState)(false);
|
|
49
|
+
const [reloadTick, setReloadTick] = (0, react_1.useState)(0);
|
|
50
|
+
const pendingReloadRef = (0, react_1.useRef)(false);
|
|
49
51
|
const errorsRef = (0, react_1.useRef)(errors);
|
|
50
52
|
const hasCommittedRef = (0, react_1.useRef)(hasCommittedOnce);
|
|
51
53
|
errorsRef.current = errors;
|
|
52
54
|
hasCommittedRef.current = hasCommittedOnce;
|
|
55
|
+
const reload = (0, react_1.useCallback)(() => {
|
|
56
|
+
if (isOnline === false)
|
|
57
|
+
return;
|
|
58
|
+
pendingReloadRef.current = true;
|
|
59
|
+
setReloadTick((n) => n + 1);
|
|
60
|
+
}, [isOnline]);
|
|
53
61
|
const pathParamsKey = JSON.stringify(pathParams ?? null);
|
|
54
62
|
const queryParamsKey = JSON.stringify(queryParams ?? null);
|
|
55
63
|
const bodyKey = body === undefined || body === null
|
|
@@ -65,7 +73,12 @@ function RopeGeoHttpRequest({ service, method, path, pathParams, queryParams, bo
|
|
|
65
73
|
const prevOnline = prevIsOnlineRef.current;
|
|
66
74
|
const reconnecting = prevOnline === false && online;
|
|
67
75
|
const keyChanged = lastRequestKeyRef.current !== requestKey;
|
|
76
|
+
const isManualReload = pendingReloadRef.current;
|
|
77
|
+
if (isManualReload) {
|
|
78
|
+
pendingReloadRef.current = false;
|
|
79
|
+
}
|
|
68
80
|
if (!online) {
|
|
81
|
+
pendingReloadRef.current = false;
|
|
69
82
|
if (keyChanged) {
|
|
70
83
|
lastRequestKeyRef.current = requestKey;
|
|
71
84
|
setData(null);
|
|
@@ -86,7 +99,10 @@ function RopeGeoHttpRequest({ service, method, path, pathParams, queryParams, bo
|
|
|
86
99
|
}
|
|
87
100
|
if (!keyChanged && reconnecting) {
|
|
88
101
|
const onlyNoNetwork = errorsRef.current?.message === network_1.NO_NETWORK_MESSAGE;
|
|
89
|
-
if (
|
|
102
|
+
if (!isManualReload &&
|
|
103
|
+
hasCommittedRef.current &&
|
|
104
|
+
onlyNoNetwork &&
|
|
105
|
+
!refreshOnReconnect) {
|
|
90
106
|
setErrors(null);
|
|
91
107
|
setLoading(false);
|
|
92
108
|
prevIsOnlineRef.current = true;
|
|
@@ -106,7 +122,8 @@ function RopeGeoHttpRequest({ service, method, path, pathParams, queryParams, bo
|
|
|
106
122
|
hasCommittedRef.current &&
|
|
107
123
|
errorsRef.current?.message === network_1.NO_NETWORK_MESSAGE &&
|
|
108
124
|
refreshOnReconnect;
|
|
109
|
-
|
|
125
|
+
const keepStaleForManualReload = isManualReload && hasCommittedRef.current;
|
|
126
|
+
if (!keyChanged && !keepStaleDuringFetch && !keepStaleForManualReload) {
|
|
110
127
|
setData(null);
|
|
111
128
|
}
|
|
112
129
|
const policyDispose = timeoutMs == null
|
|
@@ -144,7 +161,7 @@ function RopeGeoHttpRequest({ service, method, path, pathParams, queryParams, bo
|
|
|
144
161
|
return;
|
|
145
162
|
const text = await res.text();
|
|
146
163
|
if (!res.ok) {
|
|
147
|
-
setErrors(new Error(
|
|
164
|
+
setErrors(new Error((0, network_1.formatHttpStatusMessage)(res.status, text || res.statusText)));
|
|
148
165
|
setData(null);
|
|
149
166
|
setHasCommittedOnce(false);
|
|
150
167
|
return;
|
|
@@ -182,7 +199,7 @@ function RopeGeoHttpRequest({ service, method, path, pathParams, queryParams, bo
|
|
|
182
199
|
if (cancelled)
|
|
183
200
|
return;
|
|
184
201
|
if (timedOutRef.current) {
|
|
185
|
-
setErrors(new Error(network_1.NETWORK_REQUEST_TIMED_OUT_MESSAGE));
|
|
202
|
+
setErrors(new Error((0, network_1.formatNetworkRequestErrorMessage)(new Error(network_1.NETWORK_REQUEST_TIMED_OUT_MESSAGE))));
|
|
186
203
|
setData(null);
|
|
187
204
|
setHasCommittedOnce(false);
|
|
188
205
|
return;
|
|
@@ -193,7 +210,7 @@ function RopeGeoHttpRequest({ service, method, path, pathParams, queryParams, bo
|
|
|
193
210
|
url,
|
|
194
211
|
error: err instanceof Error ? err.message : String(err),
|
|
195
212
|
});
|
|
196
|
-
setErrors(
|
|
213
|
+
setErrors(new Error((0, network_1.formatNetworkRequestErrorMessage)(err)));
|
|
197
214
|
setData(null);
|
|
198
215
|
setHasCommittedOnce(false);
|
|
199
216
|
})
|
|
@@ -220,6 +237,7 @@ function RopeGeoHttpRequest({ service, method, path, pathParams, queryParams, bo
|
|
|
220
237
|
isOnline,
|
|
221
238
|
refreshOnReconnect,
|
|
222
239
|
requestKey,
|
|
240
|
+
reloadTick,
|
|
223
241
|
]);
|
|
224
242
|
const refreshing = loading && hasCommittedOnce;
|
|
225
243
|
return ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: children({
|
|
@@ -228,5 +246,6 @@ function RopeGeoHttpRequest({ service, method, path, pathParams, queryParams, bo
|
|
|
228
246
|
data,
|
|
229
247
|
errors,
|
|
230
248
|
timeoutCountdown,
|
|
249
|
+
reload,
|
|
231
250
|
}) }));
|
|
232
251
|
}
|
|
@@ -51,6 +51,12 @@ export type RopeGeoPaginationHttpRequestProps<T = unknown> = {
|
|
|
51
51
|
errors: Error | null;
|
|
52
52
|
/** Timeout countdown for the active phase (initial page or current batch); `null` between phases. */
|
|
53
53
|
timeoutCountdown: number | null;
|
|
54
|
+
/**
|
|
55
|
+
* Re-runs the full pagination pass while online. Sets `loading` to `true`, clears `errors`,
|
|
56
|
+
* and resets progress (`received` / `total` / `data`) until the new pass completes. No-op when
|
|
57
|
+
* `isOnline` is `false`.
|
|
58
|
+
*/
|
|
59
|
+
reload: () => void;
|
|
54
60
|
}) => ReactNode;
|
|
55
61
|
};
|
|
56
62
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RopeGeoPaginationHttpRequest.d.ts","sourceRoot":"","sources":["../../src/components/RopeGeoPaginationHttpRequest.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"RopeGeoPaginationHttpRequest.d.ts","sourceRoot":"","sources":["../../src/components/RopeGeoPaginationHttpRequest.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAYvC,OAAO,EACL,KAAK,gBAAgB,EAEtB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,MAAM,EAAE,OAAO,EAAoB,MAAM,sBAAsB,CAAC;AA8DzE,MAAM,MAAM,iCAAiC,CAAC,CAAC,GAAG,OAAO,IAAI;IAC3D,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,CAAC,OAAO,MAAM,CAAC,CAAC,MAAM,OAAO,MAAM,CAAC,CAAC;IAC9C,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,WAAW,EAAE,gBAAgB,CAAC;IAC9B;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;;;OAMG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,QAAQ,EAAE,CAAC,IAAI,EAAE;QACf,OAAO,EAAE,OAAO,CAAC;QACjB;;;WAGG;QACH,UAAU,EAAE,OAAO,CAAC;QACpB,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;QACrB;;;WAGG;QACH,IAAI,EAAE,CAAC,EAAE,GAAG,IAAI,CAAC;QACjB,+FAA+F;QAC/F,MAAM,EAAE,KAAK,GAAG,IAAI,CAAC;QACrB,qGAAqG;QACrG,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;QAChC;;;;WAIG;QACH,MAAM,EAAE,MAAM,IAAI,CAAC;KACpB,KAAK,SAAS,CAAC;CACjB,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,4BAA4B,CAAC,CAAC,GAAG,OAAO,EAAE,EACxD,OAAO,EACP,MAAmB,EACnB,IAAI,EACJ,UAAU,EACV,WAAW,EACX,SAAc,EACd,mBAAmB,EACnB,QAAQ,EACR,kBAA0B,EAC1B,QAAQ,GACT,EAAE,iCAAiC,CAAC,CAAC,CAAC,2CAmVtC"}
|
|
@@ -65,6 +65,8 @@ function RopeGeoPaginationHttpRequest({ service, method = RopeGeoHttpRequest_1.M
|
|
|
65
65
|
const [errors, setErrors] = (0, react_1.useState)(null);
|
|
66
66
|
const [timeoutCountdown, setTimeoutCountdown] = (0, react_1.useState)(null);
|
|
67
67
|
const [hasCommittedOnce, setHasCommittedOnce] = (0, react_1.useState)(false);
|
|
68
|
+
const [reloadTick, setReloadTick] = (0, react_1.useState)(0);
|
|
69
|
+
const pendingReloadRef = (0, react_1.useRef)(false);
|
|
68
70
|
const errorsRef = (0, react_1.useRef)(errors);
|
|
69
71
|
const hasCommittedRef = (0, react_1.useRef)(hasCommittedOnce);
|
|
70
72
|
errorsRef.current = errors;
|
|
@@ -75,12 +77,23 @@ function RopeGeoPaginationHttpRequest({ service, method = RopeGeoHttpRequest_1.M
|
|
|
75
77
|
const requestKey = (0, react_1.useMemo)(() => `${service}|${method}|${path}|${pathParamsKey}|${queryParamsKey}|${effectiveBatch}|${timeoutAfterSeconds ?? ""}`, [service, method, path, pathParamsKey, queryParamsKey, effectiveBatch, timeoutAfterSeconds]);
|
|
76
78
|
const prevIsOnlineRef = (0, react_1.useRef)(undefined);
|
|
77
79
|
const lastRequestKeyRef = (0, react_1.useRef)("");
|
|
80
|
+
const reload = (0, react_1.useCallback)(() => {
|
|
81
|
+
if (isOnline === false)
|
|
82
|
+
return;
|
|
83
|
+
pendingReloadRef.current = true;
|
|
84
|
+
setReloadTick((n) => n + 1);
|
|
85
|
+
}, [isOnline]);
|
|
78
86
|
(0, react_1.useEffect)(() => {
|
|
79
87
|
const online = isOnline !== false;
|
|
80
88
|
const prevOnline = prevIsOnlineRef.current;
|
|
81
89
|
const reconnecting = prevOnline === false && online;
|
|
82
90
|
const keyChanged = lastRequestKeyRef.current !== requestKey;
|
|
91
|
+
const isManualReload = pendingReloadRef.current;
|
|
92
|
+
if (isManualReload) {
|
|
93
|
+
pendingReloadRef.current = false;
|
|
94
|
+
}
|
|
83
95
|
if (!online) {
|
|
96
|
+
pendingReloadRef.current = false;
|
|
84
97
|
if (keyChanged) {
|
|
85
98
|
lastRequestKeyRef.current = requestKey;
|
|
86
99
|
setHasCommittedOnce(false);
|
|
@@ -103,9 +116,19 @@ function RopeGeoPaginationHttpRequest({ service, method = RopeGeoHttpRequest_1.M
|
|
|
103
116
|
setData(null);
|
|
104
117
|
setErrors(null);
|
|
105
118
|
}
|
|
119
|
+
else if (isManualReload) {
|
|
120
|
+
setHasCommittedOnce(false);
|
|
121
|
+
setReceived(0);
|
|
122
|
+
setTotal(null);
|
|
123
|
+
setData(null);
|
|
124
|
+
setErrors(null);
|
|
125
|
+
}
|
|
106
126
|
if (!keyChanged && reconnecting) {
|
|
107
127
|
const onlyNoNetwork = errorsRef.current?.message === network_1.NO_NETWORK_MESSAGE;
|
|
108
|
-
if (
|
|
128
|
+
if (!isManualReload &&
|
|
129
|
+
hasCommittedRef.current &&
|
|
130
|
+
onlyNoNetwork &&
|
|
131
|
+
!refreshOnReconnect) {
|
|
109
132
|
setErrors(null);
|
|
110
133
|
setLoading(false);
|
|
111
134
|
prevIsOnlineRef.current = true;
|
|
@@ -124,7 +147,7 @@ function RopeGeoPaginationHttpRequest({ service, method = RopeGeoHttpRequest_1.M
|
|
|
124
147
|
hasCommittedRef.current &&
|
|
125
148
|
errorsRef.current?.message === network_1.NO_NETWORK_MESSAGE &&
|
|
126
149
|
refreshOnReconnect;
|
|
127
|
-
if (!keyChanged && !keepStaleDuringFetch) {
|
|
150
|
+
if (!keyChanged && !keepStaleDuringFetch && !isManualReload) {
|
|
128
151
|
setReceived(0);
|
|
129
152
|
setTotal(null);
|
|
130
153
|
setData(null);
|
|
@@ -204,7 +227,7 @@ function RopeGeoPaginationHttpRequest({ service, method = RopeGeoHttpRequest_1.M
|
|
|
204
227
|
const text = await res.text();
|
|
205
228
|
if (!res.ok) {
|
|
206
229
|
abortController.abort();
|
|
207
|
-
throw new Error(
|
|
230
|
+
throw new Error((0, network_1.formatHttpStatusMessage)(res.status, text || res.statusText));
|
|
208
231
|
}
|
|
209
232
|
if (text.length === 0) {
|
|
210
233
|
abortController.abort();
|
|
@@ -238,7 +261,7 @@ function RopeGeoPaginationHttpRequest({ service, method = RopeGeoHttpRequest_1.M
|
|
|
238
261
|
catch (err) {
|
|
239
262
|
if (pageNum !== 1 && merged != null && merged.consumeDidTimeout()) {
|
|
240
263
|
abortController.abort();
|
|
241
|
-
throw new Error(network_1.NETWORK_REQUEST_TIMED_OUT_MESSAGE);
|
|
264
|
+
throw new Error((0, network_1.formatNetworkRequestErrorMessage)(new Error(network_1.NETWORK_REQUEST_TIMED_OUT_MESSAGE)));
|
|
242
265
|
}
|
|
243
266
|
throw err;
|
|
244
267
|
}
|
|
@@ -301,7 +324,7 @@ function RopeGeoPaginationHttpRequest({ service, method = RopeGeoHttpRequest_1.M
|
|
|
301
324
|
console.error("[RopeGeoPaginationHttpRequest] Request failed", {
|
|
302
325
|
error: err instanceof Error ? err.message : String(err),
|
|
303
326
|
});
|
|
304
|
-
setErrors(
|
|
327
|
+
setErrors(new Error((0, network_1.formatNetworkRequestErrorMessage)(err)));
|
|
305
328
|
setData(null);
|
|
306
329
|
setHasCommittedOnce(false);
|
|
307
330
|
}
|
|
@@ -326,6 +349,7 @@ function RopeGeoPaginationHttpRequest({ service, method = RopeGeoHttpRequest_1.M
|
|
|
326
349
|
isOnline,
|
|
327
350
|
refreshOnReconnect,
|
|
328
351
|
requestKey,
|
|
352
|
+
reloadTick,
|
|
329
353
|
]);
|
|
330
354
|
const refreshing = loading && hasCommittedOnce;
|
|
331
355
|
return ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: children({
|
|
@@ -336,5 +360,6 @@ function RopeGeoPaginationHttpRequest({ service, method = RopeGeoHttpRequest_1.M
|
|
|
336
360
|
data,
|
|
337
361
|
errors,
|
|
338
362
|
timeoutCountdown,
|
|
363
|
+
reload,
|
|
339
364
|
}) }));
|
|
340
365
|
}
|
|
@@ -3,5 +3,5 @@
|
|
|
3
3
|
* Published as `ropegeo-common/helpers/network`. Prefer this entry over `ropegeo-common/helpers` in
|
|
4
4
|
* Metro/RN bundles so the full helpers barrel (S3 folder upload, etc.) is not resolved.
|
|
5
5
|
*/
|
|
6
|
-
export { NETWORK_REQUEST_TIMED_OUT_MESSAGE, NO_NETWORK_MESSAGE, installNetworkRequestPolicyTimers, isAbortError, isNetworkRequestTimeoutError, mergeParentSignalWithDeadline, resolveRequestTimeoutMs, type MergedDeadlineHandles, type NetworkRequestPolicyTimerCallbacks, } from "./networkRequestPolicy";
|
|
6
|
+
export { formatHttpStatusMessage, formatNetworkRequestErrorMessage, NETWORK_REQUEST_TIMED_OUT_MESSAGE, NO_NETWORK_MESSAGE, installNetworkRequestPolicyTimers, isAbortError, isNetworkRequestTimeoutError, mergeParentSignalWithDeadline, resolveRequestTimeoutMs, type MergedDeadlineHandles, type NetworkRequestPolicyTimerCallbacks, } from "./networkRequestPolicy";
|
|
7
7
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/helpers/network/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,iCAAiC,EACjC,kBAAkB,EAClB,iCAAiC,EACjC,YAAY,EACZ,4BAA4B,EAC5B,6BAA6B,EAC7B,uBAAuB,EACvB,KAAK,qBAAqB,EAC1B,KAAK,kCAAkC,GACxC,MAAM,wBAAwB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/helpers/network/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,uBAAuB,EACvB,gCAAgC,EAChC,iCAAiC,EACjC,kBAAkB,EAClB,iCAAiC,EACjC,YAAY,EACZ,4BAA4B,EAC5B,6BAA6B,EAC7B,uBAAuB,EACvB,KAAK,qBAAqB,EAC1B,KAAK,kCAAkC,GACxC,MAAM,wBAAwB,CAAC"}
|
|
@@ -5,8 +5,10 @@
|
|
|
5
5
|
* Metro/RN bundles so the full helpers barrel (S3 folder upload, etc.) is not resolved.
|
|
6
6
|
*/
|
|
7
7
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
-
exports.resolveRequestTimeoutMs = exports.mergeParentSignalWithDeadline = exports.isNetworkRequestTimeoutError = exports.isAbortError = exports.installNetworkRequestPolicyTimers = exports.NO_NETWORK_MESSAGE = exports.NETWORK_REQUEST_TIMED_OUT_MESSAGE = void 0;
|
|
8
|
+
exports.resolveRequestTimeoutMs = exports.mergeParentSignalWithDeadline = exports.isNetworkRequestTimeoutError = exports.isAbortError = exports.installNetworkRequestPolicyTimers = exports.NO_NETWORK_MESSAGE = exports.NETWORK_REQUEST_TIMED_OUT_MESSAGE = exports.formatNetworkRequestErrorMessage = exports.formatHttpStatusMessage = void 0;
|
|
9
9
|
var networkRequestPolicy_1 = require("./networkRequestPolicy");
|
|
10
|
+
Object.defineProperty(exports, "formatHttpStatusMessage", { enumerable: true, get: function () { return networkRequestPolicy_1.formatHttpStatusMessage; } });
|
|
11
|
+
Object.defineProperty(exports, "formatNetworkRequestErrorMessage", { enumerable: true, get: function () { return networkRequestPolicy_1.formatNetworkRequestErrorMessage; } });
|
|
10
12
|
Object.defineProperty(exports, "NETWORK_REQUEST_TIMED_OUT_MESSAGE", { enumerable: true, get: function () { return networkRequestPolicy_1.NETWORK_REQUEST_TIMED_OUT_MESSAGE; } });
|
|
11
13
|
Object.defineProperty(exports, "NO_NETWORK_MESSAGE", { enumerable: true, get: function () { return networkRequestPolicy_1.NO_NETWORK_MESSAGE; } });
|
|
12
14
|
Object.defineProperty(exports, "installNetworkRequestPolicyTimers", { enumerable: true, get: function () { return networkRequestPolicy_1.installNetworkRequestPolicyTimers; } });
|
|
@@ -3,6 +3,16 @@
|
|
|
3
3
|
export declare const NETWORK_REQUEST_TIMED_OUT_MESSAGE = "Network request timed out";
|
|
4
4
|
/** Use this exact message for client-side offline gating and RN fetch failures treated as offline. */
|
|
5
5
|
export declare const NO_NETWORK_MESSAGE = "No network connection";
|
|
6
|
+
/**
|
|
7
|
+
* Formats HTTP response failures as user-facing copy (e.g. "500 Internal Server Error").
|
|
8
|
+
* `detail` can be a response body snippet or `statusText`.
|
|
9
|
+
*/
|
|
10
|
+
export declare function formatHttpStatusMessage(status: number, detail?: string): string;
|
|
11
|
+
/**
|
|
12
|
+
* Normalizes raw network/request errors into stable user-facing copy.
|
|
13
|
+
* Keeps NO_NETWORK_MESSAGE unchanged for offline gating checks.
|
|
14
|
+
*/
|
|
15
|
+
export declare function formatNetworkRequestErrorMessage(error: unknown): string;
|
|
6
16
|
export declare function isNetworkRequestTimeoutError(e: unknown): boolean;
|
|
7
17
|
export declare function isAbortError(e: unknown): boolean;
|
|
8
18
|
/** Milliseconds for `timeoutAfterSeconds` on request components; `null` when timeout is disabled. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"networkRequestPolicy.d.ts","sourceRoot":"","sources":["../../../src/helpers/network/networkRequestPolicy.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAE7E,8EAA8E;AAC9E,eAAO,MAAM,iCAAiC,8BAA8B,CAAC;AAE7E,sGAAsG;AACtG,eAAO,MAAM,kBAAkB,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"networkRequestPolicy.d.ts","sourceRoot":"","sources":["../../../src/helpers/network/networkRequestPolicy.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAE7E,8EAA8E;AAC9E,eAAO,MAAM,iCAAiC,8BAA8B,CAAC;AAE7E,sGAAsG;AACtG,eAAO,MAAM,kBAAkB,0BAA0B,CAAC;AAoB1D;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAO/E;AAED;;;GAGG;AACH,wBAAgB,gCAAgC,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAmBvE;AAED,wBAAgB,4BAA4B,CAAC,CAAC,EAAE,OAAO,GAAG,OAAO,CAEhE;AAED,wBAAgB,YAAY,CAAC,CAAC,EAAE,OAAO,GAAG,OAAO,CAUhD;AAED,qGAAqG;AACrG,wBAAgB,uBAAuB,CAAC,mBAAmB,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CASnF;AAED,MAAM,MAAM,kCAAkC,GAAG;IAC/C,QAAQ,EAAE,MAAM,OAAO,CAAC;IACxB,kBAAkB,EAAE,CAAC,gBAAgB,EAAE,MAAM,KAAK,IAAI,CAAC;IACvD,uBAAuB,EAAE,MAAM,IAAI,CAAC;IACpC,aAAa,EAAE,MAAM,IAAI,CAAC;CAC3B,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,iCAAiC,CAC/C,kBAAkB,EAAE,MAAM,EAC1B,aAAa,EAAE,MAAM,EACrB,SAAS,EAAE,kCAAkC,GAC5C,MAAM,IAAI,CAuCZ;AAED,MAAM,MAAM,qBAAqB,GAAG;IAClC,MAAM,EAAE,WAAW,CAAC;IACpB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,iBAAiB,EAAE,MAAM,OAAO,CAAC;CAClC,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,6BAA6B,CAC3C,YAAY,EAAE,WAAW,EACzB,UAAU,EAAE,MAAM,GACjB,qBAAqB,CAqCvB"}
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
/** Network helpers for optional request deadlines and timeout countdowns. */
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
4
|
exports.NO_NETWORK_MESSAGE = exports.NETWORK_REQUEST_TIMED_OUT_MESSAGE = void 0;
|
|
5
|
+
exports.formatHttpStatusMessage = formatHttpStatusMessage;
|
|
6
|
+
exports.formatNetworkRequestErrorMessage = formatNetworkRequestErrorMessage;
|
|
5
7
|
exports.isNetworkRequestTimeoutError = isNetworkRequestTimeoutError;
|
|
6
8
|
exports.isAbortError = isAbortError;
|
|
7
9
|
exports.resolveRequestTimeoutMs = resolveRequestTimeoutMs;
|
|
@@ -11,6 +13,59 @@ exports.mergeParentSignalWithDeadline = mergeParentSignalWithDeadline;
|
|
|
11
13
|
exports.NETWORK_REQUEST_TIMED_OUT_MESSAGE = "Network request timed out";
|
|
12
14
|
/** Use this exact message for client-side offline gating and RN fetch failures treated as offline. */
|
|
13
15
|
exports.NO_NETWORK_MESSAGE = "No network connection";
|
|
16
|
+
const HTTP_STATUS_TEXT = {
|
|
17
|
+
400: "Bad Request",
|
|
18
|
+
401: "Unauthorized",
|
|
19
|
+
403: "Forbidden",
|
|
20
|
+
404: "Not Found",
|
|
21
|
+
408: "Request Timeout",
|
|
22
|
+
409: "Conflict",
|
|
23
|
+
429: "Too Many Requests",
|
|
24
|
+
500: "Internal Server Error",
|
|
25
|
+
502: "Bad Gateway",
|
|
26
|
+
503: "Service Unavailable",
|
|
27
|
+
504: "Gateway Timeout",
|
|
28
|
+
};
|
|
29
|
+
function firstLineOrEmpty(value) {
|
|
30
|
+
return (value.split("\n")[0] ?? "").trim();
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Formats HTTP response failures as user-facing copy (e.g. "500 Internal Server Error").
|
|
34
|
+
* `detail` can be a response body snippet or `statusText`.
|
|
35
|
+
*/
|
|
36
|
+
function formatHttpStatusMessage(status, detail) {
|
|
37
|
+
const trimmed = (detail ?? "").trim();
|
|
38
|
+
if (trimmed !== "") {
|
|
39
|
+
const line = firstLineOrEmpty(trimmed);
|
|
40
|
+
return line === "" ? String(status) : `${status} ${line}`;
|
|
41
|
+
}
|
|
42
|
+
return `${status} ${HTTP_STATUS_TEXT[status] ?? "HTTP Error"}`;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Normalizes raw network/request errors into stable user-facing copy.
|
|
46
|
+
* Keeps NO_NETWORK_MESSAGE unchanged for offline gating checks.
|
|
47
|
+
*/
|
|
48
|
+
function formatNetworkRequestErrorMessage(error) {
|
|
49
|
+
const raw = error instanceof Error
|
|
50
|
+
? error.message
|
|
51
|
+
: typeof error === "string"
|
|
52
|
+
? error
|
|
53
|
+
: String(error ?? "");
|
|
54
|
+
const msg = raw.trim();
|
|
55
|
+
if (msg === "")
|
|
56
|
+
return "Request failed";
|
|
57
|
+
if (msg === exports.NO_NETWORK_MESSAGE)
|
|
58
|
+
return exports.NO_NETWORK_MESSAGE;
|
|
59
|
+
if (msg === exports.NETWORK_REQUEST_TIMED_OUT_MESSAGE)
|
|
60
|
+
return exports.NETWORK_REQUEST_TIMED_OUT_MESSAGE;
|
|
61
|
+
const http = /^HTTP\s+(\d{3})(?::\s*(.*))?$/i.exec(msg);
|
|
62
|
+
if (http != null) {
|
|
63
|
+
const code = Number(http[1]);
|
|
64
|
+
const detail = (http[2] ?? "").trim();
|
|
65
|
+
return formatHttpStatusMessage(code, detail);
|
|
66
|
+
}
|
|
67
|
+
return msg;
|
|
68
|
+
}
|
|
14
69
|
function isNetworkRequestTimeoutError(e) {
|
|
15
70
|
return e instanceof Error && e.message === exports.NETWORK_REQUEST_TIMED_OUT_MESSAGE;
|
|
16
71
|
}
|