ropegeo-common 1.16.0 → 1.16.2
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
|
@@ -326,7 +326,7 @@ Legend entries for page minimaps are keyed objects (`legend` on `PageMiniMap`);
|
|
|
326
326
|
|
|
327
327
|
| Name | Description | Import |
|
|
328
328
|
| --- | --- | --- |
|
|
329
|
-
| `RopeGeoDataLoader` | Single-request loader: `onlinePath` / `onlinePathParams`, optional `offlineData` (
|
|
329
|
+
| `RopeGeoDataLoader` | Single-request loader: `onlinePath` / `onlinePathParams`, optional `offlineData` (`undefined` → fetch online; `null` → `data` null / loading-style, no fetch; `T` → use as `data`, no fetch), optional `timeoutAfterSeconds` and `isOnline`. Children receive `data`, `errors`, `timeoutCountdown` (numeric only while an online fetch is in flight, otherwise `null`), and `reload`. Reconnect refetch uses `dirtyWhileOffline` driven by a semantic key (no `refreshOnReconnect` prop). Also exports `Method`, `Service`, `SERVICE_BASE_URL`. | `import { RopeGeoDataLoader, Method, Service } from 'ropegeo-common/components'` |
|
|
330
330
|
| `RopeGeoPagedDataLoader` | Cursor-paginated list: same networking props as above; children get `loadNextPage`, `loadingNextPage`, `morePages`, plus `data`, `errors`, `timeoutCountdown`, `reload`. | `import { RopeGeoPagedDataLoader } from 'ropegeo-common/components'` |
|
|
331
331
|
| `RopeGeoProgressDataLoader` | Page-based “progress” fetch: batches additional pages until `total` is satisfied; children get `received`, `total`, `data`, `errors`, `timeoutCountdown`, `reload`. | `import { RopeGeoProgressDataLoader } from 'ropegeo-common/components'` |
|
|
332
332
|
|
|
@@ -31,15 +31,12 @@ export type RopeGeoDataLoaderProps<T = unknown> = {
|
|
|
31
31
|
*/
|
|
32
32
|
isOnline?: boolean;
|
|
33
33
|
/**
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
34
|
+
* Offline / local-first behavior without reading files inside the loader:
|
|
35
|
+
* - **`undefined`**: omit or leave unset — fetch from {@link onlinePath} as usual.
|
|
36
|
+
* - **`null`**: do not fetch; children receive `data: null` and `errors: null` (loading-style).
|
|
37
|
+
* - **`T`**: use as `data` immediately; no network.
|
|
37
38
|
*/
|
|
38
|
-
offlineData?: T |
|
|
39
|
-
/**
|
|
40
|
-
* Required when `offlineData` is a string. Reads file contents as UTF-8 text for JSON parsing.
|
|
41
|
-
*/
|
|
42
|
-
readOfflineFile?: (path: string) => Promise<string>;
|
|
39
|
+
offlineData?: T | null;
|
|
43
40
|
children: (args: {
|
|
44
41
|
data: T | null;
|
|
45
42
|
errors: Error | null;
|
|
@@ -52,5 +49,5 @@ export type RopeGeoDataLoaderProps<T = unknown> = {
|
|
|
52
49
|
reload: () => void;
|
|
53
50
|
}) => ReactNode;
|
|
54
51
|
};
|
|
55
|
-
export declare function RopeGeoDataLoader<T = unknown>({ service, method, onlinePath, onlinePathParams, queryParams, body, timeoutAfterSeconds, isOnline, offlineData,
|
|
52
|
+
export declare function RopeGeoDataLoader<T = unknown>({ service, method, onlinePath, onlinePathParams, queryParams, body, timeoutAfterSeconds, isOnline, offlineData, children, }: RopeGeoDataLoaderProps<T>): import("react/jsx-runtime").JSX.Element;
|
|
56
53
|
//# sourceMappingURL=RopeGeoDataLoader.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RopeGeoDataLoader.d.ts","sourceRoot":"","sources":["../../src/components/RopeGeoDataLoader.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;AAqEF,MAAM,MAAM,sBAAsB,CAAC,CAAC,GAAG,OAAO,IAAI;IAChD,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,0FAA0F;IAC1F,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1C,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC,CAAC;IACpE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB
|
|
1
|
+
{"version":3,"file":"RopeGeoDataLoader.d.ts","sourceRoot":"","sources":["../../src/components/RopeGeoDataLoader.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;AAqEF,MAAM,MAAM,sBAAsB,CAAC,CAAC,GAAG,OAAO,IAAI;IAChD,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,0FAA0F;IAC1F,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1C,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC,CAAC;IACpE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC;IACvB,QAAQ,EAAE,CAAC,IAAI,EAAE;QACf,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC;QACf,MAAM,EAAE,KAAK,GAAG,IAAI,CAAC;QACrB;;;WAGG;QACH,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;QAChC,iFAAiF;QACjF,MAAM,EAAE,MAAM,IAAI,CAAC;KACpB,KAAK,SAAS,CAAC;CACjB,CAAC;AAEF,wBAAgB,iBAAiB,CAAC,CAAC,GAAG,OAAO,EAAE,EAC7C,OAAO,EACP,MAAM,EACN,UAAU,EACV,gBAAgB,EAChB,WAAW,EACX,IAAI,EACJ,mBAAmB,EACnB,QAAQ,EACR,WAAW,EACX,QAAQ,GACT,EAAE,sBAAsB,CAAC,CAAC,CAAC,2CAgU3B"}
|
|
@@ -57,18 +57,16 @@ function dataLoaderReconnectSemanticKey(service, method, onlinePath, pathParamsK
|
|
|
57
57
|
function offlineDataKeyPart(offlineData) {
|
|
58
58
|
if (offlineData === undefined)
|
|
59
59
|
return "";
|
|
60
|
-
if (
|
|
61
|
-
return
|
|
60
|
+
if (offlineData === null)
|
|
61
|
+
return "|offline:null";
|
|
62
62
|
return `|obj:${JSON.stringify(offlineData)}`;
|
|
63
63
|
}
|
|
64
|
-
function RopeGeoDataLoader({ service, method, onlinePath, onlinePathParams, queryParams, body, timeoutAfterSeconds, isOnline, offlineData,
|
|
64
|
+
function RopeGeoDataLoader({ service, method, onlinePath, onlinePathParams, queryParams, body, timeoutAfterSeconds, isOnline, offlineData, children, }) {
|
|
65
65
|
const [data, setData] = (0, react_1.useState)(null);
|
|
66
66
|
const [errors, setErrors] = (0, react_1.useState)(null);
|
|
67
67
|
const [timeoutCountdown, setTimeoutCountdown] = (0, react_1.useState)(null);
|
|
68
68
|
const [reloadTick, setReloadTick] = (0, react_1.useState)(0);
|
|
69
69
|
const pendingReloadRef = (0, react_1.useRef)(false);
|
|
70
|
-
/** `null` = not using file path, `'pending'`, `'ok'`, `'failed'` */
|
|
71
|
-
const [offlineFileStatus, setOfflineFileStatus] = (0, react_1.useState)(null);
|
|
72
70
|
const errorsRef = (0, react_1.useRef)(errors);
|
|
73
71
|
const hasCommittedRef = (0, react_1.useRef)(false);
|
|
74
72
|
errorsRef.current = errors;
|
|
@@ -108,61 +106,25 @@ function RopeGeoDataLoader({ service, method, onlinePath, onlinePathParams, quer
|
|
|
108
106
|
setReloadTick((n) => n + 1);
|
|
109
107
|
}, [isOnline]);
|
|
110
108
|
const lastRequestKeyRef = (0, react_1.useRef)("");
|
|
111
|
-
/**
|
|
109
|
+
/** Sync `data` from {@link offlineData} when it is `null` or `T`; `undefined` defers to the network effect. */
|
|
112
110
|
(0, react_1.useEffect)(() => {
|
|
113
|
-
if (offlineData
|
|
111
|
+
if (offlineData === undefined) {
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
if (offlineData === null) {
|
|
115
|
+
setData(null);
|
|
116
|
+
setErrors(null);
|
|
117
|
+
hasCommittedRef.current = false;
|
|
118
|
+
dirtyWhileOfflineRef.current = false;
|
|
119
|
+
semanticSnapshotRef.current = null;
|
|
114
120
|
return;
|
|
115
121
|
}
|
|
116
|
-
setOfflineFileStatus(null);
|
|
117
122
|
setData(offlineData);
|
|
118
123
|
setErrors(null);
|
|
119
124
|
hasCommittedRef.current = true;
|
|
120
125
|
dirtyWhileOfflineRef.current = false;
|
|
121
126
|
semanticSnapshotRef.current = null;
|
|
122
127
|
}, [offlineData]);
|
|
123
|
-
/** String path: read file, then maybe fall back to online. */
|
|
124
|
-
(0, react_1.useEffect)(() => {
|
|
125
|
-
if (typeof offlineData !== "string") {
|
|
126
|
-
setOfflineFileStatus(null);
|
|
127
|
-
return;
|
|
128
|
-
}
|
|
129
|
-
let cancelled = false;
|
|
130
|
-
setOfflineFileStatus("pending");
|
|
131
|
-
setData(null);
|
|
132
|
-
setErrors(null);
|
|
133
|
-
hasCommittedRef.current = false;
|
|
134
|
-
if (readOfflineFile == null) {
|
|
135
|
-
setErrors(new Error("readOfflineFile is required when offlineData is a filesystem path"));
|
|
136
|
-
setOfflineFileStatus("failed");
|
|
137
|
-
return;
|
|
138
|
-
}
|
|
139
|
-
void (async () => {
|
|
140
|
-
try {
|
|
141
|
-
const text = await readOfflineFile(offlineData);
|
|
142
|
-
const raw = JSON.parse(text);
|
|
143
|
-
const parsed = models_1.Result.fromResponseBody(raw);
|
|
144
|
-
if (!cancelled) {
|
|
145
|
-
setData(parsed.result);
|
|
146
|
-
setErrors(null);
|
|
147
|
-
hasCommittedRef.current = true;
|
|
148
|
-
setOfflineFileStatus("ok");
|
|
149
|
-
dirtyWhileOfflineRef.current = false;
|
|
150
|
-
semanticSnapshotRef.current = null;
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
catch {
|
|
154
|
-
if (!cancelled) {
|
|
155
|
-
setErrors(new Error(`Could not read file at ${offlineData}`));
|
|
156
|
-
setData(null);
|
|
157
|
-
hasCommittedRef.current = false;
|
|
158
|
-
setOfflineFileStatus("failed");
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
})();
|
|
162
|
-
return () => {
|
|
163
|
-
cancelled = true;
|
|
164
|
-
};
|
|
165
|
-
}, [offlineData, readOfflineFile]);
|
|
166
128
|
(0, react_1.useEffect)(() => {
|
|
167
129
|
const online = isOnline !== false;
|
|
168
130
|
const prevOnline = prevIsOnlineRef.current;
|
|
@@ -178,19 +140,8 @@ function RopeGeoDataLoader({ service, method, onlinePath, onlinePathParams, quer
|
|
|
178
140
|
dirtyWhileOfflineRef.current = true;
|
|
179
141
|
}
|
|
180
142
|
}
|
|
181
|
-
/**
|
|
182
|
-
if (offlineData
|
|
183
|
-
prevIsOnlineRef.current = online;
|
|
184
|
-
return;
|
|
185
|
-
}
|
|
186
|
-
/** File path: wait for read outcome; `ok` keeps local data; only `failed` falls through to online fetch. */
|
|
187
|
-
if (typeof offlineData === "string" && offlineFileStatus === "ok") {
|
|
188
|
-
prevIsOnlineRef.current = online;
|
|
189
|
-
return;
|
|
190
|
-
}
|
|
191
|
-
if (typeof offlineData === "string" &&
|
|
192
|
-
offlineFileStatus !== "failed" &&
|
|
193
|
-
offlineFileStatus !== "ok") {
|
|
143
|
+
/** `offlineData` is `null` or `T`: own `data`; never hit the network here. */
|
|
144
|
+
if (offlineData !== undefined) {
|
|
194
145
|
prevIsOnlineRef.current = online;
|
|
195
146
|
return;
|
|
196
147
|
}
|
|
@@ -366,7 +317,6 @@ function RopeGeoDataLoader({ service, method, onlinePath, onlinePathParams, quer
|
|
|
366
317
|
requestKey,
|
|
367
318
|
reloadTick,
|
|
368
319
|
offlineData,
|
|
369
|
-
offlineFileStatus,
|
|
370
320
|
reconnectSemanticKey,
|
|
371
321
|
queryParams,
|
|
372
322
|
]);
|