@veloxts/client 0.4.8 → 0.4.9

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,396 @@
1
+ /**
2
+ * Proxy-based React hooks for VeloxTS
3
+ *
4
+ * Provides tRPC-style ergonomics with full IDE autocomplete
5
+ * by using TypeScript mapped types and JavaScript Proxy objects.
6
+ *
7
+ * @example
8
+ * ```tsx
9
+ * // Create hooks once at app level
10
+ * import { createVeloxHooks } from '@veloxts/client/react';
11
+ * import type { AppRouter } from './api-types';
12
+ *
13
+ * export const api = createVeloxHooks<AppRouter>();
14
+ *
15
+ * // Use in components with full autocomplete
16
+ * function UserProfile({ userId }: { userId: string }) {
17
+ * const queryClient = useQueryClient();
18
+ *
19
+ * const { data } = api.users.getUser.useQuery({ id: userId });
20
+ * const { mutate } = api.users.updateUser.useMutation({
21
+ * onSuccess: () => api.users.getUser.invalidate({ id: userId }, queryClient),
22
+ * });
23
+ * }
24
+ * ```
25
+ *
26
+ * @module @veloxts/client/react/proxy-hooks
27
+ */
28
+ import { useMutation as useReactMutation, useQuery as useReactQuery, useQueryClient as useReactQueryClient, useSuspenseQuery as useReactSuspenseQuery, } from '@tanstack/react-query';
29
+ import { useVeloxContext } from './provider.js';
30
+ import { buildQueryKey } from './utils.js';
31
+ // ============================================================================
32
+ // Query/Mutation Detection
33
+ // ============================================================================
34
+ /**
35
+ * Determines if a procedure is a query based on naming convention
36
+ *
37
+ * Matches the logic in @veloxts/router for consistency.
38
+ * Procedures starting with these prefixes are queries:
39
+ * - get* (e.g., getUser, getProfile)
40
+ * - list* (e.g., listUsers, listPosts)
41
+ * - find* (e.g., findUsers, findByEmail)
42
+ *
43
+ * Everything else is considered a mutation.
44
+ *
45
+ * @param procedureName - The procedure name to check
46
+ * @returns true if the procedure is a query, false for mutation
47
+ */
48
+ function isQueryProcedure(procedureName) {
49
+ const queryPrefixes = ['get', 'list', 'find'];
50
+ return queryPrefixes.some((prefix) => procedureName.startsWith(prefix));
51
+ }
52
+ /**
53
+ * Determines the mutation type from procedure name
54
+ * @internal
55
+ */
56
+ function getMutationType(procedureName) {
57
+ if (/^(?:create|add)/.test(procedureName))
58
+ return 'create';
59
+ if (/^(?:update|edit|patch)/.test(procedureName))
60
+ return 'update';
61
+ if (/^(?:delete|remove)/.test(procedureName))
62
+ return 'delete';
63
+ return 'unknown';
64
+ }
65
+ /**
66
+ * Extracts ID from mutation input for targeted invalidation
67
+ *
68
+ * Looks for common patterns:
69
+ * - `{ id }` - Direct id field
70
+ * - `{ userId }`, `{ postId }` - *Id pattern
71
+ * - `{ data: { id } }` - Nested in data object
72
+ *
73
+ * @internal
74
+ */
75
+ function extractIdFromInput(input) {
76
+ if (!input || typeof input !== 'object')
77
+ return null;
78
+ const obj = input;
79
+ // Direct id field
80
+ if (typeof obj.id === 'string')
81
+ return obj.id;
82
+ if (typeof obj.id === 'number')
83
+ return String(obj.id);
84
+ // *Id pattern (userId, postId, etc.)
85
+ for (const key of Object.keys(obj)) {
86
+ if (key.endsWith('Id') && (typeof obj[key] === 'string' || typeof obj[key] === 'number')) {
87
+ return String(obj[key]);
88
+ }
89
+ }
90
+ // Nested in data
91
+ if (obj.data && typeof obj.data === 'object') {
92
+ const data = obj.data;
93
+ if (typeof data.id === 'string')
94
+ return data.id;
95
+ if (typeof data.id === 'number')
96
+ return String(data.id);
97
+ }
98
+ return null;
99
+ }
100
+ /**
101
+ * Performs convention-based cache invalidation after mutation success
102
+ *
103
+ * Invalidation rules:
104
+ * - `create*`, `add*` → invalidates `list*`, `find*` queries
105
+ * - `update*`, `edit*`, `patch*` → invalidates `get*` (matching ID), `list*`, `find*`
106
+ * - `delete*`, `remove*` → invalidates `get*` (matching ID), `list*`, `find*`
107
+ *
108
+ * @internal
109
+ */
110
+ async function performAutoInvalidation(queryClient, namespace, procedureName, input, output, config) {
111
+ const mutationType = getMutationType(procedureName);
112
+ const exclude = config?.exclude ?? [];
113
+ // Get all queries in this namespace from the cache
114
+ const queries = queryClient.getQueryCache().findAll({ queryKey: [namespace] });
115
+ for (const query of queries) {
116
+ const queryKey = query.queryKey;
117
+ const queryProcName = queryKey[1];
118
+ // Skip if excluded
119
+ if (exclude.includes(queryProcName))
120
+ continue;
121
+ // Create/Update/Delete all invalidate list/find queries
122
+ if (/^(?:list|find)/.test(queryProcName)) {
123
+ await queryClient.invalidateQueries({ queryKey: [namespace, queryProcName] });
124
+ continue;
125
+ }
126
+ // Update/Delete also invalidate matching get queries
127
+ if (mutationType !== 'create' && /^get/.test(queryProcName)) {
128
+ const id = extractIdFromInput(input) ?? extractIdFromInput(output);
129
+ if (id) {
130
+ // Invalidate the specific query if it matches the ID
131
+ const queryInput = queryKey[2];
132
+ const queryId = queryInput ? extractIdFromInput(queryInput) : null;
133
+ if (queryId === id) {
134
+ await queryClient.invalidateQueries({ queryKey: query.queryKey });
135
+ }
136
+ }
137
+ }
138
+ }
139
+ // Handle additional invalidations from config
140
+ if (config?.additional) {
141
+ for (const [ns, proc, inp] of config.additional) {
142
+ const queryKey = inp !== undefined ? [ns, proc, inp] : [ns, proc];
143
+ await queryClient.invalidateQueries({ queryKey });
144
+ }
145
+ }
146
+ // Run custom invalidation handler if provided
147
+ if (config?.custom) {
148
+ const context = {
149
+ namespace,
150
+ procedureName,
151
+ input,
152
+ data: output,
153
+ queryClient,
154
+ invalidate: async (proc, inp) => {
155
+ const queryKey = inp !== undefined ? [namespace, proc, inp] : [namespace, proc];
156
+ await queryClient.invalidateQueries({ queryKey });
157
+ },
158
+ };
159
+ await config.custom(context);
160
+ }
161
+ }
162
+ // ============================================================================
163
+ // Procedure Proxy Creators
164
+ // ============================================================================
165
+ /**
166
+ * Creates a query procedure proxy with all hook methods
167
+ *
168
+ * @param namespace - The procedure namespace (e.g., 'users')
169
+ * @param procedureName - The procedure name (e.g., 'getUser')
170
+ * @param getClient - Factory function to get the client (called inside hooks)
171
+ */
172
+ function createQueryProcedureProxy(namespace, procedureName, getClient) {
173
+ return {
174
+ useQuery(input, options) {
175
+ const client = getClient();
176
+ const queryKey = buildQueryKey(namespace, procedureName, input);
177
+ return useReactQuery({
178
+ queryKey,
179
+ queryFn: async () => {
180
+ const namespaceClient = client[namespace];
181
+ const procedure = namespaceClient[procedureName];
182
+ return procedure(input);
183
+ },
184
+ ...options,
185
+ });
186
+ },
187
+ useSuspenseQuery(input, options) {
188
+ const client = getClient();
189
+ const queryKey = buildQueryKey(namespace, procedureName, input);
190
+ return useReactSuspenseQuery({
191
+ queryKey,
192
+ queryFn: async () => {
193
+ const namespaceClient = client[namespace];
194
+ const procedure = namespaceClient[procedureName];
195
+ return procedure(input);
196
+ },
197
+ ...options,
198
+ });
199
+ },
200
+ getQueryKey(input) {
201
+ return buildQueryKey(namespace, procedureName, input);
202
+ },
203
+ invalidate(input, queryClient) {
204
+ const queryKey = input
205
+ ? buildQueryKey(namespace, procedureName, input)
206
+ : [namespace, procedureName];
207
+ return queryClient.invalidateQueries({ queryKey });
208
+ },
209
+ prefetch(input, queryClient) {
210
+ const client = getClient();
211
+ const queryKey = buildQueryKey(namespace, procedureName, input);
212
+ return queryClient.prefetchQuery({
213
+ queryKey,
214
+ queryFn: async () => {
215
+ const namespaceClient = client[namespace];
216
+ const procedure = namespaceClient[procedureName];
217
+ return procedure(input);
218
+ },
219
+ });
220
+ },
221
+ setData(input, data, queryClient) {
222
+ const queryKey = buildQueryKey(namespace, procedureName, input);
223
+ queryClient.setQueryData(queryKey, data);
224
+ },
225
+ getData(input, queryClient) {
226
+ const queryKey = buildQueryKey(namespace, procedureName, input);
227
+ return queryClient.getQueryData(queryKey);
228
+ },
229
+ };
230
+ }
231
+ /**
232
+ * Creates a mutation procedure proxy with hook methods and auto-invalidation
233
+ *
234
+ * Auto-invalidation is enabled by default and follows naming conventions:
235
+ * - `create*`, `add*` → invalidates `list*`, `find*` queries
236
+ * - `update*`, `edit*`, `patch*` → invalidates `get*` (matching ID), `list*`, `find*`
237
+ * - `delete*`, `remove*` → invalidates `get*` (matching ID), `list*`, `find*`
238
+ *
239
+ * @param namespace - The procedure namespace (e.g., 'users')
240
+ * @param procedureName - The procedure name (e.g., 'createUser')
241
+ * @param getClient - Factory function to get the client (called inside hooks)
242
+ */
243
+ function createMutationProcedureProxy(namespace, procedureName, getClient) {
244
+ return {
245
+ useMutation(options) {
246
+ const client = getClient();
247
+ const queryClient = useReactQueryClient();
248
+ // Extract auto-invalidation configuration
249
+ const typedOptions = options;
250
+ const autoInvalidateOption = typedOptions?.autoInvalidate;
251
+ const autoInvalidateEnabled = autoInvalidateOption !== false;
252
+ const autoInvalidateConfig = typeof autoInvalidateOption === 'object' ? autoInvalidateOption : undefined;
253
+ // Store original onSuccess to call after auto-invalidation
254
+ const originalOnSuccess = options?.onSuccess;
255
+ return useReactMutation({
256
+ mutationFn: async (input) => {
257
+ const namespaceClient = client[namespace];
258
+ const procedure = namespaceClient[procedureName];
259
+ return procedure(input);
260
+ },
261
+ ...options,
262
+ onSuccess: async (data, variables, context, meta) => {
263
+ // Perform auto-invalidation if enabled
264
+ if (autoInvalidateEnabled) {
265
+ await performAutoInvalidation(queryClient, namespace, procedureName, variables, data, autoInvalidateConfig);
266
+ }
267
+ // Call user's onSuccess callback if provided (React Query v5 signature)
268
+ if (originalOnSuccess) {
269
+ await originalOnSuccess(data, variables, context, meta);
270
+ }
271
+ },
272
+ });
273
+ },
274
+ };
275
+ }
276
+ // ============================================================================
277
+ // Namespace Proxy
278
+ // ============================================================================
279
+ /**
280
+ * Creates a proxy for a namespace that returns procedure proxies
281
+ *
282
+ * Each property access on the namespace proxy creates a procedure proxy
283
+ * with the appropriate methods (useQuery for queries, useMutation for mutations).
284
+ *
285
+ * @param namespace - The namespace name (e.g., 'users')
286
+ * @param getClient - Factory function to get the client
287
+ */
288
+ function createNamespaceProxy(namespace, getClient) {
289
+ // Cache procedure proxies to avoid recreating on every access
290
+ const procedureCache = new Map();
291
+ return new Proxy({}, {
292
+ get(_target, procedureName) {
293
+ // Return cached proxy if available
294
+ const cached = procedureCache.get(procedureName);
295
+ if (cached) {
296
+ return cached;
297
+ }
298
+ // Create new procedure proxy based on naming convention
299
+ const procedureProxy = isQueryProcedure(procedureName)
300
+ ? createQueryProcedureProxy(namespace, procedureName, getClient)
301
+ : createMutationProcedureProxy(namespace, procedureName, getClient);
302
+ // Cache for future access
303
+ procedureCache.set(procedureName, procedureProxy);
304
+ return procedureProxy;
305
+ },
306
+ });
307
+ }
308
+ // ============================================================================
309
+ // Main Factory
310
+ // ============================================================================
311
+ /**
312
+ * Creates a typed proxy for accessing VeloxTS procedures as React hooks
313
+ *
314
+ * This is the primary entry point for the tRPC-style API. It returns a proxy
315
+ * that mirrors your router structure and provides hook methods with full
316
+ * IDE autocomplete.
317
+ *
318
+ * @template TRouter - The router type (collection of procedure collections)
319
+ * @param config - Optional configuration
320
+ * @returns Fully typed proxy with autocomplete for namespaces and procedures
321
+ *
322
+ * @example Basic usage
323
+ * ```tsx
324
+ * // api.ts - Create hooks once
325
+ * import { createVeloxHooks } from '@veloxts/client/react';
326
+ * import type { AppRouter } from '../../api/src';
327
+ *
328
+ * export const api = createVeloxHooks<AppRouter>();
329
+ *
330
+ * // UserProfile.tsx - Use with full autocomplete
331
+ * import { api } from '../api';
332
+ *
333
+ * function UserProfile({ userId }: { userId: string }) {
334
+ * const { data: user, isLoading } = api.users.getUser.useQuery({ id: userId });
335
+ *
336
+ * const { mutate: updateUser } = api.users.updateUser.useMutation({
337
+ * onSuccess: () => {
338
+ * api.users.getUser.invalidate({ id: userId });
339
+ * },
340
+ * });
341
+ *
342
+ * if (isLoading) return <div>Loading...</div>;
343
+ * return <div>{user?.name}</div>;
344
+ * }
345
+ * ```
346
+ *
347
+ * @example With Suspense
348
+ * ```tsx
349
+ * function UserProfileSuspense({ userId }: { userId: string }) {
350
+ * // Throws promise for Suspense boundary
351
+ * const { data: user } = api.users.getUser.useSuspenseQuery({ id: userId });
352
+ * return <h1>{user.name}</h1>;
353
+ * }
354
+ *
355
+ * // Wrap with Suspense boundary
356
+ * <Suspense fallback={<Spinner />}>
357
+ * <UserProfileSuspense userId="123" />
358
+ * </Suspense>
359
+ * ```
360
+ *
361
+ * @example SSR with direct client
362
+ * ```tsx
363
+ * import { createClient } from '@veloxts/client';
364
+ *
365
+ * const client = createClient<AppRouter>({ baseUrl: '/api' });
366
+ * const api = createVeloxHooks<AppRouter>({ client });
367
+ * ```
368
+ */
369
+ export function createVeloxHooks(config) {
370
+ // Cache namespace proxies to avoid recreating on every access
371
+ const namespaceCache = new Map();
372
+ // Factory function that gets the client
373
+ // If config.client is provided, use it directly (SSR/testing)
374
+ // Otherwise, get from context (must be inside VeloxProvider)
375
+ const getClient = () => {
376
+ // Must always call hook before returning
377
+ const { client: contextClient } = useVeloxContext();
378
+ return config?.client ?? contextClient;
379
+ };
380
+ // Create the root proxy
381
+ return new Proxy({}, {
382
+ get(_target, namespace) {
383
+ // Return cached namespace proxy if available
384
+ const cached = namespaceCache.get(namespace);
385
+ if (cached) {
386
+ return cached;
387
+ }
388
+ // Create new namespace proxy
389
+ const namespaceProxy = createNamespaceProxy(namespace, getClient);
390
+ // Cache for future access
391
+ namespaceCache.set(namespace, namespaceProxy);
392
+ return namespaceProxy;
393
+ },
394
+ });
395
+ }
396
+ //# sourceMappingURL=proxy-hooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"proxy-hooks.js","sourceRoot":"","sources":["../../src/react/proxy-hooks.ts"],"names":[],"mappings":"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"}