ropegeo-common 1.12.9 → 1.12.11

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/README.md CHANGED
@@ -312,9 +312,9 @@ Abstract classes live under `minimap/abstract/`, concrete under `minimap/concret
312
312
 
313
313
  | Name | Description | Import |
314
314
  | --- | --- | --- |
315
- | `RopeGeoHttpRequest` | Single GET/POST wrapper; parses `Result.fromResponseBody`; optional `timeoutAfterSeconds` (default from helpers) + `timeoutCountdown` children arg. | `import { RopeGeoHttpRequest, Method, Service } from 'ropegeo-common/components'` |
316
- | `RopeGeoCursorPaginationHttpRequest` | Cursor-paginated fetch with `loadMore`; optional `timeoutAfterSeconds`; `timeoutCountdown` on initial and `loadMore` requests. | `import { RopeGeoCursorPaginationHttpRequest } from 'ropegeo-common/components'` |
317
- | `RopeGeoPaginationHttpRequest<T>` | Page-based fetch; page 1 emits `timeoutCountdown`; later pages use the same per-fetch deadline; concatenates `results` into `data` (`T[]` when complete, otherwise `null` with `errors`). | `import { RopeGeoPaginationHttpRequest } from 'ropegeo-common/components'` |
315
+ | `RopeGeoHttpRequest` | Single GET/POST wrapper; parses `Result.fromResponseBody`; optional `timeoutAfterSeconds`, `isOnline`, `refreshOnReconnect`, `timeoutCountdown`, and `refreshing` (stale-while-revalidate) children args. | `import { RopeGeoHttpRequest, Method, Service } from 'ropegeo-common/components'` |
316
+ | `RopeGeoCursorPaginationHttpRequest` | Cursor-paginated fetch with `loadMore`; `data` is `T[] \| null` (null until first success); optional `timeoutAfterSeconds`, `isOnline`, `refreshOnReconnect`, `refreshing`, `timeoutCountdown`. | `import { RopeGeoCursorPaginationHttpRequest } from 'ropegeo-common/components'` |
317
+ | `RopeGeoPaginationHttpRequest<T>` | Page-based fetch; concatenates `results` into `data` (`T[]` when complete, otherwise `null` with `errors`); optional `isOnline`, `refreshOnReconnect`, `refreshing`, `timeoutCountdown`. | `import { RopeGeoPaginationHttpRequest } from 'ropegeo-common/components'` |
318
318
 
319
319
  ---
320
320
 
@@ -14,22 +14,37 @@ export type RopeGeoCursorPaginationHttpRequestProps<T = unknown> = {
14
14
  timeoutAfterSeconds?: number;
15
15
  /**
16
16
  * When `false`, no HTTP requests run and children receive {@link NO_NETWORK_MESSAGE} as the error.
17
- * Same semantics as `isOnline` on {@link RopeGeoHttpRequest}.
17
+ * Previously loaded `data` and cursor `params` are kept until the network returns.
18
18
  */
19
19
  isOnline?: boolean;
20
+ /**
21
+ * When `isOnline` goes from `false` to online and there is already successful data for the same
22
+ * request (only the soft {@link NO_NETWORK_MESSAGE} error), a new fetch runs only if this is
23
+ * `true`. Otherwise stale data stays visible and `errors` is cleared. When there is no
24
+ * successful data yet, or the last error was not the offline placeholder, a fetch always runs.
25
+ * @default false
26
+ */
27
+ refreshOnReconnect?: boolean;
20
28
  /**
21
29
  * Response body is parsed via CursorPaginationResults.fromResponseBody (must include resultType).
22
30
  * Parsed shape is ValidatedCursorPaginationResponse; children receive result.results as data.
31
+ * `data` is `null` until the first successful response for the current request identity, then an
32
+ * array (possibly empty) for loaded pages.
23
33
  */
24
34
  children: (args: {
25
35
  loading: boolean;
26
36
  loadingMore: boolean;
27
- data: T[];
37
+ /**
38
+ * `true` while the initial request is in flight after at least one successful response for the
39
+ * current request identity (stale-while-revalidate). Not used for `loadMore` alone.
40
+ */
41
+ refreshing: boolean;
42
+ data: T[] | null;
28
43
  errors: Error | null;
29
44
  loadMore: () => void;
30
45
  hasMore: boolean;
31
46
  timeoutCountdown: number | null;
32
47
  }) => ReactNode;
33
48
  };
34
- export declare function RopeGeoCursorPaginationHttpRequest<T = unknown>({ service, method, path, pathParams, queryParams, timeoutAfterSeconds, isOnline, children, }: RopeGeoCursorPaginationHttpRequestProps<T>): import("react/jsx-runtime").JSX.Element;
49
+ export declare function RopeGeoCursorPaginationHttpRequest<T = unknown>({ service, method, path, pathParams, queryParams, timeoutAfterSeconds, isOnline, refreshOnReconnect, children, }: RopeGeoCursorPaginationHttpRequestProps<T>): import("react/jsx-runtime").JSX.Element;
35
50
  //# sourceMappingURL=RopeGeoCursorPaginationHttpRequest.d.ts.map
@@ -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;AASvC,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;;;OAGG;IACH,QAAQ,EAAE,CAAC,IAAI,EAAE;QACf,OAAO,EAAE,OAAO,CAAC;QACjB,WAAW,EAAE,OAAO,CAAC;QACrB,IAAI,EAAE,CAAC,EAAE,CAAC;QACV,MAAM,EAAE,KAAK,GAAG,IAAI,CAAC;QACrB,QAAQ,EAAE,MAAM,IAAI,CAAC;QACrB,OAAO,EAAE,OAAO,CAAC;QACjB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;KACjC,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,QAAQ,GACT,EAAE,uCAAuC,CAAC,CAAC,CAAC,2CAoQ5C"}
1
+ {"version":3,"file":"RopeGeoCursorPaginationHttpRequest.d.ts","sourceRoot":"","sources":["../../src/components/RopeGeoCursorPaginationHttpRequest.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AASvC,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;KACjC,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,2CA6U5C"}
@@ -30,16 +30,26 @@ function getResponseBody(raw) {
30
30
  }
31
31
  return raw;
32
32
  }
33
- function RopeGeoCursorPaginationHttpRequest({ service, method = RopeGeoHttpRequest_1.Method.GET, path, pathParams, queryParams, timeoutAfterSeconds, isOnline, children, }) {
33
+ function RopeGeoCursorPaginationHttpRequest({ service, method = RopeGeoHttpRequest_1.Method.GET, path, pathParams, queryParams, timeoutAfterSeconds, isOnline, refreshOnReconnect = false, children, }) {
34
34
  const [loading, setLoading] = (0, react_1.useState)(true);
35
35
  const [loadingMore, setLoadingMore] = (0, react_1.useState)(false);
36
- const [data, setData] = (0, react_1.useState)([]);
36
+ const [data, setData] = (0, react_1.useState)(null);
37
37
  const [params, setParams] = (0, react_1.useState)(queryParams);
38
38
  const [errors, setErrors] = (0, react_1.useState)(null);
39
39
  const [timeoutCountdown, setTimeoutCountdown] = (0, react_1.useState)(null);
40
+ const [hasCommittedOnce, setHasCommittedOnce] = (0, react_1.useState)(false);
41
+ const errorsRef = (0, react_1.useRef)(errors);
42
+ const hasCommittedRef = (0, react_1.useRef)(hasCommittedOnce);
43
+ errorsRef.current = errors;
44
+ hasCommittedRef.current = hasCommittedOnce;
40
45
  const loadingMoreRef = (0, react_1.useRef)(false);
41
46
  const loadMoreAbortRef = (0, react_1.useRef)(null);
42
47
  const hasMore = params.cursor != null;
48
+ const pathParamsKey = JSON.stringify(pathParams ?? null);
49
+ const queryKey = queryParams.toQueryString();
50
+ const requestKey = (0, react_1.useMemo)(() => `${service}|${method}|${path}|${pathParamsKey}|${queryKey}|${timeoutAfterSeconds ?? ""}`, [service, method, path, pathParamsKey, queryKey, timeoutAfterSeconds]);
51
+ const prevIsOnlineRef = (0, react_1.useRef)(undefined);
52
+ const lastRequestKeyRef = (0, react_1.useRef)("");
43
53
  const buildUrl = (0, react_1.useCallback)((p) => {
44
54
  const baseUrl = RopeGeoHttpRequest_1.SERVICE_BASE_URL[service];
45
55
  const resolvedPath = resolvePath(path, pathParams);
@@ -48,24 +58,61 @@ function RopeGeoCursorPaginationHttpRequest({ service, method = RopeGeoHttpReque
48
58
  return new URL(fullPath, baseUrl).toString();
49
59
  }, [service, path, pathParams]);
50
60
  (0, react_1.useEffect)(() => {
51
- if (isOnline === false) {
52
- setData([]);
53
- setParams(queryParams);
61
+ const online = isOnline !== false;
62
+ const prevOnline = prevIsOnlineRef.current;
63
+ const reconnecting = prevOnline === false && online;
64
+ const keyChanged = lastRequestKeyRef.current !== requestKey;
65
+ if (!online) {
66
+ if (keyChanged) {
67
+ lastRequestKeyRef.current = requestKey;
68
+ setData(null);
69
+ setHasCommittedOnce(false);
70
+ setParams(queryParams);
71
+ setErrors(null);
72
+ }
73
+ loadMoreAbortRef.current?.abort();
74
+ loadMoreAbortRef.current = null;
75
+ loadingMoreRef.current = false;
76
+ setLoadingMore(false);
77
+ prevIsOnlineRef.current = false;
54
78
  setLoading(false);
55
79
  setErrors(new Error(network_1.NO_NETWORK_MESSAGE));
56
80
  setTimeoutCountdown(null);
57
81
  return;
58
82
  }
83
+ if (keyChanged) {
84
+ lastRequestKeyRef.current = requestKey;
85
+ setHasCommittedOnce(false);
86
+ setData(null);
87
+ setParams(queryParams);
88
+ setErrors(null);
89
+ }
90
+ if (!keyChanged && reconnecting) {
91
+ const onlyNoNetwork = errorsRef.current?.message === network_1.NO_NETWORK_MESSAGE;
92
+ if (hasCommittedRef.current && onlyNoNetwork && !refreshOnReconnect) {
93
+ setErrors(null);
94
+ setLoading(false);
95
+ prevIsOnlineRef.current = true;
96
+ return;
97
+ }
98
+ }
99
+ prevIsOnlineRef.current = true;
59
100
  let cancelled = false;
60
101
  const abortController = new AbortController();
61
102
  const timedOutRef = { current: false };
62
103
  const requestStartedAt = Date.now();
63
104
  const timeoutMs = (0, network_1.resolveRequestTimeoutMs)(timeoutAfterSeconds);
64
- setData([]);
65
- setParams(queryParams);
66
105
  setLoading(true);
67
106
  setErrors(null);
68
107
  setTimeoutCountdown(null);
108
+ const keepStaleDuringFetch = reconnecting &&
109
+ hasCommittedRef.current &&
110
+ errorsRef.current?.message === network_1.NO_NETWORK_MESSAGE &&
111
+ refreshOnReconnect;
112
+ if (!keyChanged && !keepStaleDuringFetch) {
113
+ setData(null);
114
+ setParams(queryParams);
115
+ }
69
116
  const policyDispose = timeoutMs == null
70
117
  ? () => { }
71
118
  : (0, network_1.installNetworkRequestPolicyTimers)(requestStartedAt, timeoutMs, {
@@ -96,11 +143,15 @@ function RopeGeoCursorPaginationHttpRequest({ service, method = RopeGeoHttpReque
96
143
  const text = await res.text();
97
144
  if (!res.ok) {
98
145
  setErrors(new Error(`HTTP ${res.status}: ${text || res.statusText}`));
99
- setData([]);
146
+ setData(null);
147
+ setHasCommittedOnce(false);
100
148
  return;
101
149
  }
102
150
  if (text.length === 0) {
103
151
  setData([]);
152
+ setParams(queryParams.withCursor(null));
153
+ setErrors(null);
154
+ setHasCommittedOnce(true);
104
155
  return;
105
156
  }
106
157
  try {
@@ -113,6 +164,7 @@ function RopeGeoCursorPaginationHttpRequest({ service, method = RopeGeoHttpReque
113
164
  setData(results);
114
165
  setParams(queryParams.withCursor(nextCursor));
115
166
  setErrors(null);
167
+ setHasCommittedOnce(true);
116
168
  }
117
169
  catch (parseError) {
118
170
  if (!cancelled) {
@@ -123,7 +175,8 @@ function RopeGeoCursorPaginationHttpRequest({ service, method = RopeGeoHttpReque
123
175
  parseError: parseError instanceof Error ? parseError.message : String(parseError),
124
176
  });
125
177
  setErrors(new Error("Invalid JSON response"));
126
- setData([]);
178
+ setData(null);
179
+ setHasCommittedOnce(false);
127
180
  }
128
181
  }
129
182
  })
@@ -132,7 +185,8 @@ function RopeGeoCursorPaginationHttpRequest({ service, method = RopeGeoHttpReque
132
185
  return;
133
186
  if (timedOutRef.current) {
134
187
  setErrors(new Error(network_1.NETWORK_REQUEST_TIMED_OUT_MESSAGE));
135
- setData([]);
188
+ setData(null);
189
+ setHasCommittedOnce(false);
136
190
  return;
137
191
  }
138
192
  if ((0, network_1.isAbortError)(err))
@@ -142,7 +196,8 @@ function RopeGeoCursorPaginationHttpRequest({ service, method = RopeGeoHttpReque
142
196
  error: err instanceof Error ? err.message : String(err),
143
197
  });
144
198
  setErrors(err instanceof Error ? err : new Error(String(err)));
145
- setData([]);
199
+ setData(null);
200
+ setHasCommittedOnce(false);
146
201
  })
147
202
  .finally(() => {
148
203
  policyDispose();
@@ -160,11 +215,13 @@ function RopeGeoCursorPaginationHttpRequest({ service, method = RopeGeoHttpReque
160
215
  service,
161
216
  method,
162
217
  path,
163
- pathParams,
164
- queryParams,
218
+ pathParamsKey,
219
+ queryKey,
165
220
  buildUrl,
166
221
  timeoutAfterSeconds,
167
222
  isOnline,
223
+ refreshOnReconnect,
224
+ requestKey,
168
225
  ]);
169
226
  (0, react_1.useEffect)(() => {
170
227
  return () => {
@@ -222,7 +279,7 @@ function RopeGeoCursorPaginationHttpRequest({ service, method = RopeGeoHttpReque
222
279
  const body = getResponseBody(raw);
223
280
  const result = models_1.CursorPaginationResults.fromResponseBody(body);
224
281
  const { results, nextCursor } = result;
225
- setData((prev) => [...prev, ...results]);
282
+ setData((prev) => [...(prev ?? []), ...results]);
226
283
  setParams((p) => p.withCursor(nextCursor));
227
284
  }
228
285
  catch (parseError) {
@@ -258,9 +315,11 @@ function RopeGeoCursorPaginationHttpRequest({ service, method = RopeGeoHttpReque
258
315
  setLoadingMore(false);
259
316
  });
260
317
  }, [params, method, buildUrl, timeoutAfterSeconds, isOnline]);
318
+ const refreshing = loading && hasCommittedOnce;
261
319
  return ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: children({
262
320
  loading,
263
321
  loadingMore,
322
+ refreshing,
264
323
  data,
265
324
  errors,
266
325
  loadMore,
@@ -24,16 +24,30 @@ export type RopeGeoHttpRequestProps<T = unknown> = {
24
24
  timeoutAfterSeconds?: number;
25
25
  /**
26
26
  * When `false`, the request is not started and children receive {@link NO_NETWORK_MESSAGE} as the
27
- * error. When `true` or omitted, behavior is unchanged. Pass from app-level connectivity (e.g.
28
- * `expo-network`) so fetches are not fired while offline.
27
+ * error. Previously loaded `data` is kept until the network returns. When `true` or omitted,
28
+ * behavior is unchanged. Pass from app-level connectivity (e.g. `expo-network`) so fetches are
29
+ * not fired while offline.
29
30
  */
30
31
  isOnline?: boolean;
32
+ /**
33
+ * When `isOnline` goes from `false` to online and there is already successful data for the same
34
+ * request (only the soft {@link NO_NETWORK_MESSAGE} error), a new fetch runs only if this is
35
+ * `true`. Otherwise stale data stays visible and `errors` is cleared. When there is no
36
+ * successful data yet, or the last error was not the offline placeholder, a fetch always runs.
37
+ * @default false
38
+ */
39
+ refreshOnReconnect?: boolean;
31
40
  /**
32
41
  * Response body is parsed via Result.fromResponseBody (must include resultType and result).
33
42
  * Children receive the validated result.result as data (typed by T).
34
43
  */
35
44
  children: (args: {
36
45
  loading: boolean;
46
+ /**
47
+ * `true` while a request is in flight after at least one successful response for the current
48
+ * request identity (stale-while-revalidate).
49
+ */
50
+ refreshing: boolean;
37
51
  data: T | null;
38
52
  errors: Error | null;
39
53
  /**
@@ -44,5 +58,5 @@ export type RopeGeoHttpRequestProps<T = unknown> = {
44
58
  timeoutCountdown: number | null;
45
59
  }) => ReactNode;
46
60
  };
47
- export declare function RopeGeoHttpRequest<T = unknown>({ service, method, path, pathParams, queryParams, body, timeoutAfterSeconds, isOnline, children, }: RopeGeoHttpRequestProps<T>): import("react/jsx-runtime").JSX.Element;
61
+ export declare function RopeGeoHttpRequest<T = unknown>({ service, method, path, pathParams, queryParams, body, timeoutAfterSeconds, isOnline, refreshOnReconnect, children, }: RopeGeoHttpRequestProps<T>): import("react/jsx-runtime").JSX.Element;
48
62
  //# sourceMappingURL=RopeGeoHttpRequest.d.ts.map
@@ -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;AAWvC,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;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;OAGG;IACH,QAAQ,EAAE,CAAC,IAAI,EAAE;QACf,OAAO,EAAE,OAAO,CAAC;QACjB,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC;QACf,MAAM,EAAE,KAAK,GAAG,IAAI,CAAC;QACrB;;;;WAIG;QACH,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;KACjC,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,QAAQ,GACT,EAAE,uBAAuB,CAAC,CAAC,CAAC,2CAyJ5B"}
1
+ {"version":3,"file":"RopeGeoHttpRequest.d.ts","sourceRoot":"","sources":["../../src/components/RopeGeoHttpRequest.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAWvC,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;KACjC,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,2CA0N5B"}
@@ -40,11 +40,16 @@ function buildUrl(baseUrl, path, pathParams, queryParams) {
40
40
  }
41
41
  return url.toString();
42
42
  }
43
- function RopeGeoHttpRequest({ service, method, path, pathParams, queryParams, body, timeoutAfterSeconds, isOnline, children, }) {
43
+ function RopeGeoHttpRequest({ service, method, path, pathParams, queryParams, body, timeoutAfterSeconds, isOnline, refreshOnReconnect = false, children, }) {
44
44
  const [loading, setLoading] = (0, react_1.useState)(true);
45
45
  const [data, setData] = (0, react_1.useState)(null);
46
46
  const [errors, setErrors] = (0, react_1.useState)(null);
47
47
  const [timeoutCountdown, setTimeoutCountdown] = (0, react_1.useState)(null);
48
+ const [hasCommittedOnce, setHasCommittedOnce] = (0, react_1.useState)(false);
49
+ const errorsRef = (0, react_1.useRef)(errors);
50
+ const hasCommittedRef = (0, react_1.useRef)(hasCommittedOnce);
51
+ errorsRef.current = errors;
52
+ hasCommittedRef.current = hasCommittedOnce;
48
53
  const pathParamsKey = JSON.stringify(pathParams ?? null);
49
54
  const queryParamsKey = JSON.stringify(queryParams ?? null);
50
55
  const bodyKey = body === undefined || body === null
@@ -52,14 +57,43 @@ function RopeGeoHttpRequest({ service, method, path, pathParams, queryParams, bo
52
57
  : typeof body === "object"
53
58
  ? JSON.stringify(body)
54
59
  : body;
60
+ const requestKey = (0, react_1.useMemo)(() => `${service}|${method}|${path}|${pathParamsKey}|${queryParamsKey}|${String(bodyKey)}|${timeoutAfterSeconds ?? ""}`, [service, method, path, pathParamsKey, queryParamsKey, bodyKey, timeoutAfterSeconds]);
61
+ const prevIsOnlineRef = (0, react_1.useRef)(undefined);
62
+ const lastRequestKeyRef = (0, react_1.useRef)("");
55
63
  (0, react_1.useEffect)(() => {
56
- if (isOnline === false) {
64
+ const online = isOnline !== false;
65
+ const prevOnline = prevIsOnlineRef.current;
66
+ const reconnecting = prevOnline === false && online;
67
+ const keyChanged = lastRequestKeyRef.current !== requestKey;
68
+ if (!online) {
69
+ if (keyChanged) {
70
+ lastRequestKeyRef.current = requestKey;
71
+ setData(null);
72
+ setHasCommittedOnce(false);
73
+ setErrors(null);
74
+ }
75
+ prevIsOnlineRef.current = false;
57
76
  setLoading(false);
58
- setData(null);
59
77
  setErrors(new Error(network_1.NO_NETWORK_MESSAGE));
60
78
  setTimeoutCountdown(null);
61
79
  return;
62
80
  }
81
+ if (keyChanged) {
82
+ lastRequestKeyRef.current = requestKey;
83
+ setHasCommittedOnce(false);
84
+ setData(null);
85
+ setErrors(null);
86
+ }
87
+ if (!keyChanged && reconnecting) {
88
+ const onlyNoNetwork = errorsRef.current?.message === network_1.NO_NETWORK_MESSAGE;
89
+ if (hasCommittedRef.current && onlyNoNetwork && !refreshOnReconnect) {
90
+ setErrors(null);
91
+ setLoading(false);
92
+ prevIsOnlineRef.current = true;
93
+ return;
94
+ }
95
+ }
96
+ prevIsOnlineRef.current = true;
63
97
  let cancelled = false;
64
98
  const abortController = new AbortController();
65
99
  const timedOutRef = { current: false };
@@ -68,6 +102,13 @@ function RopeGeoHttpRequest({ service, method, path, pathParams, queryParams, bo
68
102
  setLoading(true);
69
103
  setErrors(null);
70
104
  setTimeoutCountdown(null);
105
+ const keepStaleDuringFetch = reconnecting &&
106
+ hasCommittedRef.current &&
107
+ errorsRef.current?.message === network_1.NO_NETWORK_MESSAGE &&
108
+ refreshOnReconnect;
109
+ if (!keyChanged && !keepStaleDuringFetch) {
110
+ setData(null);
111
+ }
71
112
  const policyDispose = timeoutMs == null
72
113
  ? () => { }
73
114
  : (0, network_1.installNetworkRequestPolicyTimers)(requestStartedAt, timeoutMs, {
@@ -105,10 +146,13 @@ function RopeGeoHttpRequest({ service, method, path, pathParams, queryParams, bo
105
146
  if (!res.ok) {
106
147
  setErrors(new Error(`HTTP ${res.status}: ${text || res.statusText}`));
107
148
  setData(null);
149
+ setHasCommittedOnce(false);
108
150
  return;
109
151
  }
110
152
  if (text.length === 0) {
111
153
  setData(null);
154
+ setErrors(null);
155
+ setHasCommittedOnce(true);
112
156
  return;
113
157
  }
114
158
  try {
@@ -117,6 +161,7 @@ function RopeGeoHttpRequest({ service, method, path, pathParams, queryParams, bo
117
161
  if (!cancelled) {
118
162
  setData(parsed.result);
119
163
  setErrors(null);
164
+ setHasCommittedOnce(true);
120
165
  }
121
166
  }
122
167
  catch (parseError) {
@@ -129,6 +174,7 @@ function RopeGeoHttpRequest({ service, method, path, pathParams, queryParams, bo
129
174
  });
130
175
  setErrors(parseError instanceof Error ? parseError : new Error("Invalid JSON response"));
131
176
  setData(null);
177
+ setHasCommittedOnce(false);
132
178
  }
133
179
  }
134
180
  })
@@ -138,6 +184,7 @@ function RopeGeoHttpRequest({ service, method, path, pathParams, queryParams, bo
138
184
  if (timedOutRef.current) {
139
185
  setErrors(new Error(network_1.NETWORK_REQUEST_TIMED_OUT_MESSAGE));
140
186
  setData(null);
187
+ setHasCommittedOnce(false);
141
188
  return;
142
189
  }
143
190
  if ((0, network_1.isAbortError)(err))
@@ -148,6 +195,7 @@ function RopeGeoHttpRequest({ service, method, path, pathParams, queryParams, bo
148
195
  });
149
196
  setErrors(err instanceof Error ? err : new Error(String(err)));
150
197
  setData(null);
198
+ setHasCommittedOnce(false);
151
199
  })
152
200
  .finally(() => {
153
201
  policyDispose();
@@ -170,9 +218,13 @@ function RopeGeoHttpRequest({ service, method, path, pathParams, queryParams, bo
170
218
  bodyKey,
171
219
  timeoutAfterSeconds,
172
220
  isOnline,
221
+ refreshOnReconnect,
222
+ requestKey,
173
223
  ]);
224
+ const refreshing = loading && hasCommittedOnce;
174
225
  return ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: children({
175
226
  loading,
227
+ refreshing,
176
228
  data,
177
229
  errors,
178
230
  timeoutCountdown,
@@ -20,11 +20,26 @@ export type RopeGeoPaginationHttpRequestProps<T = unknown> = {
20
20
  timeoutAfterSeconds?: number;
21
21
  /**
22
22
  * When `false`, no HTTP requests run and children receive {@link NO_NETWORK_MESSAGE} as the error.
23
- * Same semantics as `isOnline` on {@link RopeGeoHttpRequest}.
23
+ * Previously loaded `data`, `received`, and `total` are kept so UIs can stay on stale results until
24
+ * the network returns. Same semantics as `isOnline` on {@link RopeGeoHttpRequest} and
25
+ * {@link RopeGeoCursorPaginationHttpRequest}.
24
26
  */
25
27
  isOnline?: boolean;
28
+ /**
29
+ * When `isOnline` goes from `false` to online and there is already successful data for the same
30
+ * request (only the soft {@link NO_NETWORK_MESSAGE} error), a new fetch runs only if this is
31
+ * `true`. Otherwise stale data stays visible and `errors` is cleared. When there is no
32
+ * successful data yet, or the last error was not the offline placeholder, a fetch always runs.
33
+ * @default false
34
+ */
35
+ refreshOnReconnect?: boolean;
26
36
  children: (args: {
27
37
  loading: boolean;
38
+ /**
39
+ * `true` while a full pagination pass is in flight after at least one successful completion for
40
+ * the current request identity (stale-while-revalidate).
41
+ */
42
+ refreshing: boolean;
28
43
  received: number;
29
44
  total: number | null;
30
45
  /**
@@ -44,5 +59,5 @@ export type RopeGeoPaginationHttpRequestProps<T = unknown> = {
44
59
  * {@link PaginationResults.fromResponseBody}. Final `data` is pages concatenated in page order.
45
60
  * In-flight requests use one {@link AbortController}: unmount or any failure aborts the rest.
46
61
  */
47
- export declare function RopeGeoPaginationHttpRequest<T = unknown>({ service, method, path, pathParams, queryParams, batchSize, timeoutAfterSeconds, isOnline, children, }: RopeGeoPaginationHttpRequestProps<T>): import("react/jsx-runtime").JSX.Element;
62
+ export declare function RopeGeoPaginationHttpRequest<T = unknown>({ service, method, path, pathParams, queryParams, batchSize, timeoutAfterSeconds, isOnline, refreshOnReconnect, children, }: RopeGeoPaginationHttpRequestProps<T>): import("react/jsx-runtime").JSX.Element;
48
63
  //# sourceMappingURL=RopeGeoPaginationHttpRequest.d.ts.map
@@ -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;AAUvC,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;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,CAAC,IAAI,EAAE;QACf,OAAO,EAAE,OAAO,CAAC;QACjB,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;KACjC,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,QAAQ,GACT,EAAE,iCAAiC,CAAC,CAAC,CAAC,2CAuPtC"}
1
+ {"version":3,"file":"RopeGeoPaginationHttpRequest.d.ts","sourceRoot":"","sources":["../../src/components/RopeGeoPaginationHttpRequest.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAUvC,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;KACjC,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,2CAqTtC"}
@@ -57,36 +57,79 @@ function concatPaginationResultItemsSorted(pagesByNum) {
57
57
  * {@link PaginationResults.fromResponseBody}. Final `data` is pages concatenated in page order.
58
58
  * In-flight requests use one {@link AbortController}: unmount or any failure aborts the rest.
59
59
  */
60
- function RopeGeoPaginationHttpRequest({ service, method = RopeGeoHttpRequest_1.Method.GET, path, pathParams, queryParams, batchSize = 10, timeoutAfterSeconds, isOnline, children, }) {
60
+ function RopeGeoPaginationHttpRequest({ service, method = RopeGeoHttpRequest_1.Method.GET, path, pathParams, queryParams, batchSize = 10, timeoutAfterSeconds, isOnline, refreshOnReconnect = false, children, }) {
61
61
  const [loading, setLoading] = (0, react_1.useState)(true);
62
62
  const [received, setReceived] = (0, react_1.useState)(0);
63
63
  const [total, setTotal] = (0, react_1.useState)(null);
64
64
  const [data, setData] = (0, react_1.useState)(null);
65
65
  const [errors, setErrors] = (0, react_1.useState)(null);
66
66
  const [timeoutCountdown, setTimeoutCountdown] = (0, react_1.useState)(null);
67
+ const [hasCommittedOnce, setHasCommittedOnce] = (0, react_1.useState)(false);
68
+ const errorsRef = (0, react_1.useRef)(errors);
69
+ const hasCommittedRef = (0, react_1.useRef)(hasCommittedOnce);
70
+ errorsRef.current = errors;
71
+ hasCommittedRef.current = hasCommittedOnce;
67
72
  const pathParamsKey = JSON.stringify(pathParams ?? null);
68
73
  const queryParamsKey = queryParams.toQueryString();
69
74
  const effectiveBatch = Math.max(1, Math.floor(batchSize));
75
+ const requestKey = (0, react_1.useMemo)(() => `${service}|${method}|${path}|${pathParamsKey}|${queryParamsKey}|${effectiveBatch}|${timeoutAfterSeconds ?? ""}`, [service, method, path, pathParamsKey, queryParamsKey, effectiveBatch, timeoutAfterSeconds]);
76
+ const prevIsOnlineRef = (0, react_1.useRef)(undefined);
77
+ const lastRequestKeyRef = (0, react_1.useRef)("");
70
78
  (0, react_1.useEffect)(() => {
71
- if (isOnline === false) {
79
+ const online = isOnline !== false;
80
+ const prevOnline = prevIsOnlineRef.current;
81
+ const reconnecting = prevOnline === false && online;
82
+ const keyChanged = lastRequestKeyRef.current !== requestKey;
83
+ if (!online) {
84
+ if (keyChanged) {
85
+ lastRequestKeyRef.current = requestKey;
86
+ setHasCommittedOnce(false);
87
+ setReceived(0);
88
+ setTotal(null);
89
+ setData(null);
90
+ setErrors(null);
91
+ }
92
+ prevIsOnlineRef.current = false;
72
93
  setLoading(false);
73
- setReceived(0);
74
- setTotal(null);
75
- setData(null);
76
94
  setErrors(new Error(network_1.NO_NETWORK_MESSAGE));
77
95
  setTimeoutCountdown(null);
78
96
  return;
79
97
  }
98
+ if (keyChanged) {
99
+ lastRequestKeyRef.current = requestKey;
100
+ setHasCommittedOnce(false);
101
+ setReceived(0);
102
+ setTotal(null);
103
+ setData(null);
104
+ setErrors(null);
105
+ }
106
+ if (!keyChanged && reconnecting) {
107
+ const onlyNoNetwork = errorsRef.current?.message === network_1.NO_NETWORK_MESSAGE;
108
+ if (hasCommittedRef.current && onlyNoNetwork && !refreshOnReconnect) {
109
+ setErrors(null);
110
+ setLoading(false);
111
+ prevIsOnlineRef.current = true;
112
+ return;
113
+ }
114
+ }
115
+ prevIsOnlineRef.current = true;
80
116
  let cancelled = false;
81
117
  const abortController = new AbortController();
82
118
  const { signal } = abortController;
83
119
  const timeoutMs = (0, network_1.resolveRequestTimeoutMs)(timeoutAfterSeconds);
84
120
  setLoading(true);
85
- setReceived(0);
86
- setTotal(null);
87
- setData(null);
88
121
  setErrors(null);
89
122
  setTimeoutCountdown(null);
123
+ const keepStaleDuringFetch = reconnecting &&
124
+ hasCommittedRef.current &&
125
+ errorsRef.current?.message === network_1.NO_NETWORK_MESSAGE &&
126
+ refreshOnReconnect;
127
+ if (!keyChanged && !keepStaleDuringFetch) {
128
+ setReceived(0);
129
+ setTotal(null);
130
+ setData(null);
131
+ setHasCommittedOnce(false);
132
+ }
90
133
  const baseUrl = RopeGeoHttpRequest_1.SERVICE_BASE_URL[service];
91
134
  const resolvedPath = resolvePath(path, pathParams);
92
135
  const baseInit = {
@@ -219,6 +262,7 @@ function RopeGeoPaginationHttpRequest({ service, method = RopeGeoHttpRequest_1.M
219
262
  return;
220
263
  setData(concatPaginationResultItemsSorted(pagesByNum));
221
264
  setErrors(null);
265
+ setHasCommittedOnce(true);
222
266
  return;
223
267
  }
224
268
  const lastPage = Math.max(1, Math.ceil(totalCount / limit));
@@ -249,6 +293,7 @@ function RopeGeoPaginationHttpRequest({ service, method = RopeGeoHttpRequest_1.M
249
293
  return;
250
294
  setData(concatPaginationResultItemsSorted(pagesByNum));
251
295
  setErrors(null);
296
+ setHasCommittedOnce(true);
252
297
  }
253
298
  catch (err) {
254
299
  if (cancelled || (0, network_1.isAbortError)(err))
@@ -258,6 +303,7 @@ function RopeGeoPaginationHttpRequest({ service, method = RopeGeoHttpRequest_1.M
258
303
  });
259
304
  setErrors(err instanceof Error ? err : new Error(String(err)));
260
305
  setData(null);
306
+ setHasCommittedOnce(false);
261
307
  }
262
308
  finally {
263
309
  clearActivePolicy();
@@ -275,13 +321,16 @@ function RopeGeoPaginationHttpRequest({ service, method = RopeGeoHttpRequest_1.M
275
321
  path,
276
322
  pathParamsKey,
277
323
  queryParamsKey,
278
- queryParams,
279
324
  effectiveBatch,
280
325
  timeoutAfterSeconds,
281
326
  isOnline,
327
+ refreshOnReconnect,
328
+ requestKey,
282
329
  ]);
330
+ const refreshing = loading && hasCommittedOnce;
283
331
  return ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: children({
284
332
  loading,
333
+ refreshing,
285
334
  received,
286
335
  total,
287
336
  data,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ropegeo-common",
3
- "version": "1.12.9",
3
+ "version": "1.12.11",
4
4
  "description": "Shared domain models and helpers for RopeGeo and WebScraper",
5
5
  "license": "ISC",
6
6
  "repository": {