@robohall/react-query-factory 2.1.0 → 2.1.1

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
@@ -9,7 +9,7 @@
9
9
  <a href="https://roberth26.github.io/react-query-factory/"><strong>Visit the Sandbox</strong></a>
10
10
  </p>
11
11
 
12
- TanStack Query handles caching, syncing, and invalidation. What it doesn't do is crawl paginated APIs for you. This library adds that — a factory function that wraps your `queryFn` with a configurable crawl loop so `useQuery` can return accumulated results instead of a single page. The same factory produces `useInfiniteQuery` options, composes into child factories that share the cache, and exposes scope-aware invalidation keys. TanStack's API stays fully exposed at every call site.
12
+ TanStack Query handles caching, syncing, and invalidation. What it doesn't do is crawl paginated APIs for you. This library adds that — a factory function that wraps your `queryFn` with a configurable crawl loop so `useQuery` can return accumulated results instead of a single page. The `queryFn` can be a plain async function or an async iterable (e.g. an AWS SDK paginator), with no cursor wiring required in the latter case. The same factory produces `useInfiniteQuery` options, composes into child factories that share the cache, and exposes scope-aware invalidation keys. TanStack's API stays fully exposed at every call site.
13
13
 
14
14
  Zero runtime dependencies.
15
15
 
@@ -30,7 +30,30 @@ function useInstances(params: DescribeInstancesCommandInput) {
30
30
  }
31
31
  ```
32
32
 
33
- Works, but the key only exists inside the hook. Prefetching in a route loader, invalidating after a mutation, or fetching imperatively all require knowing `['instances', params]` without calling the hook.
33
+ Works, until requirements grow. You need a `select` option — so the hook grows a generic. You need a `useInfiniteQuery` variant so you write a second hook with a key differentiator to avoid a cache collision. You need to prefetch in a route loader — but the key is trapped inside the hook.
34
+
35
+ ```typescript
36
+ function useInstances<TSelected = Instance[]>(
37
+ params: DescribeInstancesCommandInput,
38
+ options?: { select?: (data: Instance[]) => TSelected },
39
+ ) {
40
+ return useQuery({
41
+ queryKey: ['instances', params],
42
+ queryFn: () => fetchInstances(params),
43
+ select: options?.select,
44
+ });
45
+ }
46
+
47
+ // separate hook, duplicated key and queryFn, must stay in sync manually
48
+ function useInstancesInfinite(params: DescribeInstancesCommandInput) {
49
+ return useInfiniteQuery({
50
+ queryKey: ['instances', 'infinite', params],
51
+ // ...
52
+ });
53
+ }
54
+ ```
55
+
56
+ The generics multiply with every new transform. The key is still trapped — prefetching and invalidation still can't reach it from outside.
34
57
 
35
58
  ### Step 2 — `queryOptions` for colocation
36
59
 
@@ -126,7 +149,7 @@ Now you have two separate factories that duplicate the key and queryFn and need
126
149
  ### What's missing
127
150
 
128
151
  - Define the query **once**: key, queryFn, pagination config
129
- - Let each **call site** decide how much to crawl (e.g. 50 records or all of them)
152
+ - Let each **call site** decide how much to crawl (e.g. 50 records, all of them, or none)
130
153
  - Optionally have `useQuery` crawl and return the **accumulated result** instead of a single page
131
154
  - Use **async iterables** as `queryFn` — pass a paginator function directly, no cursor wiring required
132
155
  - Have `.infinite()` available on the **same factory**, no duplication
package/dist/index.js CHANGED
@@ -122,13 +122,16 @@ function buildInfiniteCrawlingQueryFn(queryFn, getNextPageParam, shouldFetchNext
122
122
  const initialResult = queryFn(params, ctx);
123
123
  if (isAsyncIterable(initialResult)) {
124
124
  const pages2 = [];
125
+ const startParam = context.pageParam;
125
126
  let acc2 = void 0;
126
127
  let nextBatchParam2 = null;
127
128
  for await (const page of initialResult) {
128
129
  if ((_b = context.signal) == null ? void 0 : _b.aborted) break;
129
130
  pages2.push(page);
130
131
  acc2 = reduce(acc2, page);
131
- const nextParam = getNextPageParam(page, pages2, void 0, []);
132
+ const nextParam = getNextPageParam(page, pages2, startParam, [
133
+ startParam
134
+ ]);
132
135
  nextBatchParam2 = nextParam != null ? nextParam : null;
133
136
  if (nextParam == null) break;
134
137
  if (!shouldFetchNextPage(acc2, crawlOptions)) break;
@@ -147,9 +150,9 @@ function buildInfiniteCrawlingQueryFn(queryFn, getNextPageParam, shouldFetchNext
147
150
  pages.push(page);
148
151
  pageParams.push(currentParam);
149
152
  acc = reduce(acc, page);
150
- if ((_c = context.signal) == null ? void 0 : _c.aborted) break;
151
153
  const nextParam = getNextPageParam(page, pages, currentParam, pageParams);
152
154
  nextBatchParam = nextParam != null ? nextParam : null;
155
+ if ((_c = context.signal) == null ? void 0 : _c.aborted) break;
153
156
  if (nextParam == null) break;
154
157
  if (!shouldFetchNextPage(acc, crawlOptions)) break;
155
158
  currentParam = nextParam;
@@ -279,7 +282,7 @@ function queryFactory(configOrParent, childConfig) {
279
282
  } : {
280
283
  getNextPageParam: (_b = childConfig.getNextPageParam) != null ? _b : parentCfg.getNextPageParam,
281
284
  getPreviousPageParam: (_c = childConfig.getPreviousPageParam) != null ? _c : parentCfg.getPreviousPageParam,
282
- initialPageParam: childConfig.initialPageParam !== void 0 ? childConfig.initialPageParam : parentCfg.initialPageParam,
285
+ initialPageParam: "initialPageParam" in childConfig ? childConfig.initialPageParam : parentCfg.initialPageParam,
283
286
  shouldFetchNextPage: (_d = childConfig.shouldFetchNextPage) != null ? _d : parentCfg.shouldFetchNextPage,
284
287
  reduce: (_e = childConfig.reduce) != null ? _e : parentCfg.reduce
285
288
  };
package/dist/index.mjs CHANGED
@@ -96,13 +96,16 @@ function buildInfiniteCrawlingQueryFn(queryFn, getNextPageParam, shouldFetchNext
96
96
  const initialResult = queryFn(params, ctx);
97
97
  if (isAsyncIterable(initialResult)) {
98
98
  const pages2 = [];
99
+ const startParam = context.pageParam;
99
100
  let acc2 = void 0;
100
101
  let nextBatchParam2 = null;
101
102
  for await (const page of initialResult) {
102
103
  if ((_b = context.signal) == null ? void 0 : _b.aborted) break;
103
104
  pages2.push(page);
104
105
  acc2 = reduce(acc2, page);
105
- const nextParam = getNextPageParam(page, pages2, void 0, []);
106
+ const nextParam = getNextPageParam(page, pages2, startParam, [
107
+ startParam
108
+ ]);
106
109
  nextBatchParam2 = nextParam != null ? nextParam : null;
107
110
  if (nextParam == null) break;
108
111
  if (!shouldFetchNextPage(acc2, crawlOptions)) break;
@@ -121,9 +124,9 @@ function buildInfiniteCrawlingQueryFn(queryFn, getNextPageParam, shouldFetchNext
121
124
  pages.push(page);
122
125
  pageParams.push(currentParam);
123
126
  acc = reduce(acc, page);
124
- if ((_c = context.signal) == null ? void 0 : _c.aborted) break;
125
127
  const nextParam = getNextPageParam(page, pages, currentParam, pageParams);
126
128
  nextBatchParam = nextParam != null ? nextParam : null;
129
+ if ((_c = context.signal) == null ? void 0 : _c.aborted) break;
127
130
  if (nextParam == null) break;
128
131
  if (!shouldFetchNextPage(acc, crawlOptions)) break;
129
132
  currentParam = nextParam;
@@ -253,7 +256,7 @@ function queryFactory(configOrParent, childConfig) {
253
256
  } : {
254
257
  getNextPageParam: (_b = childConfig.getNextPageParam) != null ? _b : parentCfg.getNextPageParam,
255
258
  getPreviousPageParam: (_c = childConfig.getPreviousPageParam) != null ? _c : parentCfg.getPreviousPageParam,
256
- initialPageParam: childConfig.initialPageParam !== void 0 ? childConfig.initialPageParam : parentCfg.initialPageParam,
259
+ initialPageParam: "initialPageParam" in childConfig ? childConfig.initialPageParam : parentCfg.initialPageParam,
257
260
  shouldFetchNextPage: (_d = childConfig.shouldFetchNextPage) != null ? _d : parentCfg.shouldFetchNextPage,
258
261
  reduce: (_e = childConfig.reduce) != null ? _e : parentCfg.reduce
259
262
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@robohall/react-query-factory",
3
- "version": "2.1.0",
3
+ "version": "2.1.1",
4
4
  "description": "A factory abstraction for TanStack Query (React Query) with composable keys, crawling support, and automatic infinite query generation",
5
5
  "author": "Robert Hall",
6
6
  "license": "MIT",