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