@ainias42/tanstack-ids 0.0.2 → 0.0.4
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/.prettierrc +1 -1
- package/dist/QueryContext/QueriesContextProvider.d.ts +1 -1
- package/dist/QueryContext/QueriesContextProvider.js +1 -1
- package/dist/QueryContext/QueriesContextProvider.js.map +1 -1
- package/dist/QueryContext/SubQueriesContext.d.ts +1 -1
- package/dist/QueryContext/SubQueriesContext.js +2 -2
- package/dist/QueryContext/SubQueriesContext.js.map +1 -1
- package/dist/QueryContext/useGenerateQueriesContextId.js +1 -1
- package/dist/QueryContext/useGenerateQueriesContextId.js.map +1 -1
- package/dist/QueryContext/useQueriesError.js +1 -1
- package/dist/QueryContext/useQueriesError.js.map +1 -1
- package/dist/QueryContext/useQueriesIsFetching.js +1 -1
- package/dist/QueryContext/useQueriesIsFetching.js.map +1 -1
- package/dist/QueryContext/useQueriesReload.js +1 -1
- package/dist/QueryContext/useQueriesReload.js.map +1 -1
- package/dist/QueryContext/useQueriesStore.d.ts +2 -1
- package/dist/QueryContext/useQueriesStore.js +17 -17
- package/dist/QueryContext/useQueriesStore.js.map +1 -1
- package/dist/QueryContext/useQuerySubscribeToReload.js +5 -5
- package/dist/QueryContext/useQuerySubscribeToReload.js.map +1 -1
- package/dist/QueryContext/useScopedQueriesIsFetching.js +1 -1
- package/dist/QueryContext/useScopedQueriesIsFetching.js.map +1 -1
- package/dist/generateIdsQuery.d.ts +82 -7
- package/dist/generateIdsQuery.js +51 -32
- package/dist/generateIdsQuery.js.map +1 -1
- package/dist/generateNestedIdQuery.d.ts +83 -9
- package/dist/generateNestedIdQuery.js +2 -2
- package/dist/generateNestedIdQuery.js.map +1 -1
- package/dist/generateQuery.js +1 -1
- package/dist/generateQuery.js.map +1 -1
- package/dist/hooks/formatInitialPage.js +1 -1
- package/dist/hooks/useArrayData.js +1 -1
- package/dist/hooks/useArrayData.js.map +1 -1
- package/dist/noop.js +0 -1
- package/dist/noop.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/eslint.config.js +3 -0
- package/package.json +12 -8
- package/src/QueryContext/QueriesContextProvider.tsx +2 -2
- package/src/QueryContext/SubQueriesContext.tsx +4 -4
- package/src/QueryContext/useGenerateQueriesContextId.ts +1 -1
- package/src/QueryContext/useQueriesError.ts +1 -1
- package/src/QueryContext/useQueriesIsFetching.ts +1 -1
- package/src/QueryContext/useQueriesReload.ts +1 -1
- package/src/QueryContext/useQueriesStore.ts +21 -21
- package/src/QueryContext/useQuerySubscribeToReload.ts +5 -5
- package/src/QueryContext/useScopedQueriesIsFetching.ts +1 -1
- package/src/generateIdsQuery.ts +172 -127
- package/src/generateNestedIdQuery.ts +6 -6
- package/src/generateQuery.ts +12 -13
- package/src/hoistReactQueryKitAttributes.ts +1 -1
- package/src/hooks/formatInitialPage.ts +1 -1
- package/src/hooks/useArrayData.ts +3 -3
- package/src/hooks/useIndexedData.ts +3 -3
- package/src/noop.ts +0 -1
- package/tsconfig.json +3 -12
- package/.eslintrc.cjs +0 -3
package/src/generateIdsQuery.ts
CHANGED
|
@@ -17,25 +17,25 @@ export type Unpacked<T> = T extends (infer U)[] ? U : T;
|
|
|
17
17
|
|
|
18
18
|
type DeepPartial<T> = T extends object
|
|
19
19
|
? {
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
[P in keyof T]?: DeepPartial<T[P]>;
|
|
21
|
+
}
|
|
22
22
|
: T;
|
|
23
23
|
|
|
24
24
|
export function generateIdsQuery<
|
|
25
25
|
IdType extends number | string | symbol,
|
|
26
26
|
Type extends {
|
|
27
27
|
id: IdType;
|
|
28
|
-
}
|
|
28
|
+
},
|
|
29
29
|
>(
|
|
30
30
|
key: string,
|
|
31
31
|
fetcher: (ids: IdType[]) => Promise<Type[]> | Type[],
|
|
32
32
|
additionalQueryOptions?: Omit<CreateQueryOptions<Type, [IdType]>, 'queryKey' | 'fetcher'> & {
|
|
33
33
|
schedulerTime?: number;
|
|
34
|
-
}
|
|
34
|
+
},
|
|
35
35
|
) {
|
|
36
36
|
const batch = create<URecord<IdType, Type>[], IdType, Type>({
|
|
37
|
-
fetcher: async ids => {
|
|
38
|
-
return [ArrayHelper.arrayToObject(await fetcher(ids), value => value.id)];
|
|
37
|
+
fetcher: async (ids) => {
|
|
38
|
+
return [ArrayHelper.arrayToObject(await fetcher(ids), (value) => value.id)];
|
|
39
39
|
},
|
|
40
40
|
resolver: ([items], id) => {
|
|
41
41
|
const item = items?.[id];
|
|
@@ -44,13 +44,13 @@ export function generateIdsQuery<
|
|
|
44
44
|
}
|
|
45
45
|
return item;
|
|
46
46
|
},
|
|
47
|
-
scheduler: windowScheduler(additionalQueryOptions?.schedulerTime ?? 15)
|
|
47
|
+
scheduler: windowScheduler(additionalQueryOptions?.schedulerTime ?? 15),
|
|
48
48
|
});
|
|
49
49
|
|
|
50
50
|
const useQueryHook = createQuery<Type, [IdType]>({
|
|
51
51
|
queryKey: [key],
|
|
52
|
-
fetcher: identifier => batch.fetch(identifier[0]),
|
|
53
|
-
...additionalQueryOptions
|
|
52
|
+
fetcher: (identifier) => batch.fetch(identifier[0]),
|
|
53
|
+
...additionalQueryOptions,
|
|
54
54
|
});
|
|
55
55
|
|
|
56
56
|
function useManyHook(
|
|
@@ -58,16 +58,16 @@ export function generateIdsQuery<
|
|
|
58
58
|
otherAdditionalQueryOptions: Omit<
|
|
59
59
|
UseQueryOptions<Type, unknown, Type, [string, [IdType]]>,
|
|
60
60
|
'context' | 'fetcher' | 'queryKey'
|
|
61
|
-
> & { reloadWithContext?: boolean } = {}
|
|
61
|
+
> & { reloadWithContext?: boolean } = {},
|
|
62
62
|
) {
|
|
63
|
-
const queries = ids.map(id => ({
|
|
63
|
+
const queries = ids.map((id) => ({
|
|
64
64
|
...useQueryHook.getOptions([id]),
|
|
65
|
-
...otherAdditionalQueryOptions
|
|
65
|
+
...otherAdditionalQueryOptions,
|
|
66
66
|
}));
|
|
67
67
|
|
|
68
68
|
const results = useQueries<Type[], QueriesResults<Type[]>>({
|
|
69
69
|
// @ts-expect-error wrong type in tanstack-query
|
|
70
|
-
queries
|
|
70
|
+
queries,
|
|
71
71
|
}) as UseQueryResult<Type, Error>[];
|
|
72
72
|
|
|
73
73
|
const oldData = useRef<typeof results>([]);
|
|
@@ -84,29 +84,32 @@ export function generateIdsQuery<
|
|
|
84
84
|
}
|
|
85
85
|
|
|
86
86
|
const shouldReload = otherAdditionalQueryOptions.reloadWithContext ?? true;
|
|
87
|
-
const keys = shouldReload ? ids.map(id => hashKey(useQueryHook.getKey([id as DeepPartial<IdType>]))) : [];
|
|
87
|
+
const keys = shouldReload ? ids.map((id) => hashKey(useQueryHook.getKey([id as DeepPartial<IdType>]))) : [];
|
|
88
88
|
|
|
89
89
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
90
|
-
const isFetching = useMemo(() => oldData.current.some(item => item.isFetching), [oldData.current]);
|
|
90
|
+
const isFetching = useMemo(() => oldData.current.some((item) => item.isFetching), [oldData.current]);
|
|
91
91
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
92
|
-
const error = useMemo(() => oldData.current.find(item => item.error)?.error, [oldData.current]);
|
|
92
|
+
const error = useMemo(() => oldData.current.find((item) => item.error)?.error, [oldData.current]);
|
|
93
93
|
|
|
94
94
|
useQueriesSubscribeToReload(keys, isFetching, error);
|
|
95
95
|
|
|
96
96
|
return returnData.current;
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
-
function useOneHook(
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
99
|
+
function useOneHook(
|
|
100
|
+
identifier: IdType,
|
|
101
|
+
otherAdditionalQueryOptions: Omit<
|
|
102
|
+
QueryHookOptions<Type, unknown, Type, [IdType]>,
|
|
103
|
+
'context' | 'fetcher' | 'queryKey' | 'variables'
|
|
104
|
+
> & { reloadWithContext?: boolean } = {},
|
|
105
|
+
) {
|
|
106
|
+
const result = useQueryHook({ ...otherAdditionalQueryOptions, variables: [identifier] });
|
|
104
107
|
|
|
105
108
|
const shouldReload = otherAdditionalQueryOptions.reloadWithContext ?? true;
|
|
106
109
|
useQueriesSubscribeToReload(
|
|
107
110
|
shouldReload ? [hashKey(useQueryHook.getKey([identifier as DeepPartial<IdType>]))] : [],
|
|
108
111
|
result.isFetching,
|
|
109
|
-
result.error
|
|
112
|
+
result.error,
|
|
110
113
|
);
|
|
111
114
|
return result;
|
|
112
115
|
}
|
|
@@ -116,29 +119,45 @@ export function generateIdsQuery<
|
|
|
116
119
|
FuncArguments extends Parameters<Func>['length'] extends 0
|
|
117
120
|
? void
|
|
118
121
|
: Parameters<Func> = Parameters<Func>['length'] extends 0 ? void : Parameters<Func>,
|
|
119
|
-
ResultAsArray extends boolean = false
|
|
122
|
+
ResultAsArray extends boolean = false,
|
|
120
123
|
>(
|
|
121
|
-
queryClient: QueryClient,
|
|
122
124
|
filterFunc: Func,
|
|
123
125
|
additionalOptions?: Omit<CreateQueryOptions<IdType[], [FuncArguments]>, 'queryKey' | 'fetcher'> & {
|
|
124
126
|
resultAsArray?: ResultAsArray;
|
|
125
127
|
subKey?: string;
|
|
126
|
-
}
|
|
128
|
+
},
|
|
127
129
|
) {
|
|
130
|
+
let queryClient: QueryClient | undefined;
|
|
131
|
+
|
|
132
|
+
function getQueryClient() {
|
|
133
|
+
if (!queryClient) {
|
|
134
|
+
throw new Error('QueryClient not set');
|
|
135
|
+
}
|
|
136
|
+
return queryClient;
|
|
137
|
+
}
|
|
138
|
+
|
|
128
139
|
const queryHook = generateQuery(
|
|
129
140
|
`${key}-filter${additionalOptions?.subKey ? `-${additionalOptions.subKey}` : ''}`,
|
|
130
141
|
async (filter: FuncArguments) => {
|
|
131
142
|
const result = await filterFunc(filter);
|
|
132
|
-
return result.map(item => {
|
|
133
|
-
|
|
143
|
+
return result.map((item) => {
|
|
144
|
+
getQueryClient().setQueryData(useQueryHook.getKey([item.id as DeepPartial<IdType>]), item);
|
|
134
145
|
return item.id;
|
|
135
146
|
});
|
|
136
147
|
},
|
|
137
148
|
{
|
|
138
149
|
initialDataUpdatedAt: 0,
|
|
139
150
|
...additionalOptions,
|
|
140
|
-
initialData: (additionalOptions?.initialData as IdType[]) ?? []
|
|
141
|
-
|
|
151
|
+
initialData: (additionalOptions?.initialData as IdType[]) ?? [],
|
|
152
|
+
use: [
|
|
153
|
+
function myTestMiddleware(useQueryNext) {
|
|
154
|
+
return (options2, currentQueryClient) => {
|
|
155
|
+
queryClient = useQueryClient(currentQueryClient);
|
|
156
|
+
return useQueryNext(options2, queryClient);
|
|
157
|
+
};
|
|
158
|
+
},
|
|
159
|
+
],
|
|
160
|
+
},
|
|
142
161
|
);
|
|
143
162
|
|
|
144
163
|
type QueryHookArgument = Parameters<typeof queryHook>[0];
|
|
@@ -147,12 +166,12 @@ export function generateIdsQuery<
|
|
|
147
166
|
function useFilter<Args extends HookArgs>(
|
|
148
167
|
...args: Args
|
|
149
168
|
): ResultAsArray extends true ? UseQueryResult<Type, Error>[] : URecord<IdType, UseQueryResult<Type, Error>> {
|
|
150
|
-
const result = queryHook({variables: args} as QueryHookArgument);
|
|
169
|
+
const result = queryHook({ variables: args } as QueryHookArgument);
|
|
151
170
|
|
|
152
171
|
useQueriesSubscribeToReload(
|
|
153
172
|
[hashKey(queryHook.getKey(args as Parameters<(typeof queryHook)['getKey']>[0]))],
|
|
154
173
|
result.isFetching,
|
|
155
|
-
result.error
|
|
174
|
+
result.error,
|
|
156
175
|
);
|
|
157
176
|
|
|
158
177
|
// When staleTime is same as filterStaleTime, then the queries will run at the same time as the filter
|
|
@@ -160,10 +179,10 @@ export function generateIdsQuery<
|
|
|
160
179
|
// filter will be saved inside the queryClient, so the queries will be updated with the new data.
|
|
161
180
|
// Same goes for reloading with context.
|
|
162
181
|
// Other usages of useManyHook are not affected by this.
|
|
163
|
-
const indexedResult = useManyHook(result.data, {staleTime: Infinity, reloadWithContext: false});
|
|
182
|
+
const indexedResult = useManyHook(result.data, { staleTime: Infinity, reloadWithContext: false });
|
|
164
183
|
const arrayResult: UseQueryResult<Type, Error>[] = useMemo(
|
|
165
|
-
() => ArrayHelper.noUndefined(result.data.map(id => indexedResult[id])),
|
|
166
|
-
[indexedResult, result.data]
|
|
184
|
+
() => ArrayHelper.noUndefined(result.data.map((id) => indexedResult[id])),
|
|
185
|
+
[indexedResult, result.data],
|
|
167
186
|
);
|
|
168
187
|
|
|
169
188
|
if (additionalOptions?.resultAsArray) {
|
|
@@ -174,48 +193,45 @@ export function generateIdsQuery<
|
|
|
174
193
|
return indexedResult as ResultAsArray extends true
|
|
175
194
|
? UseQueryResult<Type, Error>[]
|
|
176
195
|
: URecord<IdType, UseQueryResult<Type, Error>>;
|
|
177
|
-
|
|
178
196
|
}
|
|
179
197
|
|
|
180
198
|
return hoistReactQueryKitAttributes(queryHook, useFilter);
|
|
181
199
|
}
|
|
182
200
|
|
|
183
|
-
function generateInfiniteQuery<PageParams, Meta, FuncArguments extends any[] = []>(
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
}
|
|
213
|
-
) {
|
|
201
|
+
function generateInfiniteQuery<PageParams, Meta, FuncArguments extends any[] = []>({
|
|
202
|
+
queryFn,
|
|
203
|
+
...options
|
|
204
|
+
}: Omit<
|
|
205
|
+
CreateInfiniteQueryOptions<{ data: IdType[]; meta: Meta }, FuncArguments, Error, PageParams>,
|
|
206
|
+
'getNextPageParam' | 'getPreviousPageParam' | 'queryKey' | 'fetcher'
|
|
207
|
+
> & {
|
|
208
|
+
queryFn: (
|
|
209
|
+
pageParams: PageParams,
|
|
210
|
+
args: FuncArguments,
|
|
211
|
+
context: QueryFunctionContext<[string, FuncArguments], PageParams>,
|
|
212
|
+
) => Awaitable<{ data: Type[]; meta: Meta }>;
|
|
213
|
+
getNextPageParam: (options: {
|
|
214
|
+
getLastPage: () => Type[];
|
|
215
|
+
getAllPages: () => Type[][];
|
|
216
|
+
lastPageParam: PageParams;
|
|
217
|
+
allPageParams: PageParams[];
|
|
218
|
+
lastPageLength: number;
|
|
219
|
+
lastPageMeta: Meta;
|
|
220
|
+
}) => PageParams | undefined;
|
|
221
|
+
getPreviousPageParam?: (options: {
|
|
222
|
+
getFirstPage: () => Type[];
|
|
223
|
+
getAllPages: () => Type[][];
|
|
224
|
+
firstPageParam: PageParams;
|
|
225
|
+
allPageParams: PageParams[];
|
|
226
|
+
firstPageLength: number;
|
|
227
|
+
firstPageMeta: Meta;
|
|
228
|
+
}) => PageParams | undefined;
|
|
229
|
+
}) {
|
|
214
230
|
let queryClient: QueryClient | undefined;
|
|
215
231
|
|
|
216
232
|
function getQueryClient() {
|
|
217
233
|
if (!queryClient) {
|
|
218
|
-
throw new Error(
|
|
234
|
+
throw new Error('QueryClient not set');
|
|
219
235
|
}
|
|
220
236
|
return queryClient;
|
|
221
237
|
}
|
|
@@ -224,128 +240,157 @@ export function generateIdsQuery<
|
|
|
224
240
|
return getQueryClient().getQueryData(useQueryHook.getKey([id as DeepPartial<IdType>])) as Type | undefined;
|
|
225
241
|
}
|
|
226
242
|
|
|
227
|
-
const {getPreviousPageParam} = options;
|
|
228
|
-
const infiniteQueryHook = createInfiniteQuery<
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
243
|
+
const { getPreviousPageParam } = options;
|
|
244
|
+
const infiniteQueryHook = createInfiniteQuery<
|
|
245
|
+
{
|
|
246
|
+
data: IdType[];
|
|
247
|
+
meta: Meta;
|
|
248
|
+
},
|
|
249
|
+
FuncArguments,
|
|
250
|
+
Error,
|
|
251
|
+
PageParams
|
|
252
|
+
>({
|
|
232
253
|
...options,
|
|
233
|
-
use: [
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
254
|
+
use: [
|
|
255
|
+
function myTestMiddleware(useQueryNext) {
|
|
256
|
+
return (options2, currentQueryClient) => {
|
|
257
|
+
queryClient = useQueryClient(currentQueryClient);
|
|
258
|
+
return useQueryNext(options2, queryClient);
|
|
259
|
+
};
|
|
260
|
+
},
|
|
261
|
+
],
|
|
239
262
|
queryKey: [`${key}-infinite-query`],
|
|
240
263
|
fetcher: async (_, ctx) => {
|
|
241
264
|
const context = ctx as typeof ctx & { pageParam: PageParams };
|
|
242
265
|
const result = await queryFn(
|
|
243
266
|
context.pageParam,
|
|
244
267
|
context.queryKey[1] as FuncArguments,
|
|
245
|
-
context as QueryFunctionContext<[string, FuncArguments], PageParams
|
|
268
|
+
context as QueryFunctionContext<[string, FuncArguments], PageParams>,
|
|
246
269
|
);
|
|
247
270
|
return {
|
|
248
271
|
meta: result.meta,
|
|
249
|
-
data: result.data.map(item => {
|
|
272
|
+
data: result.data.map((item) => {
|
|
250
273
|
getQueryClient().setQueryData(useQueryHook.getKey([item.id as DeepPartial<IdType>]), item);
|
|
251
274
|
return item.id;
|
|
252
|
-
})
|
|
275
|
+
}),
|
|
253
276
|
};
|
|
254
277
|
},
|
|
255
|
-
getNextPageParam: (
|
|
256
|
-
meta: Meta,
|
|
257
|
-
|
|
258
|
-
|
|
278
|
+
getNextPageParam: (
|
|
279
|
+
lastPage: { meta: Meta; data: IdType[] },
|
|
280
|
+
allPages: {
|
|
281
|
+
meta: Meta;
|
|
282
|
+
data: IdType[];
|
|
283
|
+
}[],
|
|
284
|
+
lastPageParam,
|
|
285
|
+
allPageParams,
|
|
286
|
+
) => {
|
|
259
287
|
return options.getNextPageParam({
|
|
260
288
|
lastPageMeta: lastPage.meta,
|
|
261
289
|
getLastPage: () => ArrayHelper.noUndefined(lastPage.data.map(findEntity)),
|
|
262
|
-
getAllPages: () => allPages.map(page => ArrayHelper.noUndefined(page.data.map(findEntity))),
|
|
290
|
+
getAllPages: () => allPages.map((page) => ArrayHelper.noUndefined(page.data.map(findEntity))),
|
|
263
291
|
lastPageParam,
|
|
264
292
|
allPageParams,
|
|
265
|
-
lastPageLength: lastPage.data.length
|
|
293
|
+
lastPageLength: lastPage.data.length,
|
|
266
294
|
});
|
|
267
295
|
},
|
|
268
296
|
getPreviousPageParam: !getPreviousPageParam
|
|
269
297
|
? undefined
|
|
270
298
|
: (firstPage, allPages, firstPageParam, allPageParams) => {
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
299
|
+
return getPreviousPageParam({
|
|
300
|
+
firstPageMeta: firstPage.meta,
|
|
301
|
+
getFirstPage: () => ArrayHelper.noUndefined(firstPage.data.map(findEntity)),
|
|
302
|
+
getAllPages: () => allPages.map((page) => ArrayHelper.noUndefined(page.data.map(findEntity))),
|
|
303
|
+
firstPageParam,
|
|
304
|
+
allPageParams,
|
|
305
|
+
firstPageLength: firstPage.data.length,
|
|
306
|
+
});
|
|
307
|
+
},
|
|
280
308
|
});
|
|
281
309
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
310
|
+
type HookOptions = Override<
|
|
311
|
+
Parameters<typeof infiniteQueryHook>[0] & {
|
|
312
|
+
select?: undefined;
|
|
313
|
+
},
|
|
314
|
+
{
|
|
315
|
+
initialData?: {
|
|
316
|
+
pages: { data: Type[]; meta: Meta }[];
|
|
317
|
+
pageParams: PageParams[];
|
|
318
|
+
};
|
|
289
319
|
}
|
|
290
|
-
|
|
320
|
+
>;
|
|
291
321
|
|
|
292
|
-
type InfiniteQueryArgs = FuncArguments extends
|
|
293
|
-
|
|
294
|
-
|
|
322
|
+
type InfiniteQueryArgs = FuncArguments extends
|
|
323
|
+
| {
|
|
324
|
+
length: 0;
|
|
325
|
+
}
|
|
326
|
+
| symbol
|
|
327
|
+
| undefined
|
|
328
|
+
? [HookOptions] | []
|
|
329
|
+
: [HookOptions];
|
|
295
330
|
|
|
296
331
|
function useInfiniteQuery(...args: InfiniteQueryArgs) {
|
|
297
332
|
const infiniteQueryClient = useQueryClient();
|
|
298
333
|
|
|
299
334
|
let infiniteOptions: Parameters<typeof infiniteQueryHook>[0] & {
|
|
300
|
-
select?: undefined
|
|
335
|
+
select?: undefined;
|
|
301
336
|
};
|
|
302
|
-
if (args.length === 1 &&
|
|
303
|
-
const {initialData} = args[0];
|
|
337
|
+
if (args.length === 1 && 'initialData' in args[0] && args[0].initialData) {
|
|
338
|
+
const { initialData } = args[0];
|
|
304
339
|
infiniteOptions = {
|
|
305
340
|
...args[0],
|
|
306
341
|
initialData: {
|
|
307
|
-
pages: initialData.pages.map(page => ({
|
|
342
|
+
pages: initialData.pages.map((page) => ({
|
|
308
343
|
...page,
|
|
309
|
-
data: page.data.map(item => {
|
|
310
|
-
infiniteQueryClient.setQueryData(
|
|
344
|
+
data: page.data.map((item) => {
|
|
345
|
+
infiniteQueryClient.setQueryData(
|
|
346
|
+
useQueryHook.getKey([item.id as DeepPartial<IdType>]),
|
|
347
|
+
item,
|
|
348
|
+
);
|
|
311
349
|
return item.id;
|
|
312
|
-
})
|
|
350
|
+
}),
|
|
313
351
|
})),
|
|
314
|
-
pageParams: initialData.pageParams
|
|
315
|
-
}
|
|
352
|
+
pageParams: initialData.pageParams,
|
|
353
|
+
},
|
|
316
354
|
} as Parameters<typeof infiniteQueryHook>[0] & {
|
|
317
|
-
select?: undefined
|
|
355
|
+
select?: undefined;
|
|
318
356
|
};
|
|
319
357
|
} else {
|
|
320
|
-
infiniteOptions =
|
|
321
|
-
|
|
322
|
-
|
|
358
|
+
infiniteOptions =
|
|
359
|
+
(args[0] as Parameters<typeof infiniteQueryHook>[0] & {
|
|
360
|
+
select?: undefined;
|
|
361
|
+
}) ?? {};
|
|
323
362
|
}
|
|
324
363
|
const result = infiniteQueryHook(infiniteOptions);
|
|
325
364
|
useQueriesSubscribeToReload(
|
|
326
|
-
[
|
|
365
|
+
[
|
|
366
|
+
hashKey(
|
|
367
|
+
infiniteQueryHook.getKey(
|
|
368
|
+
infiniteOptions.variables as Parameters<(typeof infiniteQueryHook)['getKey']>[0],
|
|
369
|
+
),
|
|
370
|
+
),
|
|
371
|
+
],
|
|
327
372
|
result.isFetching,
|
|
328
|
-
result.error
|
|
373
|
+
result.error,
|
|
329
374
|
);
|
|
330
|
-
const ids = useMemo(() => result.data?.pages.flatMap(page => page.data) ?? [], [result.data?.pages]);
|
|
375
|
+
const ids = useMemo(() => result.data?.pages.flatMap((page) => page.data) ?? [], [result.data?.pages]);
|
|
331
376
|
|
|
332
377
|
// When staleTime is same as filterStaleTime, then the queries will run at the same time as the filter
|
|
333
378
|
// Because of this, use staleTime: Inifinity to prevent the queries from running again. The result of the
|
|
334
379
|
// filter will be saved inside the queryClient, so the queries will be updated with the new data.
|
|
335
380
|
// Same goes for reloading with context.
|
|
336
381
|
// Other usages of useManyHook are not affected by this.
|
|
337
|
-
const manyData = useManyHook(ids, {staleTime: Infinity, reloadWithContext: false});
|
|
382
|
+
const manyData = useManyHook(ids, { staleTime: Infinity, reloadWithContext: false });
|
|
338
383
|
const indexedData = useIndexedData(manyData);
|
|
339
384
|
|
|
340
385
|
const pages = useMemo(() => {
|
|
341
386
|
return result.data
|
|
342
|
-
? result.data.pages.map(page => ArrayHelper.noUndefined(page.data.map(id => indexedData[id])))
|
|
387
|
+
? result.data.pages.map((page) => ArrayHelper.noUndefined(page.data.map((id) => indexedData[id])))
|
|
343
388
|
: [];
|
|
344
389
|
}, [indexedData, result.data]);
|
|
345
390
|
|
|
346
391
|
return {
|
|
347
392
|
...result,
|
|
348
|
-
data: !result.data ? undefined : {...result.data, pages}
|
|
393
|
+
data: !result.data ? undefined : { ...result.data, pages },
|
|
349
394
|
};
|
|
350
395
|
}
|
|
351
396
|
|
|
@@ -355,5 +400,5 @@ export function generateIdsQuery<
|
|
|
355
400
|
|
|
356
401
|
const useMany = hoistReactQueryKitAttributes(useQueryHook, useManyHook);
|
|
357
402
|
const useOne = hoistReactQueryKitAttributes(useQueryHook, useOneHook);
|
|
358
|
-
return {useMany, useOne, generateFilter, generateInfiniteQuery};
|
|
403
|
+
return { useMany, useOne, generateFilter, generateInfiniteQuery };
|
|
359
404
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { type QueryClient, hashKey } from '@tanstack/react-query';
|
|
2
1
|
import { generateIdsQuery } from '@/generateIdsQuery';
|
|
2
|
+
import { hashKey } from '@tanstack/react-query';
|
|
3
3
|
import { noop } from '@/noop';
|
|
4
4
|
import { useMemo } from 'react';
|
|
5
5
|
import type { DeepPartial } from '@/types/DeepPartial';
|
|
@@ -9,7 +9,7 @@ export function generateNestedIdQuery<
|
|
|
9
9
|
Type extends {
|
|
10
10
|
id: IdType;
|
|
11
11
|
},
|
|
12
|
-
Args extends any[]
|
|
12
|
+
Args extends any[],
|
|
13
13
|
>(key: string, fetcherFactory: (...args: Args) => (ids: IdType[]) => Promise<Type[]> | Type[]) {
|
|
14
14
|
const factory = (...args: Args) => {
|
|
15
15
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
@@ -19,17 +19,17 @@ export function generateNestedIdQuery<
|
|
|
19
19
|
}, [args]);
|
|
20
20
|
};
|
|
21
21
|
|
|
22
|
-
factory.getFilterKey = (args: Args, variables?: any[]) => {
|
|
22
|
+
factory.getFilterKey = (args: Args, variables?: any[]): readonly unknown[] => {
|
|
23
23
|
const keyWithArgs = `${key}-${hashKey(args)}`;
|
|
24
24
|
return generateIdsQuery(keyWithArgs, fetcherFactory(...args))
|
|
25
|
-
.generateFilter(
|
|
25
|
+
.generateFilter(noop as (..._: any[]) => Type[])
|
|
26
26
|
.getKey([variables]);
|
|
27
27
|
};
|
|
28
28
|
|
|
29
29
|
factory.getKey = <Variables extends [(DeepPartial<IdType> | undefined)?] | undefined = undefined>(
|
|
30
30
|
args: Args,
|
|
31
|
-
variables?: Variables
|
|
32
|
-
) => {
|
|
31
|
+
variables?: Variables,
|
|
32
|
+
): readonly unknown[] => {
|
|
33
33
|
const keyWithArgs = `${key}-${hashKey(args)}`;
|
|
34
34
|
return generateIdsQuery(keyWithArgs, fetcherFactory(...args)).useOne.getKey(variables);
|
|
35
35
|
};
|
package/src/generateQuery.ts
CHANGED
|
@@ -13,19 +13,18 @@ export function generateQuery<
|
|
|
13
13
|
AdditionalOptionsType extends Omit<
|
|
14
14
|
CreateQueryOptions<FuncReturnType, FuncArguments>,
|
|
15
15
|
'queryKey' | 'fetcher'
|
|
16
|
-
> = Omit<CreateQueryOptions<FuncReturnType, FuncArguments>, 'queryKey' | 'fetcher'
|
|
16
|
+
> = Omit<CreateQueryOptions<FuncReturnType, FuncArguments>, 'queryKey' | 'fetcher'>,
|
|
17
17
|
>(primaryKey: string, queryFn: Func, additionalOptions?: AdditionalOptionsType) {
|
|
18
18
|
const queryHook = createQuery<FuncReturnType, FuncArguments>({
|
|
19
19
|
queryKey: [primaryKey],
|
|
20
|
-
fetcher: variables => {
|
|
20
|
+
fetcher: (variables) => {
|
|
21
21
|
if (Array.isArray(variables)) {
|
|
22
22
|
return queryFn(...variables);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
}
|
|
24
|
+
return queryFn();
|
|
26
25
|
},
|
|
27
26
|
initialDataUpdatedAt: 0,
|
|
28
|
-
...additionalOptions
|
|
27
|
+
...additionalOptions,
|
|
29
28
|
});
|
|
30
29
|
|
|
31
30
|
type QueryHookArgument = Parameters<typeof queryHook>[0];
|
|
@@ -33,20 +32,20 @@ export function generateQuery<
|
|
|
33
32
|
|
|
34
33
|
function useHook<Arg extends HookArgs>(...options: Arg) {
|
|
35
34
|
type DataReturnType = Arg extends [
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
35
|
+
{
|
|
36
|
+
initialData: FuncReturnType | (() => FuncReturnType);
|
|
37
|
+
},
|
|
38
|
+
]
|
|
40
39
|
? FuncReturnType
|
|
41
40
|
: AdditionalOptionsType extends { initialData: FuncReturnType | (() => FuncReturnType) }
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
? FuncReturnType
|
|
42
|
+
: FuncReturnType | undefined;
|
|
44
43
|
|
|
45
44
|
const result = queryHook(options[0] as QueryHookArgument);
|
|
46
45
|
useQueriesSubscribeToReload(
|
|
47
46
|
[hashKey(queryHook.getKey(options[0]?.variables as Parameters<(typeof queryHook)['getKey']>[0]))],
|
|
48
47
|
result.isFetching,
|
|
49
|
-
result.error
|
|
48
|
+
result.error,
|
|
50
49
|
);
|
|
51
50
|
|
|
52
51
|
type Return = Arg extends [{ select: (...arg: any[]) => any }] ? ReturnType<Arg[0]['select']> : DataReturnType;
|
|
@@ -2,7 +2,7 @@ import type { ExposeMethods } from 'react-query-kit/build/lib/types';
|
|
|
2
2
|
|
|
3
3
|
export function hoistReactQueryKitAttributes<ReturnType, HookArgs, ToFunc extends (...args: any) => any, Error>(
|
|
4
4
|
from: ExposeMethods<ReturnType, HookArgs, Error>,
|
|
5
|
-
to: ToFunc
|
|
5
|
+
to: ToFunc,
|
|
6
6
|
) {
|
|
7
7
|
const partialHook: Partial<ExposeMethods<ReturnType, HookArgs, Error>> & ToFunc = to;
|
|
8
8
|
const hoistedOptions = ['fetcher', 'getKey', 'queryKeyHashFn', 'getOptions'] as const;
|
|
@@ -7,13 +7,13 @@ export function useArrayData<DataType>(
|
|
|
7
7
|
| {
|
|
8
8
|
data: DataType;
|
|
9
9
|
}[]
|
|
10
|
-
| URecord<any, { data: DataType | undefined }
|
|
10
|
+
| URecord<any, { data: DataType | undefined }>,
|
|
11
11
|
): Exclude<DataType, undefined>[] {
|
|
12
12
|
return useMemo(
|
|
13
13
|
() =>
|
|
14
14
|
ArrayHelper.noUndefined(
|
|
15
|
-
(Array.isArray(result) ? result : ObjectHelper.values(result)).map(data => data.data)
|
|
15
|
+
(Array.isArray(result) ? result : ObjectHelper.values(result)).map((data) => data.data),
|
|
16
16
|
),
|
|
17
|
-
[result]
|
|
17
|
+
[result],
|
|
18
18
|
);
|
|
19
19
|
}
|
|
@@ -8,7 +8,7 @@ export function useIndexedData<DataType, IndexType extends number | string | sym
|
|
|
8
8
|
{
|
|
9
9
|
data: DataType | undefined;
|
|
10
10
|
}
|
|
11
|
-
|
|
11
|
+
>,
|
|
12
12
|
) {
|
|
13
13
|
return useMemo(
|
|
14
14
|
() =>
|
|
@@ -17,8 +17,8 @@ export function useIndexedData<DataType, IndexType extends number | string | sym
|
|
|
17
17
|
acc[key] = data.data;
|
|
18
18
|
return acc;
|
|
19
19
|
},
|
|
20
|
-
{} as URecord<IndexType, DataType
|
|
20
|
+
{} as URecord<IndexType, DataType>,
|
|
21
21
|
),
|
|
22
|
-
[result]
|
|
22
|
+
[result],
|
|
23
23
|
);
|
|
24
24
|
}
|
package/src/noop.ts
CHANGED