@ainias42/tanstack-ids 0.0.1 → 0.0.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/dist/QueryContext/SubQueriesContext.js +3 -3
- package/dist/QueryContext/SubQueriesContext.js.map +1 -1
- package/dist/QueryContext/useQuerySubscribeToReload.js +4 -3
- package/dist/QueryContext/useQuerySubscribeToReload.js.map +1 -1
- package/dist/generateIdsQuery.d.ts +107 -21
- package/dist/generateIdsQuery.js +56 -22
- package/dist/generateIdsQuery.js.map +1 -1
- package/dist/generateNestedIdQuery.d.ts +105 -19
- package/dist/hooks/formatInitialPage.d.ts +10 -0
- package/dist/hooks/formatInitialPage.js +13 -0
- package/dist/hooks/formatInitialPage.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/QueryContext/SubQueriesContext.tsx +3 -3
- package/src/QueryContext/useQuerySubscribeToReload.ts +4 -3
- package/src/generateIdsQuery.ts +102 -29
- package/src/hooks/formatInitialPage.ts +12 -0
- package/src/index.ts +1 -0
package/src/generateIdsQuery.ts
CHANGED
|
@@ -3,15 +3,15 @@ import { NotFoundError } from '@/NotFoundError';
|
|
|
3
3
|
import { create, windowScheduler } from '@yornaath/batshit';
|
|
4
4
|
import { createInfiniteQuery, createQuery } from 'react-query-kit';
|
|
5
5
|
import { generateQuery } from '@/generateQuery';
|
|
6
|
-
import { hashKey, useQueries } from '@tanstack/react-query';
|
|
6
|
+
import { hashKey, useQueries, useQueryClient } from '@tanstack/react-query';
|
|
7
7
|
import { hoistReactQueryKitAttributes } from '@/hoistReactQueryKitAttributes';
|
|
8
8
|
import { useIndexedData } from '@/hooks/useIndexedData';
|
|
9
9
|
import { useMemo, useRef } from 'react';
|
|
10
10
|
import { useQueriesSubscribeToReload } from '@/QueryContext/useQuerySubscribeToReload';
|
|
11
|
-
import type {
|
|
11
|
+
import type { Awaitable, Override, URecord } from '@ainias42/js-helper';
|
|
12
|
+
import type { CreateInfiniteQueryOptions, CreateQueryOptions, QueryHookOptions } from 'react-query-kit';
|
|
12
13
|
import type { QueriesResults } from '@tanstack/react-query/build/legacy/useQueries';
|
|
13
14
|
import type { QueryClient, QueryFunctionContext, UseQueryOptions, UseQueryResult } from '@tanstack/react-query';
|
|
14
|
-
import type { URecord } from '@ainias42/js-helper';
|
|
15
15
|
|
|
16
16
|
export type Unpacked<T> = T extends (infer U)[] ? U : T;
|
|
17
17
|
|
|
@@ -96,10 +96,15 @@ export function generateIdsQuery<
|
|
|
96
96
|
return returnData.current;
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
-
function useOneHook(identifier: IdType
|
|
100
|
-
|
|
99
|
+
function useOneHook(identifier: IdType, otherAdditionalQueryOptions: Omit<
|
|
100
|
+
QueryHookOptions<Type, unknown, Type, [IdType]>,
|
|
101
|
+
'context' | 'fetcher' | 'queryKey' | 'variables'
|
|
102
|
+
> & { reloadWithContext?: boolean } = {}) {
|
|
103
|
+
const result = useQueryHook({...otherAdditionalQueryOptions, variables: [identifier]});
|
|
104
|
+
|
|
105
|
+
const shouldReload = otherAdditionalQueryOptions.reloadWithContext ?? true;
|
|
101
106
|
useQueriesSubscribeToReload(
|
|
102
|
-
[hashKey(useQueryHook.getKey([identifier as DeepPartial<IdType>]))],
|
|
107
|
+
shouldReload ? [hashKey(useQueryHook.getKey([identifier as DeepPartial<IdType>]))] : [],
|
|
103
108
|
result.isFetching,
|
|
104
109
|
result.error
|
|
105
110
|
);
|
|
@@ -175,26 +180,26 @@ export function generateIdsQuery<
|
|
|
175
180
|
return hoistReactQueryKitAttributes(queryHook, useFilter);
|
|
176
181
|
}
|
|
177
182
|
|
|
178
|
-
function generateInfiniteQuery<PageParams, FuncArguments extends any[]>(
|
|
179
|
-
queryClient: QueryClient,
|
|
183
|
+
function generateInfiniteQuery<PageParams, Meta, FuncArguments extends any[] = []>(
|
|
180
184
|
{
|
|
181
185
|
queryFn,
|
|
182
186
|
...options
|
|
183
187
|
}: Omit<
|
|
184
|
-
CreateInfiniteQueryOptions<IdType[], FuncArguments, Error, PageParams>,
|
|
188
|
+
CreateInfiniteQueryOptions<{ data: IdType[], meta: Meta }, FuncArguments, Error, PageParams>,
|
|
185
189
|
'getNextPageParam' | 'getPreviousPageParam' | 'queryKey' | 'fetcher'
|
|
186
190
|
> & {
|
|
187
191
|
queryFn: (
|
|
188
192
|
pageParams: PageParams,
|
|
189
193
|
args: FuncArguments,
|
|
190
194
|
context: QueryFunctionContext<[string, FuncArguments], PageParams>
|
|
191
|
-
) =>
|
|
195
|
+
) => Awaitable<{ data: Type[], meta: Meta }>;
|
|
192
196
|
getNextPageParam: (options: {
|
|
193
197
|
getLastPage: () => Type[];
|
|
194
198
|
getAllPages: () => Type[][];
|
|
195
199
|
lastPageParam: PageParams;
|
|
196
200
|
allPageParams: PageParams[];
|
|
197
201
|
lastPageLength: number;
|
|
202
|
+
lastPageMeta: Meta;
|
|
198
203
|
}) => PageParams | undefined;
|
|
199
204
|
getPreviousPageParam?: (options: {
|
|
200
205
|
getFirstPage: () => Type[];
|
|
@@ -202,16 +207,35 @@ export function generateIdsQuery<
|
|
|
202
207
|
firstPageParam: PageParams;
|
|
203
208
|
allPageParams: PageParams[];
|
|
204
209
|
firstPageLength: number;
|
|
210
|
+
firstPageMeta: Meta;
|
|
205
211
|
}) => PageParams | undefined;
|
|
206
212
|
}
|
|
207
213
|
) {
|
|
214
|
+
let queryClient: QueryClient | undefined;
|
|
215
|
+
|
|
216
|
+
function getQueryClient() {
|
|
217
|
+
if (!queryClient) {
|
|
218
|
+
throw new Error("QueryClient not set");
|
|
219
|
+
}
|
|
220
|
+
return queryClient;
|
|
221
|
+
}
|
|
222
|
+
|
|
208
223
|
function findEntity(id: IdType) {
|
|
209
|
-
return
|
|
224
|
+
return getQueryClient().getQueryData(useQueryHook.getKey([id as DeepPartial<IdType>])) as Type | undefined;
|
|
210
225
|
}
|
|
211
226
|
|
|
212
227
|
const {getPreviousPageParam} = options;
|
|
213
|
-
const infiniteQueryHook = createInfiniteQuery<
|
|
228
|
+
const infiniteQueryHook = createInfiniteQuery<{
|
|
229
|
+
data: IdType[],
|
|
230
|
+
meta: Meta
|
|
231
|
+
}, FuncArguments, Error, PageParams>({
|
|
214
232
|
...options,
|
|
233
|
+
use: [function myTestMiddleware(useQueryNext) {
|
|
234
|
+
return (options, currentQueryClient) => {
|
|
235
|
+
queryClient = useQueryClient(currentQueryClient);
|
|
236
|
+
return useQueryNext(options, queryClient);
|
|
237
|
+
};
|
|
238
|
+
}],
|
|
215
239
|
queryKey: [`${key}-infinite-query`],
|
|
216
240
|
fetcher: async (_, ctx) => {
|
|
217
241
|
const context = ctx as typeof ctx & { pageParam: PageParams };
|
|
@@ -220,41 +244,90 @@ export function generateIdsQuery<
|
|
|
220
244
|
context.queryKey[1] as FuncArguments,
|
|
221
245
|
context as QueryFunctionContext<[string, FuncArguments], PageParams>
|
|
222
246
|
);
|
|
223
|
-
return
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
247
|
+
return {
|
|
248
|
+
meta: result.meta,
|
|
249
|
+
data: result.data.map(item => {
|
|
250
|
+
getQueryClient().setQueryData(useQueryHook.getKey([item.id as DeepPartial<IdType>]), item);
|
|
251
|
+
return item.id;
|
|
252
|
+
})
|
|
253
|
+
};
|
|
227
254
|
},
|
|
228
|
-
getNextPageParam: (lastPage:
|
|
255
|
+
getNextPageParam: (lastPage: { meta: Meta, data: IdType[] }, allPages: {
|
|
256
|
+
meta: Meta,
|
|
257
|
+
data: IdType[]
|
|
258
|
+
}[], lastPageParam, allPageParams) => {
|
|
229
259
|
return options.getNextPageParam({
|
|
230
|
-
|
|
231
|
-
|
|
260
|
+
lastPageMeta: lastPage.meta,
|
|
261
|
+
getLastPage: () => ArrayHelper.noUndefined(lastPage.data.map(findEntity)),
|
|
262
|
+
getAllPages: () => allPages.map(page => ArrayHelper.noUndefined(page.data.map(findEntity))),
|
|
232
263
|
lastPageParam,
|
|
233
264
|
allPageParams,
|
|
234
|
-
lastPageLength: lastPage.length
|
|
265
|
+
lastPageLength: lastPage.data.length
|
|
235
266
|
});
|
|
236
267
|
},
|
|
237
268
|
getPreviousPageParam: !getPreviousPageParam
|
|
238
269
|
? undefined
|
|
239
270
|
: (firstPage, allPages, firstPageParam, allPageParams) => {
|
|
240
271
|
return getPreviousPageParam({
|
|
241
|
-
|
|
242
|
-
|
|
272
|
+
firstPageMeta: firstPage.meta,
|
|
273
|
+
getFirstPage: () => ArrayHelper.noUndefined(firstPage.data.map(findEntity)),
|
|
274
|
+
getAllPages: () => allPages.map(page => ArrayHelper.noUndefined(page.data.map(findEntity))),
|
|
243
275
|
firstPageParam,
|
|
244
276
|
allPageParams,
|
|
245
|
-
firstPageLength: firstPage.length
|
|
277
|
+
firstPageLength: firstPage.data.length
|
|
246
278
|
});
|
|
247
279
|
}
|
|
248
280
|
});
|
|
249
281
|
|
|
250
|
-
|
|
251
|
-
|
|
282
|
+
|
|
283
|
+
type HookOptions = Override<Parameters<typeof infiniteQueryHook>[0] & {
|
|
284
|
+
select?: undefined,
|
|
285
|
+
}, {
|
|
286
|
+
initialData?: {
|
|
287
|
+
pages: { data: Type[], meta: Meta }[],
|
|
288
|
+
pageParams: PageParams[]
|
|
289
|
+
}
|
|
290
|
+
}>;
|
|
291
|
+
|
|
292
|
+
type InfiniteQueryArgs = FuncArguments extends ({
|
|
293
|
+
length: 0
|
|
294
|
+
} | symbol | undefined) ? ([HookOptions] | []) : ([HookOptions]);
|
|
295
|
+
|
|
296
|
+
function useInfiniteQuery(...args: InfiniteQueryArgs) {
|
|
297
|
+
const infiniteQueryClient = useQueryClient();
|
|
298
|
+
|
|
299
|
+
let infiniteOptions: Parameters<typeof infiniteQueryHook>[0] & {
|
|
300
|
+
select?: undefined,
|
|
301
|
+
};
|
|
302
|
+
if (args.length === 1 && "initialData" in args[0] && args[0].initialData) {
|
|
303
|
+
const {initialData} = args[0];
|
|
304
|
+
infiniteOptions = {
|
|
305
|
+
...args[0],
|
|
306
|
+
initialData: {
|
|
307
|
+
pages: initialData.pages.map(page => ({
|
|
308
|
+
...page,
|
|
309
|
+
data: page.data.map(item => {
|
|
310
|
+
infiniteQueryClient.setQueryData(useQueryHook.getKey([item.id as DeepPartial<IdType>]), item);
|
|
311
|
+
return item.id;
|
|
312
|
+
})
|
|
313
|
+
})),
|
|
314
|
+
pageParams: initialData.pageParams
|
|
315
|
+
}
|
|
316
|
+
} as Parameters<typeof infiniteQueryHook>[0] & {
|
|
317
|
+
select?: undefined,
|
|
318
|
+
};
|
|
319
|
+
} else {
|
|
320
|
+
infiniteOptions = args[0] as Parameters<typeof infiniteQueryHook>[0] & {
|
|
321
|
+
select?: undefined,
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
const result = infiniteQueryHook(infiniteOptions);
|
|
252
325
|
useQueriesSubscribeToReload(
|
|
253
|
-
[hashKey(infiniteQueryHook.getKey(
|
|
326
|
+
[hashKey(infiniteQueryHook.getKey(infiniteOptions.variables as Parameters<(typeof infiniteQueryHook)['getKey']>[0]))],
|
|
254
327
|
result.isFetching,
|
|
255
328
|
result.error
|
|
256
329
|
);
|
|
257
|
-
const ids = useMemo(() => result.data?.pages.
|
|
330
|
+
const ids = useMemo(() => result.data?.pages.flatMap(page => page.data) ?? [], [result.data?.pages]);
|
|
258
331
|
|
|
259
332
|
// When staleTime is same as filterStaleTime, then the queries will run at the same time as the filter
|
|
260
333
|
// Because of this, use staleTime: Inifinity to prevent the queries from running again. The result of the
|
|
@@ -266,7 +339,7 @@ export function generateIdsQuery<
|
|
|
266
339
|
|
|
267
340
|
const pages = useMemo(() => {
|
|
268
341
|
return result.data
|
|
269
|
-
? result.data.pages.map(page => ArrayHelper.noUndefined(page.map(id => indexedData[id])))
|
|
342
|
+
? result.data.pages.map(page => ArrayHelper.noUndefined(page.data.map(id => indexedData[id])))
|
|
270
343
|
: [];
|
|
271
344
|
}, [indexedData, result.data]);
|
|
272
345
|
|
|
@@ -276,7 +349,7 @@ export function generateIdsQuery<
|
|
|
276
349
|
};
|
|
277
350
|
}
|
|
278
351
|
|
|
279
|
-
// @ts-expect-error type
|
|
352
|
+
// @ts-expect-error wrong type in tanstack-query
|
|
280
353
|
return hoistReactQueryKitAttributes(infiniteQueryHook, useInfiniteQuery);
|
|
281
354
|
}
|
|
282
355
|
|
package/src/index.ts
CHANGED
|
@@ -4,6 +4,7 @@ export * from './generateQuery';
|
|
|
4
4
|
export * from './hoistReactQueryKitAttributes';
|
|
5
5
|
export * from './noop';
|
|
6
6
|
export * from './NotFoundError';
|
|
7
|
+
export * from './hooks/formatInitialPage';
|
|
7
8
|
export * from './hooks/useArrayData';
|
|
8
9
|
export * from './hooks/useIndexedData';
|
|
9
10
|
export * from './QueryContext/QueriesContext';
|