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` (object or filesystem path + `readOfflineFile`), 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'` |
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
- * Inline offline payload or filesystem path. When an object, it is used as `data` immediately
35
- * (no network, no file read). When a string, `readOfflineFile` is invoked; on failure the error
36
- * `Could not read file at {path}` is set and the loader falls back to {@link onlinePath} when online.
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 | string;
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, readOfflineFile, children, }: RopeGeoDataLoaderProps<T>): import("react/jsx-runtime").JSX.Element;
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;;;;OAIG;IACH,WAAW,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC;IACzB;;OAEG;IACH,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACpD,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,eAAe,EACf,QAAQ,GACT,EAAE,sBAAsB,CAAC,CAAC,CAAC,2CA+X3B"}
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 (typeof offlineData === "string")
61
- return `|file:${offlineData}`;
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, readOfflineFile, children, }) {
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
- /** Inline object offlineData immediate, no network. */
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 == null || typeof offlineData !== "object") {
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
- /** Inline object: dedicated effect owns `data`; never hit the network here. */
182
- if (offlineData != null && typeof offlineData === "object") {
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
  ]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ropegeo-common",
3
- "version": "1.16.0",
3
+ "version": "1.16.2",
4
4
  "description": "Shared domain models and helpers for RopeGeo and WebScraper",
5
5
  "license": "ISC",
6
6
  "repository": {