@umituz/react-native-design-system 2.8.9 → 2.8.11
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/package.json +8 -1
- package/src/exports/tanstack.ts +1 -0
- package/src/index.ts +5 -0
- package/src/media/presentation/hooks/useCardMediaUpload.ts +1 -1
- package/src/media/presentation/hooks/useCardMultimediaFlashcard.ts +3 -3
- package/src/media/presentation/hooks/useMediaUpload.ts +1 -1
- package/src/media/presentation/hooks/useMultimediaFlashcard.ts +3 -3
- package/src/tanstack/domain/constants/CacheDefaults.ts +63 -0
- package/src/tanstack/domain/repositories/BaseRepository.ts +280 -0
- package/src/tanstack/domain/repositories/RepositoryFactory.ts +135 -0
- package/src/tanstack/domain/types/CacheStrategy.ts +115 -0
- package/src/tanstack/domain/utils/ErrorHelpers.ts +154 -0
- package/src/tanstack/domain/utils/QueryKeyFactory.ts +134 -0
- package/src/tanstack/domain/utils/TypeUtilities.ts +153 -0
- package/src/tanstack/index.ts +161 -0
- package/src/tanstack/infrastructure/config/PersisterConfig.ts +162 -0
- package/src/tanstack/infrastructure/config/QueryClientConfig.ts +154 -0
- package/src/tanstack/infrastructure/config/QueryClientSingleton.ts +69 -0
- package/src/tanstack/infrastructure/monitoring/DevMonitor.ts +274 -0
- package/src/tanstack/infrastructure/providers/TanstackProvider.tsx +105 -0
- package/src/tanstack/presentation/hooks/useInvalidateQueries.ts +128 -0
- package/src/tanstack/presentation/hooks/useOptimisticUpdate.ts +88 -0
- package/src/tanstack/presentation/hooks/usePaginatedQuery.ts +129 -0
- package/src/tanstack/presentation/hooks/usePrefetch.ts +237 -0
- package/src/tanstack/presentation/utils/RetryHelpers.ts +67 -0
- package/src/tanstack/types/global.d.ts +1 -0
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error Helpers
|
|
3
|
+
* Domain layer - Error handling utilities
|
|
4
|
+
*
|
|
5
|
+
* General-purpose error handling for TanStack Query
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Check if error is a QueryError (from TanStack Query)
|
|
10
|
+
*/
|
|
11
|
+
export function isQueryError(error: unknown): boolean {
|
|
12
|
+
return (
|
|
13
|
+
error !== null &&
|
|
14
|
+
typeof error === 'object' &&
|
|
15
|
+
'message' in error &&
|
|
16
|
+
typeof error.message === 'string'
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Check if error is a MutationError (from TanStack Query)
|
|
22
|
+
*/
|
|
23
|
+
export function isMutationError(error: unknown): boolean {
|
|
24
|
+
return isQueryError(error);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Check if error is a network error
|
|
29
|
+
*/
|
|
30
|
+
export function isNetworkError(error: unknown): boolean {
|
|
31
|
+
if (!isQueryError(error)) return false;
|
|
32
|
+
|
|
33
|
+
const message = (error as { message: string }).message.toLowerCase();
|
|
34
|
+
return (
|
|
35
|
+
message.includes('network') ||
|
|
36
|
+
message.includes('fetch') ||
|
|
37
|
+
message.includes('connection')
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Check if error is an abort error
|
|
43
|
+
*/
|
|
44
|
+
export function isAbortError(error: unknown): boolean {
|
|
45
|
+
return error instanceof Error && error.name === 'AbortError';
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Extract error message from error
|
|
50
|
+
*/
|
|
51
|
+
export function getErrorMessage(error: unknown): string {
|
|
52
|
+
if (error instanceof Error) {
|
|
53
|
+
return error.message;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (isQueryError(error)) {
|
|
57
|
+
return (error as { message: string }).message;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (typeof error === 'string') {
|
|
61
|
+
return error;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return 'An unknown error occurred';
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Get user-friendly error message
|
|
69
|
+
* Maps technical errors to user-friendly messages
|
|
70
|
+
*/
|
|
71
|
+
export function getUserFriendlyMessage(error: unknown): string {
|
|
72
|
+
const message = getErrorMessage(error).toLowerCase();
|
|
73
|
+
|
|
74
|
+
if (isNetworkError(error)) {
|
|
75
|
+
return 'Network connection failed. Please check your internet connection.';
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (isAbortError(error)) {
|
|
79
|
+
return 'Request was cancelled.';
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (message.includes('unauthorized') || message.includes('401')) {
|
|
83
|
+
return 'You are not authorized to perform this action.';
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (message.includes('forbidden') || message.includes('403')) {
|
|
87
|
+
return 'You do not have permission to access this resource.';
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (message.includes('not found') || message.includes('404')) {
|
|
91
|
+
return 'The requested resource was not found.';
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (message.includes('validation') || message.includes('400')) {
|
|
95
|
+
return 'Please check your input and try again.';
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (message.includes('server') || message.includes('500')) {
|
|
99
|
+
return 'A server error occurred. Please try again later.';
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (message.includes('timeout')) {
|
|
103
|
+
return 'Request timed out. Please try again.';
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return 'An error occurred. Please try again.';
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Parse error response (for API errors with structured data)
|
|
111
|
+
*/
|
|
112
|
+
export interface ErrorResponse {
|
|
113
|
+
message: string;
|
|
114
|
+
errors?: Record<string, string[]>;
|
|
115
|
+
code?: string;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export function parseErrorResponse(error: unknown): ErrorResponse | null {
|
|
119
|
+
if (!isQueryError(error)) return null;
|
|
120
|
+
|
|
121
|
+
const errorObj = error as { response?: { data?: ErrorResponse } };
|
|
122
|
+
|
|
123
|
+
if (errorObj.response?.data) {
|
|
124
|
+
return errorObj.response.data;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Get validation errors from error response
|
|
132
|
+
*/
|
|
133
|
+
export function getValidationErrors(error: unknown): Record<string, string[]> | null {
|
|
134
|
+
const response = parseErrorResponse(error);
|
|
135
|
+
return response?.errors ?? null;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Get error code from error response
|
|
140
|
+
*/
|
|
141
|
+
export function getErrorCode(error: unknown): string | null {
|
|
142
|
+
const response = parseErrorResponse(error);
|
|
143
|
+
return response?.code ?? null;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Log error in development
|
|
148
|
+
*/
|
|
149
|
+
export function logError(context: string, error: unknown): void {
|
|
150
|
+
if (__DEV__) {
|
|
151
|
+
|
|
152
|
+
console.error(`[${context}]`, error);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Query Key Factory
|
|
3
|
+
* Domain layer - Query key generation utilities
|
|
4
|
+
*
|
|
5
|
+
* General-purpose query key patterns for any React Native app
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Create a typed query key factory for a resource
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```typescript
|
|
13
|
+
* const postKeys = createQueryKeyFactory('posts');
|
|
14
|
+
*
|
|
15
|
+
* // All posts
|
|
16
|
+
* postKeys.all() // ['posts']
|
|
17
|
+
*
|
|
18
|
+
* // Posts list
|
|
19
|
+
* postKeys.lists() // ['posts', 'list']
|
|
20
|
+
*
|
|
21
|
+
* // Posts list with filters
|
|
22
|
+
* postKeys.list({ status: 'published' }) // ['posts', 'list', { status: 'published' }]
|
|
23
|
+
*
|
|
24
|
+
* // Single post detail
|
|
25
|
+
* postKeys.detail(123) // ['posts', 'detail', 123]
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export function createQueryKeyFactory(resource: string) {
|
|
29
|
+
return {
|
|
30
|
+
/**
|
|
31
|
+
* All queries for this resource
|
|
32
|
+
*/
|
|
33
|
+
all: () => [resource] as const,
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* All list queries for this resource
|
|
37
|
+
*/
|
|
38
|
+
lists: () => [resource, 'list'] as const,
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* List query with optional filters
|
|
42
|
+
*/
|
|
43
|
+
list: (filters?: Record<string, unknown>) =>
|
|
44
|
+
filters ? ([resource, 'list', filters] as const) : ([resource, 'list'] as const),
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* All detail queries for this resource
|
|
48
|
+
*/
|
|
49
|
+
details: () => [resource, 'detail'] as const,
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Detail query for specific item
|
|
53
|
+
*/
|
|
54
|
+
detail: (id: string | number) => [resource, 'detail', id] as const,
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Custom query key
|
|
58
|
+
*/
|
|
59
|
+
custom: (...args: unknown[]) => [resource, ...args] as const,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Create a query key for a list with pagination
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* ```typescript
|
|
68
|
+
* createPaginatedQueryKey('posts', { page: 1, limit: 10 })
|
|
69
|
+
* // ['posts', 'list', { page: 1, limit: 10 }]
|
|
70
|
+
* ```
|
|
71
|
+
*/
|
|
72
|
+
export function createPaginatedQueryKey(
|
|
73
|
+
resource: string,
|
|
74
|
+
pagination: { page?: number; limit?: number; cursor?: string },
|
|
75
|
+
): readonly [string, 'list', typeof pagination] {
|
|
76
|
+
return [resource, 'list', pagination] as const;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Create a query key for infinite scroll
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* ```typescript
|
|
84
|
+
* createInfiniteQueryKey('feed', { limit: 20 })
|
|
85
|
+
* // ['feed', 'infinite', { limit: 20 }]
|
|
86
|
+
* ```
|
|
87
|
+
*/
|
|
88
|
+
export function createInfiniteQueryKey(
|
|
89
|
+
resource: string,
|
|
90
|
+
params?: Record<string, unknown>,
|
|
91
|
+
): readonly [string, 'infinite', Record<string, unknown>] | readonly [string, 'infinite'] {
|
|
92
|
+
return params ? ([resource, 'infinite', params] as const) : ([resource, 'infinite'] as const);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Create a scoped query key (for user-specific data)
|
|
97
|
+
*
|
|
98
|
+
* @example
|
|
99
|
+
* ```typescript
|
|
100
|
+
* createScopedQueryKey('user123', 'posts')
|
|
101
|
+
* // ['user', 'user123', 'posts']
|
|
102
|
+
* ```
|
|
103
|
+
*/
|
|
104
|
+
export function createScopedQueryKey(
|
|
105
|
+
scopeId: string,
|
|
106
|
+
resource: string,
|
|
107
|
+
...args: unknown[]
|
|
108
|
+
): readonly [string, string, string, ...unknown[]] {
|
|
109
|
+
return ['user', scopeId, resource, ...args] as const;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Match query keys by pattern
|
|
114
|
+
* Useful for invalidating multiple related queries
|
|
115
|
+
*
|
|
116
|
+
* @example
|
|
117
|
+
* ```typescript
|
|
118
|
+
* // Invalidate all post queries
|
|
119
|
+
* queryClient.invalidateQueries({
|
|
120
|
+
* predicate: (query) => matchQueryKey(query.queryKey, ['posts'])
|
|
121
|
+
* })
|
|
122
|
+
* ```
|
|
123
|
+
*/
|
|
124
|
+
export function matchQueryKey(
|
|
125
|
+
queryKey: readonly unknown[],
|
|
126
|
+
pattern: readonly unknown[],
|
|
127
|
+
): boolean {
|
|
128
|
+
if (pattern.length > queryKey.length) return false;
|
|
129
|
+
|
|
130
|
+
return pattern.every((value, index) => {
|
|
131
|
+
if (value === undefined) return true;
|
|
132
|
+
return queryKey[index] === value;
|
|
133
|
+
});
|
|
134
|
+
}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type Utilities
|
|
3
|
+
* Domain layer - Type extractors and helpers
|
|
4
|
+
*
|
|
5
|
+
* General-purpose type utilities for TanStack Query
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { UseQueryResult, UseMutationResult } from '@tanstack/react-query';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Extract data type from UseQueryResult
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* const result = useQuery({ queryKey: ['user'], queryFn: fetchUser });
|
|
16
|
+
* type User = ExtractQueryDataType<typeof result>; // User
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
export type ExtractQueryDataType<TQuery extends UseQueryResult<unknown, unknown>> =
|
|
20
|
+
TQuery extends UseQueryResult<infer TData, unknown> ? TData : never;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Extract error type from UseQueryResult
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```typescript
|
|
27
|
+
* const result = useQuery({ queryKey: ['user'], queryFn: fetchUser });
|
|
28
|
+
* type Error = ExtractQueryErrorType<typeof result>; // Error
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export type ExtractQueryErrorType<TQuery extends UseQueryResult<unknown, unknown>> =
|
|
32
|
+
TQuery extends UseQueryResult<unknown, infer TError> ? TError : never;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Extract data type from UseMutationResult
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```typescript
|
|
39
|
+
* const mutation = useMutation({ mutationFn: createUser });
|
|
40
|
+
* type User = ExtractMutationDataType<typeof mutation>; // User
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
export type ExtractMutationDataType<TMutation extends UseMutationResult<unknown, unknown, unknown>> =
|
|
44
|
+
TMutation extends UseMutationResult<infer TData, unknown, unknown> ? TData : never;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Extract error type from UseMutationResult
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```typescript
|
|
51
|
+
* const mutation = useMutation({ mutationFn: createUser });
|
|
52
|
+
* type Error = ExtractMutationErrorType<typeof mutation>; // Error
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
export type ExtractMutationErrorType<TMutation extends UseMutationResult<unknown, unknown, unknown>> =
|
|
56
|
+
TMutation extends UseMutationResult<unknown, infer TError, unknown> ? TError : never;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Extract variables type from UseMutationResult
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* ```typescript
|
|
63
|
+
* const mutation = useMutation({ mutationFn: createUser });
|
|
64
|
+
* type Variables = ExtractMutationVariables<typeof mutation>; // CreateUserVars
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
67
|
+
export type ExtractMutationVariables<TMutation extends UseMutationResult<unknown, unknown, unknown>> =
|
|
68
|
+
TMutation extends UseMutationResult<unknown, unknown, infer TVariables> ? TVariables : never;
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Extract data type from infinite query
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* ```typescript
|
|
75
|
+
* const result = useInfiniteQuery({ queryKey: ['posts'], queryFn: fetchPosts });
|
|
76
|
+
* type Posts = ExtractInfiniteDataType<typeof result>; // InfiniteData<PostsResponse>
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
79
|
+
export type ExtractInfiniteDataType<TQuery extends UseQueryResult<unknown, unknown>> =
|
|
80
|
+
TQuery extends UseQueryResult<infer TData, unknown> ? TData : never;
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Extract page data type from infinite query
|
|
84
|
+
*
|
|
85
|
+
* @example
|
|
86
|
+
* ```typescript
|
|
87
|
+
* const result = useInfiniteQuery({ queryKey: ['posts'], queryFn: fetchPosts });
|
|
88
|
+
* type Page = ExtractInfinitePageType<typeof result>; // PostsResponse
|
|
89
|
+
* ```
|
|
90
|
+
*/
|
|
91
|
+
export type ExtractInfinitePageType<TQuery> = TQuery extends {
|
|
92
|
+
data: { pages: infer TPages };
|
|
93
|
+
}
|
|
94
|
+
? TPages extends Array<infer TPage>
|
|
95
|
+
? TPage
|
|
96
|
+
: never
|
|
97
|
+
: never;
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Make specific keys required from a type
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* ```typescript
|
|
104
|
+
* type User = { id?: number; name: string; email?: string };
|
|
105
|
+
* type UserWithId = RequireKeys<User, 'id' | 'email'>;
|
|
106
|
+
* // { id: number; name: string; email: string }
|
|
107
|
+
* ```
|
|
108
|
+
*/
|
|
109
|
+
export type RequireKeys<T, K extends keyof T> = Omit<T, K> & Required<Pick<T, K>>;
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Make specific keys optional from a type
|
|
113
|
+
*
|
|
114
|
+
* @example
|
|
115
|
+
* ```typescript
|
|
116
|
+
* type User = { id: number; name: string; email: string };
|
|
117
|
+
* type PartialUser = OptionalKeys<User, 'id' | 'email'>;
|
|
118
|
+
* // { id?: number; name: string; email?: string }
|
|
119
|
+
* ```
|
|
120
|
+
*/
|
|
121
|
+
export type OptionalKeys<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Deep partial type
|
|
125
|
+
*
|
|
126
|
+
* @example
|
|
127
|
+
* ```typescript
|
|
128
|
+
* type User = { id: number; profile: { name: string; email: string } };
|
|
129
|
+
* type PartialUser = DeepPartial<User>;
|
|
130
|
+
* // { id?: number; profile?: { name?: string; email?: string } }
|
|
131
|
+
* ```
|
|
132
|
+
*/
|
|
133
|
+
export type DeepPartial<T> = T extends object
|
|
134
|
+
? {
|
|
135
|
+
[K in keyof T]?: DeepPartial<T[K]>;
|
|
136
|
+
}
|
|
137
|
+
: T;
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Deep required type
|
|
141
|
+
*
|
|
142
|
+
* @example
|
|
143
|
+
* ```typescript
|
|
144
|
+
* type User = { id?: number; profile?: { name?: string; email?: string } };
|
|
145
|
+
* type RequiredUser = DeepRequired<User>;
|
|
146
|
+
* // { id: number; profile: { name: string; email: string } }
|
|
147
|
+
* ```
|
|
148
|
+
*/
|
|
149
|
+
export type DeepRequired<T> = T extends object
|
|
150
|
+
? {
|
|
151
|
+
[K in keyof T]-?: DeepRequired<T[K]>;
|
|
152
|
+
}
|
|
153
|
+
: T;
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @umituz/react-native-tanstack
|
|
3
|
+
* TanStack Query configuration and utilities for React Native apps
|
|
4
|
+
*
|
|
5
|
+
* General-purpose package for hundreds of React Native apps
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// Domain - Constants
|
|
9
|
+
export {
|
|
10
|
+
TIME_MS as QUERY_TIME_MS,
|
|
11
|
+
DEFAULT_STALE_TIME,
|
|
12
|
+
DEFAULT_GC_TIME,
|
|
13
|
+
DEFAULT_RETRY,
|
|
14
|
+
DEFAULT_REFETCH_INTERVAL,
|
|
15
|
+
} from './domain/constants/CacheDefaults';
|
|
16
|
+
|
|
17
|
+
// Domain - Types
|
|
18
|
+
export {
|
|
19
|
+
CacheStrategyType,
|
|
20
|
+
type CacheConfig as QueryCacheConfig,
|
|
21
|
+
type QueryConfig,
|
|
22
|
+
type MutationConfig,
|
|
23
|
+
} from './domain/types/CacheStrategy';
|
|
24
|
+
|
|
25
|
+
// Domain - Utils
|
|
26
|
+
export {
|
|
27
|
+
createQueryKeyFactory,
|
|
28
|
+
createPaginatedQueryKey,
|
|
29
|
+
createInfiniteQueryKey,
|
|
30
|
+
createScopedQueryKey,
|
|
31
|
+
matchQueryKey,
|
|
32
|
+
} from './domain/utils/QueryKeyFactory';
|
|
33
|
+
|
|
34
|
+
// Domain - Type Utilities
|
|
35
|
+
export type {
|
|
36
|
+
ExtractQueryDataType,
|
|
37
|
+
ExtractQueryErrorType,
|
|
38
|
+
ExtractMutationDataType,
|
|
39
|
+
ExtractMutationErrorType,
|
|
40
|
+
ExtractMutationVariables,
|
|
41
|
+
ExtractInfiniteDataType,
|
|
42
|
+
ExtractInfinitePageType,
|
|
43
|
+
RequireKeys,
|
|
44
|
+
OptionalKeys,
|
|
45
|
+
DeepPartial,
|
|
46
|
+
DeepRequired,
|
|
47
|
+
} from './domain/utils/TypeUtilities';
|
|
48
|
+
|
|
49
|
+
// Domain - Error Helpers
|
|
50
|
+
export {
|
|
51
|
+
isQueryError,
|
|
52
|
+
isMutationError,
|
|
53
|
+
isNetworkError,
|
|
54
|
+
isAbortError,
|
|
55
|
+
getErrorMessage,
|
|
56
|
+
getUserFriendlyMessage,
|
|
57
|
+
parseErrorResponse,
|
|
58
|
+
getValidationErrors,
|
|
59
|
+
getErrorCode,
|
|
60
|
+
logError,
|
|
61
|
+
type ErrorResponse,
|
|
62
|
+
} from './domain/utils/ErrorHelpers';
|
|
63
|
+
|
|
64
|
+
// Domain - Repositories
|
|
65
|
+
export {
|
|
66
|
+
BaseRepository,
|
|
67
|
+
type CreateParams,
|
|
68
|
+
type UpdateParams,
|
|
69
|
+
type ListParams,
|
|
70
|
+
type RepositoryOptions,
|
|
71
|
+
} from './domain/repositories/BaseRepository';
|
|
72
|
+
|
|
73
|
+
export { RepositoryFactory } from './domain/repositories/RepositoryFactory';
|
|
74
|
+
|
|
75
|
+
// Infrastructure - Config
|
|
76
|
+
export {
|
|
77
|
+
CacheStrategies,
|
|
78
|
+
createQueryClient,
|
|
79
|
+
getCacheStrategy,
|
|
80
|
+
type QueryClientFactoryOptions,
|
|
81
|
+
} from './infrastructure/config/QueryClientConfig';
|
|
82
|
+
|
|
83
|
+
export {
|
|
84
|
+
createPersister,
|
|
85
|
+
clearPersistedCache,
|
|
86
|
+
getPersistedCacheSize,
|
|
87
|
+
type PersisterFactoryOptions,
|
|
88
|
+
} from './infrastructure/config/PersisterConfig';
|
|
89
|
+
|
|
90
|
+
export {
|
|
91
|
+
getGlobalQueryClient,
|
|
92
|
+
hasGlobalQueryClient,
|
|
93
|
+
setGlobalQueryClient,
|
|
94
|
+
clearGlobalQueryClient,
|
|
95
|
+
} from './infrastructure/config/QueryClientSingleton';
|
|
96
|
+
|
|
97
|
+
// Infrastructure - Monitoring
|
|
98
|
+
export {
|
|
99
|
+
DevMonitor,
|
|
100
|
+
type QueryMetrics,
|
|
101
|
+
type CacheStats as QueryCacheStats,
|
|
102
|
+
type DevMonitorOptions,
|
|
103
|
+
} from './infrastructure/monitoring/DevMonitor';
|
|
104
|
+
|
|
105
|
+
// Infrastructure - Providers
|
|
106
|
+
export { TanstackProvider, type TanstackProviderProps } from './infrastructure/providers/TanstackProvider';
|
|
107
|
+
|
|
108
|
+
// Presentation - Hooks
|
|
109
|
+
export {
|
|
110
|
+
useInvalidateQueries,
|
|
111
|
+
useInvalidateMultipleQueries,
|
|
112
|
+
useRemoveQueries,
|
|
113
|
+
useResetQueries,
|
|
114
|
+
} from './presentation/hooks/useInvalidateQueries';
|
|
115
|
+
|
|
116
|
+
export {
|
|
117
|
+
useCursorPagination,
|
|
118
|
+
useOffsetPagination,
|
|
119
|
+
type CursorPageParam,
|
|
120
|
+
type OffsetPageParam,
|
|
121
|
+
type CursorPaginatedResponse,
|
|
122
|
+
type OffsetPaginatedResponse,
|
|
123
|
+
} from './presentation/hooks/usePaginatedQuery';
|
|
124
|
+
|
|
125
|
+
export {
|
|
126
|
+
useOptimisticUpdate,
|
|
127
|
+
useOptimisticListUpdate,
|
|
128
|
+
type OptimisticUpdateConfig,
|
|
129
|
+
} from './presentation/hooks/useOptimisticUpdate';
|
|
130
|
+
|
|
131
|
+
export {
|
|
132
|
+
usePrefetchQuery,
|
|
133
|
+
usePrefetchInfiniteQuery,
|
|
134
|
+
usePrefetchOnMount,
|
|
135
|
+
usePrefetchMultiple,
|
|
136
|
+
type PrefetchOptions,
|
|
137
|
+
} from './presentation/hooks/usePrefetch';
|
|
138
|
+
|
|
139
|
+
// Presentation - Utils
|
|
140
|
+
export {
|
|
141
|
+
createConditionalRetry,
|
|
142
|
+
createQuotaAwareRetry,
|
|
143
|
+
type RetryFunction,
|
|
144
|
+
type ErrorChecker,
|
|
145
|
+
} from './presentation/utils/RetryHelpers';
|
|
146
|
+
|
|
147
|
+
// Re-export TanStack Query core for convenience
|
|
148
|
+
export {
|
|
149
|
+
useQuery,
|
|
150
|
+
useMutation,
|
|
151
|
+
useInfiniteQuery,
|
|
152
|
+
useQueryClient,
|
|
153
|
+
useIsFetching,
|
|
154
|
+
useIsMutating,
|
|
155
|
+
type UseQueryResult,
|
|
156
|
+
type UseMutationResult,
|
|
157
|
+
type UseInfiniteQueryResult,
|
|
158
|
+
type InfiniteData,
|
|
159
|
+
type QueryKey,
|
|
160
|
+
type QueryClient,
|
|
161
|
+
} from '@tanstack/react-query';
|