routesync 1.0.20 → 1.0.21

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/dist/cli.js CHANGED
@@ -8461,9 +8461,9 @@ foreach ($routes as $route) {
8461
8461
  $resourceName = null;
8462
8462
  $collection = false;
8463
8463
 
8464
- if (preg_match('/returns+news+([a-zA-Z0-9_]+Resource)/', $methodSource, $matches)) {
8464
+ if (preg_match('/return\\s+new\\s+([a-zA-Z0-9_]+Resource)/', $methodSource, $matches)) {
8465
8465
  $resourceName = $matches[1];
8466
- } elseif (preg_match('/returns+([a-zA-Z0-9_]+Resource)::collection/', $methodSource, $matches)) {
8466
+ } elseif (preg_match('/return\\s+([a-zA-Z0-9_]+Resource)::collection/', $methodSource, $matches)) {
8467
8467
  $resourceName = $matches[1];
8468
8468
  $collection = true;
8469
8469
  }
@@ -8489,7 +8489,7 @@ foreach ($routes as $route) {
8489
8489
 
8490
8490
  if (!$responseMetadata) {
8491
8491
  $docComment = $resReflector->getDocComment();
8492
- if ($docComment && preg_match('/@mixins+([\\\\a-zA-Z0-9_]+)/', $docComment, $mixinMatches)) {
8492
+ if ($docComment && preg_match('/@mixin\\s+([\\\\\\\\a-zA-Z0-9_]+)/', $docComment, $mixinMatches)) {
8493
8493
  $responseMetadata = [
8494
8494
  'type' => class_basename($mixinMatches[1]),
8495
8495
  'collection' => $collection
@@ -8755,6 +8755,7 @@ var SDKGenerator = class {
8755
8755
  if (usesZod) {
8756
8756
  lines.push(`import { z } from 'zod'`);
8757
8757
  lines.push(`import * as Schemas from './schemas'`);
8758
+ lines.push(`export * as Schemas from './schemas'`);
8758
8759
  }
8759
8760
  if (usesTypes) {
8760
8761
  lines.push(`import * as Types from './types'`);
@@ -9053,7 +9054,8 @@ var HookGenerator = class _HookGenerator {
9053
9054
  const queryKey = `['${group}', '${route.actionName}']`;
9054
9055
  if (method === "GET") {
9055
9056
  lines.push(`/**`);
9056
- lines.push(` * @deprecated Use \`useApiQuery(api.${group}.${route.actionName}, ...args)\` instead.`);
9057
+ lines.push(` * @deprecated Generated hooks will become optional in v2.`);
9058
+ lines.push(` * Prefer \`useApiQuery(api.${group}.${route.actionName}, ...args)\` for future compatibility.`);
9057
9059
  lines.push(` */`);
9058
9060
  lines.push(`export function ${hookName}(...args: Parameters<typeof api.${group}.${route.actionName}>) {`);
9059
9061
  lines.push(` return useApiQuery(api.${group}.${route.actionName}, ...args as any)`);
@@ -9061,7 +9063,8 @@ var HookGenerator = class _HookGenerator {
9061
9063
  lines.push(``);
9062
9064
  } else {
9063
9065
  lines.push(`/**`);
9064
- lines.push(` * @deprecated Use \`useApiMutation(api.${group}.${route.actionName}, options)\` instead.`);
9066
+ lines.push(` * @deprecated Generated hooks will become optional in v2.`);
9067
+ lines.push(` * Prefer \`useApiMutation(api.${group}.${route.actionName}, options)\` for future compatibility.`);
9065
9068
  lines.push(` */`);
9066
9069
  lines.push(`export function ${hookName}() {`);
9067
9070
  lines.push(` return useApiMutation(api.${group}.${route.actionName})`);
package/dist/react.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as _tanstack_react_query from '@tanstack/react-query';
2
- import { UseQueryOptions, UseMutationOptions } from '@tanstack/react-query';
2
+ import { UseQueryOptions, InfiniteData, UseInfiniteQueryOptions, UseSuspenseQueryOptions, UseMutationOptions, QueryClient } from '@tanstack/react-query';
3
3
 
4
4
  type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
5
5
  type RouteTransform = (value: unknown) => unknown;
@@ -80,6 +80,20 @@ declare function useApiQuery<TResponse = unknown, TParams = unknown, TBody = unk
80
80
  ...OptionalIfEmpty<EndpointCallableOptions<TParams, TBody>>,
81
81
  queryOptions?: Omit<UseQueryOptions<TResponse, TError, TData>, 'queryKey' | 'queryFn'>
82
82
  ]): _tanstack_react_query.UseQueryResult<NoInfer<TData>, TError>;
83
+ /**
84
+ * useApiSuspenseQuery — generic wrapper for Suspense-enabled data fetching (TanStack v5).
85
+ */
86
+ declare function useApiSuspenseQuery<TResponse = unknown, TParams = unknown, TBody = unknown, TError = ApiError, TData = TResponse>(endpoint: EndpointCallable<TResponse, TParams, TBody>, ...args: [
87
+ ...OptionalIfEmpty<EndpointCallableOptions<TParams, TBody>>,
88
+ queryOptions?: Omit<UseSuspenseQueryOptions<TResponse, TError, TData>, 'queryKey' | 'queryFn'>
89
+ ]): _tanstack_react_query.UseSuspenseQueryResult<TData, TError>;
90
+ /**
91
+ * useApiInfiniteQuery — framework agnostic paginated fetching.
92
+ */
93
+ declare function useApiInfiniteQuery<TResponse = unknown, TParams = unknown, TBody = unknown, TError = ApiError, TData = InfiniteData<TResponse>, TPageParam = unknown>(endpoint: EndpointCallable<TResponse, TParams, TBody>, ...args: [
94
+ ...OptionalIfEmpty<EndpointCallableOptions<TParams, TBody>>,
95
+ queryOptions: Omit<UseInfiniteQueryOptions<TResponse, TError, TData, any, TPageParam>, 'queryKey' | 'queryFn'>
96
+ ]): _tanstack_react_query.UseInfiniteQueryResult<TData, TError>;
83
97
 
84
98
  /**
85
99
  * useApiMutation — accepts an endpoint callable directly.
@@ -94,11 +108,40 @@ declare function useApiQuery<TResponse = unknown, TParams = unknown, TBody = unk
94
108
  * invalidate: [api.cart.list, api.orders.index],
95
109
  * })
96
110
  */
97
- interface ApiMutationOptions<TData, TError, TVariables> extends Omit<UseMutationOptions<TData, TError, TVariables>, 'mutationFn'> {
111
+ interface ApiMutationOptions<TData, TError, TVariables, TContext = unknown> extends Omit<UseMutationOptions<TData, TError, TVariables, TContext>, 'mutationFn'> {
98
112
  /** Extra endpoints to invalidate on success (in addition to the auto group invalidation). */
99
113
  invalidate?: EndpointCallable<any, any, any>[];
100
114
  }
101
- declare function useApiMutation<TResponse = unknown, TParams = unknown, TBody = unknown, TError = ApiError>(endpoint: EndpointCallable<TResponse, TParams, TBody>, options?: ApiMutationOptions<TResponse, TError, EndpointCallableOptions<TParams, TBody>>): _tanstack_react_query.UseMutationResult<TResponse, TError, EndpointCallableOptions<TParams, TBody>, unknown>;
115
+ declare function useApiMutation<TResponse = unknown, TParams = unknown, TBody = unknown, TError = ApiError, TContext = unknown>(endpoint: EndpointCallable<TResponse, TParams, TBody>, options?: ApiMutationOptions<TResponse, TError, EndpointCallableOptions<TParams, TBody>, TContext>): _tanstack_react_query.UseMutationResult<TResponse, TError, EndpointCallableOptions<TParams, TBody>, TContext>;
116
+
117
+ /**
118
+ * useApiQueryClient — a typed wrapper over TanStack's QueryClient
119
+ *
120
+ * Provides ergonomic helpers like invalidateEndpoint and prefetchEndpoint
121
+ * with strong typing based on the RouteSync SDK contracts.
122
+ */
123
+ declare function useApiQueryClient(): {
124
+ queryClient: QueryClient;
125
+ /**
126
+ * Invalidate specific queries related to an endpoint.
127
+ * Optionally pass parameters to invalidate a more specific cache entry.
128
+ */
129
+ invalidateEndpoint: <TResponse, TParams, TBody>(endpoint: EndpointCallable<TResponse, TParams, TBody>, options?: EndpointCallableOptions<TParams, TBody>) => Promise<void>;
130
+ /**
131
+ * Prefetch data for an endpoint into the cache.
132
+ * Useful for SSR, RSC hydration, or proactive prefetching.
133
+ */
134
+ prefetchEndpoint: <TResponse, TParams, TBody>(endpoint: EndpointCallable<TResponse, TParams, TBody>, options?: EndpointCallableOptions<TParams, TBody>) => Promise<void>;
135
+ /**
136
+ * Manually update the cache for a specific endpoint.
137
+ * Often used for optimistic updates in mutations.
138
+ */
139
+ setEndpointData: <TResponse, TParams, TBody>(endpoint: EndpointCallable<TResponse, TParams, TBody>, options: EndpointCallableOptions<TParams, TBody> | undefined, updater: TResponse | ((oldData: TResponse | undefined) => TResponse)) => unknown;
140
+ /**
141
+ * Retrieve the current cached data for a specific endpoint.
142
+ */
143
+ getEndpointData: <TResponse, TParams, TBody>(endpoint: EndpointCallable<TResponse, TParams, TBody>, options?: EndpointCallableOptions<TParams, TBody>) => TResponse | undefined;
144
+ };
102
145
 
103
146
  /**
104
147
  * createHooks — generate typed hooks from an api group.
@@ -113,4 +156,19 @@ declare function useApiMutation<TResponse = unknown, TParams = unknown, TBody =
113
156
  */
114
157
  declare function createHooks<T extends Record<string, EndpointCallable>>(group: T): { [K in keyof T as `use${Capitalize<string & K>}`]: T[K] extends EndpointCallable ? T[K]["$def"]["method"] extends "GET" | "DELETE" ? (options?: any, queryOptions?: any) => ReturnType<typeof useApiQuery> : (options?: any) => ReturnType<typeof useApiMutation> : never; };
115
158
 
116
- export { type ApiMutationOptions, createHooks, useApiMutation, useApiQuery };
159
+ interface UseFormSetError<TFieldValues extends Record<string, any>> {
160
+ (name: keyof TFieldValues | string, error: {
161
+ type: string;
162
+ message?: string;
163
+ }): void;
164
+ }
165
+ /**
166
+ * Parses an unknown error and safely pipes 422 Unprocessable Entity
167
+ * validation messages to react-hook-form's setError.
168
+ *
169
+ * @param error - The error thrown by a RouteSync mutation
170
+ * @param setError - The `setError` function destructured from `useForm()`
171
+ */
172
+ declare function setFormErrors<TFieldValues extends Record<string, any>>(error: unknown, setError: UseFormSetError<TFieldValues>): void;
173
+
174
+ export { type ApiMutationOptions, createHooks, setFormErrors, useApiInfiniteQuery, useApiMutation, useApiQuery, useApiQueryClient, useApiSuspenseQuery };
package/dist/react.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as _tanstack_react_query from '@tanstack/react-query';
2
- import { UseQueryOptions, UseMutationOptions } from '@tanstack/react-query';
2
+ import { UseQueryOptions, InfiniteData, UseInfiniteQueryOptions, UseSuspenseQueryOptions, UseMutationOptions, QueryClient } from '@tanstack/react-query';
3
3
 
4
4
  type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
5
5
  type RouteTransform = (value: unknown) => unknown;
@@ -80,6 +80,20 @@ declare function useApiQuery<TResponse = unknown, TParams = unknown, TBody = unk
80
80
  ...OptionalIfEmpty<EndpointCallableOptions<TParams, TBody>>,
81
81
  queryOptions?: Omit<UseQueryOptions<TResponse, TError, TData>, 'queryKey' | 'queryFn'>
82
82
  ]): _tanstack_react_query.UseQueryResult<NoInfer<TData>, TError>;
83
+ /**
84
+ * useApiSuspenseQuery — generic wrapper for Suspense-enabled data fetching (TanStack v5).
85
+ */
86
+ declare function useApiSuspenseQuery<TResponse = unknown, TParams = unknown, TBody = unknown, TError = ApiError, TData = TResponse>(endpoint: EndpointCallable<TResponse, TParams, TBody>, ...args: [
87
+ ...OptionalIfEmpty<EndpointCallableOptions<TParams, TBody>>,
88
+ queryOptions?: Omit<UseSuspenseQueryOptions<TResponse, TError, TData>, 'queryKey' | 'queryFn'>
89
+ ]): _tanstack_react_query.UseSuspenseQueryResult<TData, TError>;
90
+ /**
91
+ * useApiInfiniteQuery — framework agnostic paginated fetching.
92
+ */
93
+ declare function useApiInfiniteQuery<TResponse = unknown, TParams = unknown, TBody = unknown, TError = ApiError, TData = InfiniteData<TResponse>, TPageParam = unknown>(endpoint: EndpointCallable<TResponse, TParams, TBody>, ...args: [
94
+ ...OptionalIfEmpty<EndpointCallableOptions<TParams, TBody>>,
95
+ queryOptions: Omit<UseInfiniteQueryOptions<TResponse, TError, TData, any, TPageParam>, 'queryKey' | 'queryFn'>
96
+ ]): _tanstack_react_query.UseInfiniteQueryResult<TData, TError>;
83
97
 
84
98
  /**
85
99
  * useApiMutation — accepts an endpoint callable directly.
@@ -94,11 +108,40 @@ declare function useApiQuery<TResponse = unknown, TParams = unknown, TBody = unk
94
108
  * invalidate: [api.cart.list, api.orders.index],
95
109
  * })
96
110
  */
97
- interface ApiMutationOptions<TData, TError, TVariables> extends Omit<UseMutationOptions<TData, TError, TVariables>, 'mutationFn'> {
111
+ interface ApiMutationOptions<TData, TError, TVariables, TContext = unknown> extends Omit<UseMutationOptions<TData, TError, TVariables, TContext>, 'mutationFn'> {
98
112
  /** Extra endpoints to invalidate on success (in addition to the auto group invalidation). */
99
113
  invalidate?: EndpointCallable<any, any, any>[];
100
114
  }
101
- declare function useApiMutation<TResponse = unknown, TParams = unknown, TBody = unknown, TError = ApiError>(endpoint: EndpointCallable<TResponse, TParams, TBody>, options?: ApiMutationOptions<TResponse, TError, EndpointCallableOptions<TParams, TBody>>): _tanstack_react_query.UseMutationResult<TResponse, TError, EndpointCallableOptions<TParams, TBody>, unknown>;
115
+ declare function useApiMutation<TResponse = unknown, TParams = unknown, TBody = unknown, TError = ApiError, TContext = unknown>(endpoint: EndpointCallable<TResponse, TParams, TBody>, options?: ApiMutationOptions<TResponse, TError, EndpointCallableOptions<TParams, TBody>, TContext>): _tanstack_react_query.UseMutationResult<TResponse, TError, EndpointCallableOptions<TParams, TBody>, TContext>;
116
+
117
+ /**
118
+ * useApiQueryClient — a typed wrapper over TanStack's QueryClient
119
+ *
120
+ * Provides ergonomic helpers like invalidateEndpoint and prefetchEndpoint
121
+ * with strong typing based on the RouteSync SDK contracts.
122
+ */
123
+ declare function useApiQueryClient(): {
124
+ queryClient: QueryClient;
125
+ /**
126
+ * Invalidate specific queries related to an endpoint.
127
+ * Optionally pass parameters to invalidate a more specific cache entry.
128
+ */
129
+ invalidateEndpoint: <TResponse, TParams, TBody>(endpoint: EndpointCallable<TResponse, TParams, TBody>, options?: EndpointCallableOptions<TParams, TBody>) => Promise<void>;
130
+ /**
131
+ * Prefetch data for an endpoint into the cache.
132
+ * Useful for SSR, RSC hydration, or proactive prefetching.
133
+ */
134
+ prefetchEndpoint: <TResponse, TParams, TBody>(endpoint: EndpointCallable<TResponse, TParams, TBody>, options?: EndpointCallableOptions<TParams, TBody>) => Promise<void>;
135
+ /**
136
+ * Manually update the cache for a specific endpoint.
137
+ * Often used for optimistic updates in mutations.
138
+ */
139
+ setEndpointData: <TResponse, TParams, TBody>(endpoint: EndpointCallable<TResponse, TParams, TBody>, options: EndpointCallableOptions<TParams, TBody> | undefined, updater: TResponse | ((oldData: TResponse | undefined) => TResponse)) => unknown;
140
+ /**
141
+ * Retrieve the current cached data for a specific endpoint.
142
+ */
143
+ getEndpointData: <TResponse, TParams, TBody>(endpoint: EndpointCallable<TResponse, TParams, TBody>, options?: EndpointCallableOptions<TParams, TBody>) => TResponse | undefined;
144
+ };
102
145
 
103
146
  /**
104
147
  * createHooks — generate typed hooks from an api group.
@@ -113,4 +156,19 @@ declare function useApiMutation<TResponse = unknown, TParams = unknown, TBody =
113
156
  */
114
157
  declare function createHooks<T extends Record<string, EndpointCallable>>(group: T): { [K in keyof T as `use${Capitalize<string & K>}`]: T[K] extends EndpointCallable ? T[K]["$def"]["method"] extends "GET" | "DELETE" ? (options?: any, queryOptions?: any) => ReturnType<typeof useApiQuery> : (options?: any) => ReturnType<typeof useApiMutation> : never; };
115
158
 
116
- export { type ApiMutationOptions, createHooks, useApiMutation, useApiQuery };
159
+ interface UseFormSetError<TFieldValues extends Record<string, any>> {
160
+ (name: keyof TFieldValues | string, error: {
161
+ type: string;
162
+ message?: string;
163
+ }): void;
164
+ }
165
+ /**
166
+ * Parses an unknown error and safely pipes 422 Unprocessable Entity
167
+ * validation messages to react-hook-form's setError.
168
+ *
169
+ * @param error - The error thrown by a RouteSync mutation
170
+ * @param setError - The `setError` function destructured from `useForm()`
171
+ */
172
+ declare function setFormErrors<TFieldValues extends Record<string, any>>(error: unknown, setError: UseFormSetError<TFieldValues>): void;
173
+
174
+ export { type ApiMutationOptions, createHooks, setFormErrors, useApiInfiniteQuery, useApiMutation, useApiQuery, useApiQueryClient, useApiSuspenseQuery };
package/dist/react.js CHANGED
@@ -21,8 +21,12 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var src_exports = {};
22
22
  __export(src_exports, {
23
23
  createHooks: () => createHooks,
24
+ setFormErrors: () => setFormErrors,
25
+ useApiInfiniteQuery: () => useApiInfiniteQuery,
24
26
  useApiMutation: () => useApiMutation,
25
- useApiQuery: () => useApiQuery
27
+ useApiQuery: () => useApiQuery,
28
+ useApiQueryClient: () => useApiQueryClient,
29
+ useApiSuspenseQuery: () => useApiSuspenseQuery
26
30
  });
27
31
  module.exports = __toCommonJS(src_exports);
28
32
 
@@ -38,6 +42,32 @@ function useApiQuery(endpoint, ...args) {
38
42
  ...queryOptions
39
43
  });
40
44
  }
45
+ function useApiSuspenseQuery(endpoint, ...args) {
46
+ const options = args[0];
47
+ const queryOptions = args[1];
48
+ const queryKey = endpoint.$queryKey(options);
49
+ return (0, import_react_query.useSuspenseQuery)({
50
+ queryKey,
51
+ queryFn: () => endpoint(options),
52
+ ...queryOptions
53
+ });
54
+ }
55
+ function useApiInfiniteQuery(endpoint, ...args) {
56
+ const options = args[0];
57
+ const queryOptions = args.length > 1 ? args[1] : args[0];
58
+ const queryKey = endpoint.$queryKey(options);
59
+ return (0, import_react_query.useInfiniteQuery)({
60
+ queryKey,
61
+ queryFn: ({ pageParam }) => {
62
+ const fetchOptions = { ...options };
63
+ if (pageParam !== void 0) {
64
+ fetchOptions.query = { ...fetchOptions.query || {}, page: pageParam };
65
+ }
66
+ return endpoint(fetchOptions);
67
+ },
68
+ ...queryOptions
69
+ });
70
+ }
41
71
 
42
72
  // packages/react/src/hooks/useMutation.ts
43
73
  var import_react_query2 = require("@tanstack/react-query");
@@ -57,6 +87,47 @@ function useApiMutation(endpoint, options) {
57
87
  });
58
88
  }
59
89
 
90
+ // packages/react/src/hooks/useQueryClient.ts
91
+ var import_react_query3 = require("@tanstack/react-query");
92
+ function useApiQueryClient() {
93
+ const queryClient = (0, import_react_query3.useQueryClient)();
94
+ return {
95
+ queryClient,
96
+ /**
97
+ * Invalidate specific queries related to an endpoint.
98
+ * Optionally pass parameters to invalidate a more specific cache entry.
99
+ */
100
+ invalidateEndpoint: (endpoint, options) => {
101
+ return queryClient.invalidateQueries({
102
+ queryKey: endpoint.$queryKey(options)
103
+ });
104
+ },
105
+ /**
106
+ * Prefetch data for an endpoint into the cache.
107
+ * Useful for SSR, RSC hydration, or proactive prefetching.
108
+ */
109
+ prefetchEndpoint: (endpoint, options) => {
110
+ return queryClient.prefetchQuery({
111
+ queryKey: endpoint.$queryKey(options),
112
+ queryFn: () => endpoint(options)
113
+ });
114
+ },
115
+ /**
116
+ * Manually update the cache for a specific endpoint.
117
+ * Often used for optimistic updates in mutations.
118
+ */
119
+ setEndpointData: (endpoint, options, updater) => {
120
+ return queryClient.setQueryData(endpoint.$queryKey(options), updater);
121
+ },
122
+ /**
123
+ * Retrieve the current cached data for a specific endpoint.
124
+ */
125
+ getEndpointData: (endpoint, options) => {
126
+ return queryClient.getQueryData(endpoint.$queryKey(options));
127
+ }
128
+ };
129
+ }
130
+
60
131
  // packages/react/src/hooks/createHooks.ts
61
132
  function createHooks(group) {
62
133
  const hooks = {};
@@ -71,9 +142,30 @@ function createHooks(group) {
71
142
  }
72
143
  return hooks;
73
144
  }
145
+
146
+ // packages/react/src/utils/form.ts
147
+ function setFormErrors(error, setError) {
148
+ if (error && typeof error === "object" && "status" in error && error.status === 422) {
149
+ const apiError = error;
150
+ const errors = apiError.errors;
151
+ if (errors && typeof errors === "object") {
152
+ for (const [field, messages] of Object.entries(errors)) {
153
+ if (Array.isArray(messages) && messages.length > 0) {
154
+ setError(field, { type: "server", message: String(messages[0]) });
155
+ } else if (typeof messages === "string") {
156
+ setError(field, { type: "server", message: messages });
157
+ }
158
+ }
159
+ }
160
+ }
161
+ }
74
162
  // Annotate the CommonJS export names for ESM import in node:
75
163
  0 && (module.exports = {
76
164
  createHooks,
165
+ setFormErrors,
166
+ useApiInfiniteQuery,
77
167
  useApiMutation,
78
- useApiQuery
168
+ useApiQuery,
169
+ useApiQueryClient,
170
+ useApiSuspenseQuery
79
171
  });
package/dist/react.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  // packages/react/src/hooks/useQuery.ts
2
- import { useQuery } from "@tanstack/react-query";
2
+ import { useQuery, useSuspenseQuery, useInfiniteQuery } from "@tanstack/react-query";
3
3
  function useApiQuery(endpoint, ...args) {
4
4
  const options = args[0];
5
5
  const queryOptions = args[1];
@@ -10,6 +10,32 @@ function useApiQuery(endpoint, ...args) {
10
10
  ...queryOptions
11
11
  });
12
12
  }
13
+ function useApiSuspenseQuery(endpoint, ...args) {
14
+ const options = args[0];
15
+ const queryOptions = args[1];
16
+ const queryKey = endpoint.$queryKey(options);
17
+ return useSuspenseQuery({
18
+ queryKey,
19
+ queryFn: () => endpoint(options),
20
+ ...queryOptions
21
+ });
22
+ }
23
+ function useApiInfiniteQuery(endpoint, ...args) {
24
+ const options = args[0];
25
+ const queryOptions = args.length > 1 ? args[1] : args[0];
26
+ const queryKey = endpoint.$queryKey(options);
27
+ return useInfiniteQuery({
28
+ queryKey,
29
+ queryFn: ({ pageParam }) => {
30
+ const fetchOptions = { ...options };
31
+ if (pageParam !== void 0) {
32
+ fetchOptions.query = { ...fetchOptions.query || {}, page: pageParam };
33
+ }
34
+ return endpoint(fetchOptions);
35
+ },
36
+ ...queryOptions
37
+ });
38
+ }
13
39
 
14
40
  // packages/react/src/hooks/useMutation.ts
15
41
  import { useMutation, useQueryClient } from "@tanstack/react-query";
@@ -29,6 +55,47 @@ function useApiMutation(endpoint, options) {
29
55
  });
30
56
  }
31
57
 
58
+ // packages/react/src/hooks/useQueryClient.ts
59
+ import { useQueryClient as useQueryClient2 } from "@tanstack/react-query";
60
+ function useApiQueryClient() {
61
+ const queryClient = useQueryClient2();
62
+ return {
63
+ queryClient,
64
+ /**
65
+ * Invalidate specific queries related to an endpoint.
66
+ * Optionally pass parameters to invalidate a more specific cache entry.
67
+ */
68
+ invalidateEndpoint: (endpoint, options) => {
69
+ return queryClient.invalidateQueries({
70
+ queryKey: endpoint.$queryKey(options)
71
+ });
72
+ },
73
+ /**
74
+ * Prefetch data for an endpoint into the cache.
75
+ * Useful for SSR, RSC hydration, or proactive prefetching.
76
+ */
77
+ prefetchEndpoint: (endpoint, options) => {
78
+ return queryClient.prefetchQuery({
79
+ queryKey: endpoint.$queryKey(options),
80
+ queryFn: () => endpoint(options)
81
+ });
82
+ },
83
+ /**
84
+ * Manually update the cache for a specific endpoint.
85
+ * Often used for optimistic updates in mutations.
86
+ */
87
+ setEndpointData: (endpoint, options, updater) => {
88
+ return queryClient.setQueryData(endpoint.$queryKey(options), updater);
89
+ },
90
+ /**
91
+ * Retrieve the current cached data for a specific endpoint.
92
+ */
93
+ getEndpointData: (endpoint, options) => {
94
+ return queryClient.getQueryData(endpoint.$queryKey(options));
95
+ }
96
+ };
97
+ }
98
+
32
99
  // packages/react/src/hooks/createHooks.ts
33
100
  function createHooks(group) {
34
101
  const hooks = {};
@@ -43,8 +110,29 @@ function createHooks(group) {
43
110
  }
44
111
  return hooks;
45
112
  }
113
+
114
+ // packages/react/src/utils/form.ts
115
+ function setFormErrors(error, setError) {
116
+ if (error && typeof error === "object" && "status" in error && error.status === 422) {
117
+ const apiError = error;
118
+ const errors = apiError.errors;
119
+ if (errors && typeof errors === "object") {
120
+ for (const [field, messages] of Object.entries(errors)) {
121
+ if (Array.isArray(messages) && messages.length > 0) {
122
+ setError(field, { type: "server", message: String(messages[0]) });
123
+ } else if (typeof messages === "string") {
124
+ setError(field, { type: "server", message: messages });
125
+ }
126
+ }
127
+ }
128
+ }
129
+ }
46
130
  export {
47
131
  createHooks,
132
+ setFormErrors,
133
+ useApiInfiniteQuery,
48
134
  useApiMutation,
49
- useApiQuery
135
+ useApiQuery,
136
+ useApiQueryClient,
137
+ useApiSuspenseQuery
50
138
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "routesync",
3
- "version": "1.0.20",
3
+ "version": "1.0.21",
4
4
  "description": "Laravel routes to typed frontend SDKs.",
5
5
  "main": "./dist/sdk.js",
6
6
  "module": "./dist/sdk.mjs",