@veloxts/client 0.4.1 → 0.4.3

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.
@@ -0,0 +1,162 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ /**
3
+ * VeloxProvider - React context provider for VeloxTS client
4
+ *
5
+ * Wraps your React application to provide access to the VeloxTS client
6
+ * and React Query's QueryClient.
7
+ *
8
+ * @module @veloxts/client/react/provider
9
+ */
10
+ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
11
+ import { createContext, useContext, useMemo } from 'react';
12
+ import { createClient } from '../client.js';
13
+ // ============================================================================
14
+ // Context
15
+ // ============================================================================
16
+ /**
17
+ * Internal context for VeloxTS client
18
+ *
19
+ * Typed as `unknown` at creation time since the router type
20
+ * is provided by the consumer via generic parameter.
21
+ */
22
+ const VeloxContext = createContext(null);
23
+ // ============================================================================
24
+ // Default QueryClient
25
+ // ============================================================================
26
+ /**
27
+ * Creates a default QueryClient with sensible defaults for VeloxTS
28
+ */
29
+ function createDefaultQueryClient() {
30
+ return new QueryClient({
31
+ defaultOptions: {
32
+ queries: {
33
+ staleTime: 30_000, // 30 seconds
34
+ retry: 1,
35
+ refetchOnWindowFocus: false,
36
+ },
37
+ mutations: {
38
+ retry: 0,
39
+ },
40
+ },
41
+ });
42
+ }
43
+ // ============================================================================
44
+ // Provider Component
45
+ // ============================================================================
46
+ /**
47
+ * Provider component that sets up VeloxTS client and React Query
48
+ *
49
+ * This provider:
50
+ * - Creates a memoized VeloxTS client instance from the provided config
51
+ * - Sets up React Query's QueryClientProvider
52
+ * - Makes the client available to hooks via React context
53
+ *
54
+ * @template TRouter - The router type defining your procedure collections
55
+ *
56
+ * @example Basic usage
57
+ * ```tsx
58
+ * import { VeloxProvider } from '@veloxts/client/react';
59
+ * import type { userProcedures, postProcedures } from './server/procedures';
60
+ *
61
+ * type AppRouter = {
62
+ * users: typeof userProcedures;
63
+ * posts: typeof postProcedures;
64
+ * };
65
+ *
66
+ * function App() {
67
+ * return (
68
+ * <VeloxProvider<AppRouter> config={{ baseUrl: '/api' }}>
69
+ * <YourApp />
70
+ * </VeloxProvider>
71
+ * );
72
+ * }
73
+ * ```
74
+ *
75
+ * @example With custom QueryClient
76
+ * ```tsx
77
+ * import { QueryClient } from '@tanstack/react-query';
78
+ *
79
+ * const queryClient = new QueryClient({
80
+ * defaultOptions: {
81
+ * queries: { staleTime: 60_000 },
82
+ * },
83
+ * });
84
+ *
85
+ * function App() {
86
+ * return (
87
+ * <VeloxProvider<AppRouter>
88
+ * config={{ baseUrl: '/api' }}
89
+ * queryClient={queryClient}
90
+ * >
91
+ * <YourApp />
92
+ * </VeloxProvider>
93
+ * );
94
+ * }
95
+ * ```
96
+ *
97
+ * @example With custom headers
98
+ * ```tsx
99
+ * function App() {
100
+ * const token = useAuthToken();
101
+ *
102
+ * const config = useMemo(() => ({
103
+ * baseUrl: '/api',
104
+ * headers: {
105
+ * Authorization: `Bearer ${token}`,
106
+ * },
107
+ * }), [token]);
108
+ *
109
+ * return (
110
+ * <VeloxProvider<AppRouter> config={config}>
111
+ * <YourApp />
112
+ * </VeloxProvider>
113
+ * );
114
+ * }
115
+ * ```
116
+ */
117
+ export function VeloxProvider({ children, config, queryClient: providedQueryClient, }) {
118
+ // Create client instance, memoized based on config reference
119
+ // Users should memoize their config object if they need to prevent re-renders
120
+ const client = useMemo(() => createClient(config), [config]);
121
+ // Use provided QueryClient or create default
122
+ // Only create once to avoid query state loss
123
+ const queryClient = useMemo(() => providedQueryClient ?? createDefaultQueryClient(), [providedQueryClient]);
124
+ // Memoize context value to prevent unnecessary re-renders
125
+ const contextValue = useMemo(() => ({ client }), [client]);
126
+ return (_jsx(VeloxContext.Provider, { value: contextValue, children: _jsx(QueryClientProvider, { client: queryClient, children: children }) }));
127
+ }
128
+ // ============================================================================
129
+ // Context Hook
130
+ // ============================================================================
131
+ /**
132
+ * Hook to access VeloxTS client from context
133
+ *
134
+ * This is primarily used internally by useQuery and useMutation hooks,
135
+ * but can also be used directly for advanced use cases.
136
+ *
137
+ * @template TRouter - The router type for type-safe client access
138
+ * @returns The context value containing the typed client
139
+ * @throws Error if used outside of VeloxProvider
140
+ *
141
+ * @example Direct client access (advanced)
142
+ * ```tsx
143
+ * function MyComponent() {
144
+ * const { client } = useVeloxContext<AppRouter>();
145
+ *
146
+ * // Direct client access for edge cases
147
+ * const handleClick = async () => {
148
+ * const user = await client.users.getUser({ id: '123' });
149
+ * console.log(user);
150
+ * };
151
+ * }
152
+ * ```
153
+ */
154
+ export function useVeloxContext() {
155
+ const context = useContext(VeloxContext);
156
+ if (!context) {
157
+ throw new Error('useVeloxContext must be used within a VeloxProvider. ' +
158
+ 'Wrap your component tree with <VeloxProvider config={{...}}>.');
159
+ }
160
+ return context;
161
+ }
162
+ //# sourceMappingURL=provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.js","sourceRoot":"","sources":["../../src/react/provider.tsx"],"names":[],"mappings":";AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AACzE,OAAO,EAAE,aAAa,EAAkB,UAAU,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAE3E,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAG5C,+EAA+E;AAC/E,UAAU;AACV,+EAA+E;AAE/E;;;;;GAKG;AACH,MAAM,YAAY,GAAG,aAAa,CAAoC,IAAI,CAAC,CAAC;AAE5E,+EAA+E;AAC/E,sBAAsB;AACtB,+EAA+E;AAE/E;;GAEG;AACH,SAAS,wBAAwB;IAC/B,OAAO,IAAI,WAAW,CAAC;QACrB,cAAc,EAAE;YACd,OAAO,EAAE;gBACP,SAAS,EAAE,MAAM,EAAE,aAAa;gBAChC,KAAK,EAAE,CAAC;gBACR,oBAAoB,EAAE,KAAK;aAC5B;YACD,SAAS,EAAE;gBACT,KAAK,EAAE,CAAC;aACT;SACF;KACF,CAAC,CAAC;AACL,CAAC;AAED,+EAA+E;AAC/E,qBAAqB;AACrB,+EAA+E;AAE/E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsEG;AACH,MAAM,UAAU,aAAa,CAAU,EACrC,QAAQ,EACR,MAAM,EACN,WAAW,EAAE,mBAAmB,GACJ;IAC5B,6DAA6D;IAC7D,8EAA8E;IAC9E,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,YAAY,CAAU,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;IAEtE,6CAA6C;IAC7C,6CAA6C;IAC7C,MAAM,WAAW,GAAG,OAAO,CACzB,GAAG,EAAE,CAAC,mBAAmB,IAAI,wBAAwB,EAAE,EACvD,CAAC,mBAAmB,CAAC,CACtB,CAAC;IAEF,0DAA0D;IAC1D,MAAM,YAAY,GAAG,OAAO,CAA6B,GAAG,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;IAEvF,OAAO,CACL,KAAC,YAAY,CAAC,QAAQ,IAAC,KAAK,EAAE,YAA0C,YACtE,KAAC,mBAAmB,IAAC,MAAM,EAAE,WAAW,YAAG,QAAQ,GAAuB,GACpD,CACzB,CAAC;AACJ,CAAC;AAED,+EAA+E;AAC/E,eAAe;AACf,+EAA+E;AAE/E;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,UAAU,eAAe;IAC7B,MAAM,OAAO,GAAG,UAAU,CAAC,YAAY,CAAC,CAAC;IAEzC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CACb,uDAAuD;YACrD,+DAA+D,CAClE,CAAC;IACJ,CAAC;IAED,OAAO,OAAqC,CAAC;AAC/C,CAAC"}
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Type definitions for React hooks integration
3
+ *
4
+ * Provides type utilities for building type-safe React Query hooks
5
+ * that work with VeloxTS procedure definitions.
6
+ *
7
+ * @module @veloxts/client/react/types
8
+ */
9
+ import type { UseMutationOptions, UseQueryOptions } from '@tanstack/react-query';
10
+ import type { ClientConfig, ClientFromRouter, InferProcedureInput, InferProcedureOutput, ProcedureCollection } from '../types.js';
11
+ /**
12
+ * Extracts a specific procedure from the router type
13
+ *
14
+ * Enables type inference for procedure input/output in hooks.
15
+ *
16
+ * @template TRouter - The router type (collection of procedure collections)
17
+ * @template TNamespace - The namespace key (e.g., 'users', 'posts')
18
+ * @template TProcedureName - The procedure name (e.g., 'getUser', 'listUsers')
19
+ */
20
+ export type GetProcedure<TRouter, TNamespace extends keyof TRouter, TProcedureName extends keyof GetProceduresFromCollection<TRouter[TNamespace]>> = TRouter[TNamespace] extends ProcedureCollection<infer TProcedures> ? TProcedureName extends keyof TProcedures ? TProcedures[TProcedureName] : never : never;
21
+ /**
22
+ * Extracts the procedures record from a collection
23
+ *
24
+ * @template TCollection - The procedure collection type
25
+ */
26
+ export type GetProceduresFromCollection<TCollection> = TCollection extends ProcedureCollection ? TCollection['procedures'] : never;
27
+ /**
28
+ * Options for useQuery hook
29
+ *
30
+ * Omits queryKey and queryFn since those are provided automatically
31
+ * based on the procedure namespace, name, and input.
32
+ *
33
+ * @template TData - The expected response data type
34
+ * @template TError - The error type (defaults to Error)
35
+ */
36
+ export type VeloxUseQueryOptions<TData, TError = Error> = Omit<UseQueryOptions<TData, TError>, 'queryKey' | 'queryFn'>;
37
+ /**
38
+ * Options for useMutation hook
39
+ *
40
+ * Omits mutationFn since that's provided automatically
41
+ * based on the procedure namespace and name.
42
+ *
43
+ * @template TData - The expected response data type
44
+ * @template TInput - The mutation input type
45
+ * @template TError - The error type (defaults to Error)
46
+ * @template TContext - The mutation context type
47
+ */
48
+ export type VeloxUseMutationOptions<TData, TInput, TError = Error, TContext = unknown> = Omit<UseMutationOptions<TData, TError, TInput, TContext>, 'mutationFn'>;
49
+ /**
50
+ * Query key structure for VeloxTS
51
+ *
52
+ * Format: [namespace, procedureName, input?]
53
+ *
54
+ * This structure enables:
55
+ * - Invalidating all queries for a namespace: `['users']`
56
+ * - Invalidating a specific procedure: `['users', 'getUser']`
57
+ * - Invalidating a specific query: `['users', 'getUser', { id: '123' }]`
58
+ */
59
+ export type VeloxQueryKey = readonly [string, string] | readonly [string, string, Record<string, unknown>];
60
+ /**
61
+ * Context value provided by VeloxProvider
62
+ *
63
+ * @template TRouter - The router type for type-safe client access
64
+ */
65
+ export interface VeloxContextValue<TRouter> {
66
+ /** The typed client instance */
67
+ readonly client: ClientFromRouter<TRouter>;
68
+ }
69
+ /**
70
+ * Props for VeloxProvider component
71
+ *
72
+ * @template _TRouter - The router type for type-safe client configuration (used for generic inference)
73
+ */
74
+ export interface VeloxProviderProps<_TRouter> {
75
+ /** React children to render within the provider */
76
+ readonly children: React.ReactNode;
77
+ /** Client configuration (baseUrl, headers, etc.) */
78
+ readonly config: ClientConfig;
79
+ /** Optional pre-configured QueryClient instance */
80
+ readonly queryClient?: import('@tanstack/react-query').QueryClient;
81
+ }
82
+ export type { InferProcedureInput, InferProcedureOutput, ProcedureCollection, ClientConfig, ClientFromRouter, };
83
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/react/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAEjF,OAAO,KAAK,EACV,YAAY,EACZ,gBAAgB,EAChB,mBAAmB,EACnB,oBAAoB,EACpB,mBAAmB,EACpB,MAAM,aAAa,CAAC;AAMrB;;;;;;;;GAQG;AACH,MAAM,MAAM,YAAY,CACtB,OAAO,EACP,UAAU,SAAS,MAAM,OAAO,EAChC,cAAc,SAAS,MAAM,2BAA2B,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,IAC3E,OAAO,CAAC,UAAU,CAAC,SAAS,mBAAmB,CAAC,MAAM,WAAW,CAAC,GAClE,cAAc,SAAS,MAAM,WAAW,GACtC,WAAW,CAAC,cAAc,CAAC,GAC3B,KAAK,GACP,KAAK,CAAC;AAEV;;;;GAIG;AACH,MAAM,MAAM,2BAA2B,CAAC,WAAW,IAAI,WAAW,SAAS,mBAAmB,GAC1F,WAAW,CAAC,YAAY,CAAC,GACzB,KAAK,CAAC;AAMV;;;;;;;;GAQG;AACH,MAAM,MAAM,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,IAAI,CAC5D,eAAe,CAAC,KAAK,EAAE,MAAM,CAAC,EAC9B,UAAU,GAAG,SAAS,CACvB,CAAC;AAEF;;;;;;;;;;GAUG;AACH,MAAM,MAAM,uBAAuB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,GAAG,KAAK,EAAE,QAAQ,GAAG,OAAO,IAAI,IAAI,CAC3F,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EACnD,YAAY,CACb,CAAC;AAMF;;;;;;;;;GASG;AACH,MAAM,MAAM,aAAa,GACrB,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,GACzB,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAMvD;;;;GAIG;AACH,MAAM,WAAW,iBAAiB,CAAC,OAAO;IACxC,gCAAgC;IAChC,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAC;CAC5C;AAED;;;;GAIG;AAEH,MAAM,WAAW,kBAAkB,CAAC,QAAQ;IAC1C,mDAAmD;IACnD,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IACnC,oDAAoD;IACpD,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAC9B,mDAAmD;IACnD,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,uBAAuB,EAAE,WAAW,CAAC;CACpE;AAMD,YAAY,EACV,mBAAmB,EACnB,oBAAoB,EACpB,mBAAmB,EACnB,YAAY,EACZ,gBAAgB,GACjB,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Type definitions for React hooks integration
3
+ *
4
+ * Provides type utilities for building type-safe React Query hooks
5
+ * that work with VeloxTS procedure definitions.
6
+ *
7
+ * @module @veloxts/client/react/types
8
+ */
9
+ export {};
10
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/react/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG"}
@@ -0,0 +1,151 @@
1
+ /**
2
+ * Utility functions for React Query integration
3
+ *
4
+ * Provides query key builders and cache invalidation helpers
5
+ * for consistent and predictable caching behavior.
6
+ *
7
+ * @module @veloxts/client/react/utils
8
+ */
9
+ import type { QueryClient } from '@tanstack/react-query';
10
+ import type { VeloxQueryKey } from './types.js';
11
+ /**
12
+ * Builds a stable query key for React Query
13
+ *
14
+ * Query keys are structured as: [namespace, procedureName, input?]
15
+ * This enables efficient cache invalidation by namespace or procedure.
16
+ *
17
+ * The key structure follows React Query best practices:
18
+ * - Keys are arrays for hierarchical invalidation
19
+ * - Input is serialized for stable identity
20
+ *
21
+ * @param namespace - The procedure namespace (e.g., 'users')
22
+ * @param procedureName - The procedure name (e.g., 'getUser')
23
+ * @param input - Optional input parameters
24
+ * @returns A stable query key array
25
+ *
26
+ * @example
27
+ * ```typescript
28
+ * // Query with no input
29
+ * buildQueryKey('health', 'check');
30
+ * // => ['health', 'check']
31
+ *
32
+ * // Query with object input
33
+ * buildQueryKey('users', 'getUser', { id: '123' });
34
+ * // => ['users', 'getUser', { id: '123' }]
35
+ *
36
+ * // Query with primitive input (wrapped)
37
+ * buildQueryKey('users', 'getCount', 10);
38
+ * // => ['users', 'getCount', { value: 10 }]
39
+ * ```
40
+ */
41
+ export declare function buildQueryKey(namespace: string, procedureName: string, input?: unknown): VeloxQueryKey;
42
+ /**
43
+ * Invalidates all queries for a namespace
44
+ *
45
+ * This is useful after mutations that may affect multiple resources
46
+ * within the same namespace.
47
+ *
48
+ * @param queryClient - The React Query client instance
49
+ * @param namespace - The namespace to invalidate (e.g., 'users')
50
+ *
51
+ * @example
52
+ * ```typescript
53
+ * const queryClient = useQueryClient();
54
+ *
55
+ * // After deleting a user, invalidate all user queries
56
+ * await invalidateNamespace(queryClient, 'users');
57
+ * ```
58
+ */
59
+ export declare function invalidateNamespace(queryClient: QueryClient, namespace: string): Promise<void>;
60
+ /**
61
+ * Invalidates all queries for a specific procedure
62
+ *
63
+ * This is useful when you want to refetch all instances of a specific
64
+ * query without affecting other queries in the same namespace.
65
+ *
66
+ * @param queryClient - The React Query client instance
67
+ * @param namespace - The procedure namespace (e.g., 'users')
68
+ * @param procedureName - The procedure name (e.g., 'getUser')
69
+ *
70
+ * @example
71
+ * ```typescript
72
+ * const queryClient = useQueryClient();
73
+ *
74
+ * // After updating a user, invalidate all getUser queries
75
+ * await invalidateProcedure(queryClient, 'users', 'getUser');
76
+ * ```
77
+ */
78
+ export declare function invalidateProcedure(queryClient: QueryClient, namespace: string, procedureName: string): Promise<void>;
79
+ /**
80
+ * Invalidates a specific query by its exact key
81
+ *
82
+ * This is useful when you know the exact input and want to invalidate
83
+ * only that specific cached query.
84
+ *
85
+ * @param queryClient - The React Query client instance
86
+ * @param namespace - The procedure namespace (e.g., 'users')
87
+ * @param procedureName - The procedure name (e.g., 'getUser')
88
+ * @param input - The exact input used in the query
89
+ *
90
+ * @example
91
+ * ```typescript
92
+ * const queryClient = useQueryClient();
93
+ *
94
+ * // After updating user 123, invalidate only that specific query
95
+ * await invalidateQuery(queryClient, 'users', 'getUser', { id: '123' });
96
+ * ```
97
+ */
98
+ export declare function invalidateQuery(queryClient: QueryClient, namespace: string, procedureName: string, input?: unknown): Promise<void>;
99
+ /**
100
+ * Gets cached data for a specific query
101
+ *
102
+ * Useful for optimistic updates where you need the current cached value.
103
+ *
104
+ * @param queryClient - The React Query client instance
105
+ * @param namespace - The procedure namespace
106
+ * @param procedureName - The procedure name
107
+ * @param input - The query input
108
+ * @returns The cached data or undefined if not cached
109
+ *
110
+ * @example
111
+ * ```typescript
112
+ * const queryClient = useQueryClient();
113
+ *
114
+ * // Get current cached user before optimistic update
115
+ * const previousUser = getQueryData<User>(
116
+ * queryClient,
117
+ * 'users',
118
+ * 'getUser',
119
+ * { id: '123' }
120
+ * );
121
+ * ```
122
+ */
123
+ export declare function getQueryData<TData>(queryClient: QueryClient, namespace: string, procedureName: string, input?: unknown): TData | undefined;
124
+ /**
125
+ * Sets cached data for a specific query
126
+ *
127
+ * Useful for optimistic updates where you want to update the cache
128
+ * immediately before the mutation completes.
129
+ *
130
+ * @param queryClient - The React Query client instance
131
+ * @param namespace - The procedure namespace
132
+ * @param procedureName - The procedure name
133
+ * @param input - The query input
134
+ * @param data - The data to cache
135
+ *
136
+ * @example
137
+ * ```typescript
138
+ * const queryClient = useQueryClient();
139
+ *
140
+ * // Optimistically update user in cache
141
+ * setQueryData<User>(
142
+ * queryClient,
143
+ * 'users',
144
+ * 'getUser',
145
+ * { id: '123' },
146
+ * { ...previousUser, name: 'New Name' }
147
+ * );
148
+ * ```
149
+ */
150
+ export declare function setQueryData<TData>(queryClient: QueryClient, namespace: string, procedureName: string, input: unknown, data: TData): void;
151
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/react/utils.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAEzD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAMhD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,aAAa,CAC3B,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,MAAM,EACrB,KAAK,CAAC,EAAE,OAAO,GACd,aAAa,CAYf;AAMD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,mBAAmB,CACvC,WAAW,EAAE,WAAW,EACxB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CAEf;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,mBAAmB,CACvC,WAAW,EAAE,WAAW,EACxB,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,IAAI,CAAC,CAEf;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,eAAe,CACnC,WAAW,EAAE,WAAW,EACxB,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,MAAM,EACrB,KAAK,CAAC,EAAE,OAAO,GACd,OAAO,CAAC,IAAI,CAAC,CAGf;AAMD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAChC,WAAW,EAAE,WAAW,EACxB,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,MAAM,EACrB,KAAK,CAAC,EAAE,OAAO,GACd,KAAK,GAAG,SAAS,CAGnB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAChC,WAAW,EAAE,WAAW,EACxB,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,MAAM,EACrB,KAAK,EAAE,OAAO,EACd,IAAI,EAAE,KAAK,GACV,IAAI,CAGN"}
@@ -0,0 +1,181 @@
1
+ /**
2
+ * Utility functions for React Query integration
3
+ *
4
+ * Provides query key builders and cache invalidation helpers
5
+ * for consistent and predictable caching behavior.
6
+ *
7
+ * @module @veloxts/client/react/utils
8
+ */
9
+ // ============================================================================
10
+ // Query Key Builders
11
+ // ============================================================================
12
+ /**
13
+ * Builds a stable query key for React Query
14
+ *
15
+ * Query keys are structured as: [namespace, procedureName, input?]
16
+ * This enables efficient cache invalidation by namespace or procedure.
17
+ *
18
+ * The key structure follows React Query best practices:
19
+ * - Keys are arrays for hierarchical invalidation
20
+ * - Input is serialized for stable identity
21
+ *
22
+ * @param namespace - The procedure namespace (e.g., 'users')
23
+ * @param procedureName - The procedure name (e.g., 'getUser')
24
+ * @param input - Optional input parameters
25
+ * @returns A stable query key array
26
+ *
27
+ * @example
28
+ * ```typescript
29
+ * // Query with no input
30
+ * buildQueryKey('health', 'check');
31
+ * // => ['health', 'check']
32
+ *
33
+ * // Query with object input
34
+ * buildQueryKey('users', 'getUser', { id: '123' });
35
+ * // => ['users', 'getUser', { id: '123' }]
36
+ *
37
+ * // Query with primitive input (wrapped)
38
+ * buildQueryKey('users', 'getCount', 10);
39
+ * // => ['users', 'getCount', { value: 10 }]
40
+ * ```
41
+ */
42
+ export function buildQueryKey(namespace, procedureName, input) {
43
+ if (input === undefined || input === null) {
44
+ return [namespace, procedureName];
45
+ }
46
+ // For objects, include directly in key for proper caching
47
+ if (typeof input === 'object') {
48
+ return [namespace, procedureName, input];
49
+ }
50
+ // For primitives, wrap in object to maintain consistent key structure
51
+ return [namespace, procedureName, { value: input }];
52
+ }
53
+ // ============================================================================
54
+ // Cache Invalidation Helpers
55
+ // ============================================================================
56
+ /**
57
+ * Invalidates all queries for a namespace
58
+ *
59
+ * This is useful after mutations that may affect multiple resources
60
+ * within the same namespace.
61
+ *
62
+ * @param queryClient - The React Query client instance
63
+ * @param namespace - The namespace to invalidate (e.g., 'users')
64
+ *
65
+ * @example
66
+ * ```typescript
67
+ * const queryClient = useQueryClient();
68
+ *
69
+ * // After deleting a user, invalidate all user queries
70
+ * await invalidateNamespace(queryClient, 'users');
71
+ * ```
72
+ */
73
+ export async function invalidateNamespace(queryClient, namespace) {
74
+ await queryClient.invalidateQueries({ queryKey: [namespace] });
75
+ }
76
+ /**
77
+ * Invalidates all queries for a specific procedure
78
+ *
79
+ * This is useful when you want to refetch all instances of a specific
80
+ * query without affecting other queries in the same namespace.
81
+ *
82
+ * @param queryClient - The React Query client instance
83
+ * @param namespace - The procedure namespace (e.g., 'users')
84
+ * @param procedureName - The procedure name (e.g., 'getUser')
85
+ *
86
+ * @example
87
+ * ```typescript
88
+ * const queryClient = useQueryClient();
89
+ *
90
+ * // After updating a user, invalidate all getUser queries
91
+ * await invalidateProcedure(queryClient, 'users', 'getUser');
92
+ * ```
93
+ */
94
+ export async function invalidateProcedure(queryClient, namespace, procedureName) {
95
+ await queryClient.invalidateQueries({ queryKey: [namespace, procedureName] });
96
+ }
97
+ /**
98
+ * Invalidates a specific query by its exact key
99
+ *
100
+ * This is useful when you know the exact input and want to invalidate
101
+ * only that specific cached query.
102
+ *
103
+ * @param queryClient - The React Query client instance
104
+ * @param namespace - The procedure namespace (e.g., 'users')
105
+ * @param procedureName - The procedure name (e.g., 'getUser')
106
+ * @param input - The exact input used in the query
107
+ *
108
+ * @example
109
+ * ```typescript
110
+ * const queryClient = useQueryClient();
111
+ *
112
+ * // After updating user 123, invalidate only that specific query
113
+ * await invalidateQuery(queryClient, 'users', 'getUser', { id: '123' });
114
+ * ```
115
+ */
116
+ export async function invalidateQuery(queryClient, namespace, procedureName, input) {
117
+ const queryKey = buildQueryKey(namespace, procedureName, input);
118
+ await queryClient.invalidateQueries({ queryKey });
119
+ }
120
+ // ============================================================================
121
+ // Cache Data Accessors
122
+ // ============================================================================
123
+ /**
124
+ * Gets cached data for a specific query
125
+ *
126
+ * Useful for optimistic updates where you need the current cached value.
127
+ *
128
+ * @param queryClient - The React Query client instance
129
+ * @param namespace - The procedure namespace
130
+ * @param procedureName - The procedure name
131
+ * @param input - The query input
132
+ * @returns The cached data or undefined if not cached
133
+ *
134
+ * @example
135
+ * ```typescript
136
+ * const queryClient = useQueryClient();
137
+ *
138
+ * // Get current cached user before optimistic update
139
+ * const previousUser = getQueryData<User>(
140
+ * queryClient,
141
+ * 'users',
142
+ * 'getUser',
143
+ * { id: '123' }
144
+ * );
145
+ * ```
146
+ */
147
+ export function getQueryData(queryClient, namespace, procedureName, input) {
148
+ const queryKey = buildQueryKey(namespace, procedureName, input);
149
+ return queryClient.getQueryData(queryKey);
150
+ }
151
+ /**
152
+ * Sets cached data for a specific query
153
+ *
154
+ * Useful for optimistic updates where you want to update the cache
155
+ * immediately before the mutation completes.
156
+ *
157
+ * @param queryClient - The React Query client instance
158
+ * @param namespace - The procedure namespace
159
+ * @param procedureName - The procedure name
160
+ * @param input - The query input
161
+ * @param data - The data to cache
162
+ *
163
+ * @example
164
+ * ```typescript
165
+ * const queryClient = useQueryClient();
166
+ *
167
+ * // Optimistically update user in cache
168
+ * setQueryData<User>(
169
+ * queryClient,
170
+ * 'users',
171
+ * 'getUser',
172
+ * { id: '123' },
173
+ * { ...previousUser, name: 'New Name' }
174
+ * );
175
+ * ```
176
+ */
177
+ export function setQueryData(queryClient, namespace, procedureName, input, data) {
178
+ const queryKey = buildQueryKey(namespace, procedureName, input);
179
+ queryClient.setQueryData(queryKey, data);
180
+ }
181
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/react/utils.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,+EAA+E;AAC/E,qBAAqB;AACrB,+EAA+E;AAE/E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,MAAM,UAAU,aAAa,CAC3B,SAAiB,EACjB,aAAqB,EACrB,KAAe;IAEf,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QAC1C,OAAO,CAAC,SAAS,EAAE,aAAa,CAAU,CAAC;IAC7C,CAAC;IAED,0DAA0D;IAC1D,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,CAAC,SAAS,EAAE,aAAa,EAAE,KAAgC,CAAU,CAAC;IAC/E,CAAC;IAED,sEAAsE;IACtE,OAAO,CAAC,SAAS,EAAE,aAAa,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAU,CAAC;AAC/D,CAAC;AAED,+EAA+E;AAC/E,6BAA6B;AAC7B,+EAA+E;AAE/E;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,WAAwB,EACxB,SAAiB;IAEjB,MAAM,WAAW,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;AACjE,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,WAAwB,EACxB,SAAiB,EACjB,aAAqB;IAErB,MAAM,WAAW,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,CAAC,SAAS,EAAE,aAAa,CAAC,EAAE,CAAC,CAAC;AAChF,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,WAAwB,EACxB,SAAiB,EACjB,aAAqB,EACrB,KAAe;IAEf,MAAM,QAAQ,GAAG,aAAa,CAAC,SAAS,EAAE,aAAa,EAAE,KAAK,CAAC,CAAC;IAChE,MAAM,WAAW,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC;AACpD,CAAC;AAED,+EAA+E;AAC/E,uBAAuB;AACvB,+EAA+E;AAE/E;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,UAAU,YAAY,CAC1B,WAAwB,EACxB,SAAiB,EACjB,aAAqB,EACrB,KAAe;IAEf,MAAM,QAAQ,GAAG,aAAa,CAAC,SAAS,EAAE,aAAa,EAAE,KAAK,CAAC,CAAC;IAChE,OAAO,WAAW,CAAC,YAAY,CAAQ,QAAQ,CAAC,CAAC;AACnD,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,UAAU,YAAY,CAC1B,WAAwB,EACxB,SAAiB,EACjB,aAAqB,EACrB,KAAc,EACd,IAAW;IAEX,MAAM,QAAQ,GAAG,aAAa,CAAC,SAAS,EAAE,aAAa,EAAE,KAAK,CAAC,CAAC;IAChE,WAAW,CAAC,YAAY,CAAQ,QAAQ,EAAE,IAAI,CAAC,CAAC;AAClD,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Test setup file for Vitest
3
+ *
4
+ * Sets up jest-dom matchers for React Testing Library
5
+ */
6
+ import '@testing-library/jest-dom/vitest';
7
+ //# sourceMappingURL=test-setup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-setup.d.ts","sourceRoot":"","sources":["../src/test-setup.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,kCAAkC,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Test setup file for Vitest
3
+ *
4
+ * Sets up jest-dom matchers for React Testing Library
5
+ */
6
+ import '@testing-library/jest-dom/vitest';
7
+ //# sourceMappingURL=test-setup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-setup.js","sourceRoot":"","sources":["../src/test-setup.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,kCAAkC,CAAC"}