routesync 1.0.19 → 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 +701 -580
- package/dist/core.d.mts +23 -3
- package/dist/core.d.ts +23 -3
- package/dist/core.js +1 -0
- package/dist/core.mjs +1 -0
- package/dist/react.d.mts +91 -13
- package/dist/react.d.ts +91 -13
- package/dist/react.js +98 -4
- package/dist/react.mjs +94 -4
- package/dist/sdk.d.mts +44 -12
- package/dist/sdk.d.ts +44 -12
- package/dist/sdk.js +23 -1
- package/dist/sdk.mjs +23 -1
- package/dist/vue.d.mts +9 -0
- package/dist/vue.d.ts +9 -0
- package/package.json +3 -2
package/dist/react.mjs
CHANGED
|
@@ -1,13 +1,41 @@
|
|
|
1
1
|
// packages/react/src/hooks/useQuery.ts
|
|
2
|
-
import { useQuery } from "@tanstack/react-query";
|
|
3
|
-
function useApiQuery(endpoint,
|
|
4
|
-
const
|
|
2
|
+
import { useQuery, useSuspenseQuery, useInfiniteQuery } from "@tanstack/react-query";
|
|
3
|
+
function useApiQuery(endpoint, ...args) {
|
|
4
|
+
const options = args[0];
|
|
5
|
+
const queryOptions = args[1];
|
|
6
|
+
const queryKey = endpoint.$queryKey(options);
|
|
5
7
|
return useQuery({
|
|
6
8
|
queryKey,
|
|
7
9
|
queryFn: () => endpoint(options),
|
|
8
10
|
...queryOptions
|
|
9
11
|
});
|
|
10
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
|
+
}
|
|
11
39
|
|
|
12
40
|
// packages/react/src/hooks/useMutation.ts
|
|
13
41
|
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
|
@@ -27,6 +55,47 @@ function useApiMutation(endpoint, options) {
|
|
|
27
55
|
});
|
|
28
56
|
}
|
|
29
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
|
+
|
|
30
99
|
// packages/react/src/hooks/createHooks.ts
|
|
31
100
|
function createHooks(group) {
|
|
32
101
|
const hooks = {};
|
|
@@ -41,8 +110,29 @@ function createHooks(group) {
|
|
|
41
110
|
}
|
|
42
111
|
return hooks;
|
|
43
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
|
+
}
|
|
44
130
|
export {
|
|
45
131
|
createHooks,
|
|
132
|
+
setFormErrors,
|
|
133
|
+
useApiInfiniteQuery,
|
|
46
134
|
useApiMutation,
|
|
47
|
-
useApiQuery
|
|
135
|
+
useApiQuery,
|
|
136
|
+
useApiQueryClient,
|
|
137
|
+
useApiSuspenseQuery
|
|
48
138
|
};
|
package/dist/sdk.d.mts
CHANGED
|
@@ -7,6 +7,14 @@ interface ServiceConfig {
|
|
|
7
7
|
timeout?: number;
|
|
8
8
|
retry?: RetryConfig;
|
|
9
9
|
cache?: boolean;
|
|
10
|
+
validateResponse?: boolean;
|
|
11
|
+
onValidationError?: (error: unknown, context: {
|
|
12
|
+
endpoint: string;
|
|
13
|
+
method: string;
|
|
14
|
+
path: string;
|
|
15
|
+
request: unknown;
|
|
16
|
+
response: unknown;
|
|
17
|
+
}) => void;
|
|
10
18
|
}
|
|
11
19
|
interface RetryConfig {
|
|
12
20
|
attempts: number;
|
|
@@ -16,6 +24,7 @@ interface RetryConfig {
|
|
|
16
24
|
|
|
17
25
|
declare class HttpClient {
|
|
18
26
|
private client;
|
|
27
|
+
readonly config: ServiceConfig;
|
|
19
28
|
constructor(config: ServiceConfig);
|
|
20
29
|
private setupInterceptors;
|
|
21
30
|
setToken(token: string): void;
|
|
@@ -56,11 +65,15 @@ interface RouteSchemaMap {
|
|
|
56
65
|
}
|
|
57
66
|
type RouteSchemaValue = RouteTransform | RouteParserSchema;
|
|
58
67
|
type RouteSchema = RouteSchemaValue | RouteSchemaMap;
|
|
59
|
-
interface
|
|
68
|
+
interface ResponseSchema<T> {
|
|
69
|
+
parse(input: unknown): T;
|
|
70
|
+
}
|
|
71
|
+
interface RouteDefinition<TResponse = unknown, TParams = unknown, TBody = unknown> {
|
|
60
72
|
method: HttpMethod;
|
|
61
73
|
path: string;
|
|
62
74
|
auth?: boolean;
|
|
63
75
|
schema?: RouteSchema;
|
|
76
|
+
responseSchema?: ResponseSchema<TResponse>;
|
|
64
77
|
mapper?: RouteMapper;
|
|
65
78
|
headers?: Record<string, string>;
|
|
66
79
|
cache?: unknown;
|
|
@@ -68,10 +81,13 @@ interface RouteDefinition {
|
|
|
68
81
|
body?: Record<string, any>;
|
|
69
82
|
params?: Record<string, any>;
|
|
70
83
|
query?: Record<string, any>;
|
|
84
|
+
_typeResponse?: TResponse;
|
|
85
|
+
_typeParams?: TParams;
|
|
86
|
+
_typeBody?: TBody;
|
|
71
87
|
}
|
|
72
88
|
interface ApiDefinition {
|
|
73
89
|
[group: string]: {
|
|
74
|
-
[action: string]: RouteDefinition
|
|
90
|
+
[action: string]: RouteDefinition<any, any, any>;
|
|
75
91
|
};
|
|
76
92
|
}
|
|
77
93
|
|
|
@@ -99,21 +115,37 @@ declare class TokenManager {
|
|
|
99
115
|
exists(): boolean;
|
|
100
116
|
}
|
|
101
117
|
|
|
102
|
-
type CallOptions = {
|
|
103
|
-
params?:
|
|
118
|
+
type CallOptions<TParams = unknown, TBody = unknown> = {
|
|
119
|
+
params?: TParams;
|
|
104
120
|
query?: Record<string, any>;
|
|
105
|
-
body?:
|
|
121
|
+
body?: TBody;
|
|
106
122
|
headers?: Record<string, string>;
|
|
107
123
|
};
|
|
108
|
-
|
|
109
|
-
|
|
124
|
+
type EndpointCallableOptions<TParams, TBody> = (unknown extends TParams ? {} : {
|
|
125
|
+
params: TParams;
|
|
126
|
+
}) & (unknown extends TBody ? {} : {
|
|
127
|
+
body: TBody;
|
|
128
|
+
}) & {
|
|
129
|
+
query?: Record<string, any>;
|
|
130
|
+
headers?: Record<string, string>;
|
|
131
|
+
};
|
|
132
|
+
type OptionalIfEmpty<T> = keyof Omit<T, 'query' | 'headers'> extends never ? [options?: T] : [options: T];
|
|
133
|
+
interface ApiError {
|
|
134
|
+
message: string;
|
|
135
|
+
status?: number;
|
|
136
|
+
errors?: Record<string, string[]>;
|
|
137
|
+
}
|
|
138
|
+
interface EndpointCallable<TResponse = unknown, TParams = unknown, TBody = unknown> {
|
|
139
|
+
(...args: OptionalIfEmpty<EndpointCallableOptions<TParams, TBody>>): Promise<TResponse>;
|
|
110
140
|
/** Original RouteDefinition — used by useApiQuery / useApiMutation */
|
|
111
|
-
$def: RouteDefinition
|
|
141
|
+
$def: RouteDefinition<TResponse, TParams, TBody>;
|
|
112
142
|
/** Stable TanStack query key: [group, action] */
|
|
113
143
|
$key: string[];
|
|
144
|
+
/** Consistent query key builder that incorporates params/query if provided */
|
|
145
|
+
$queryKey: (...args: OptionalIfEmpty<EndpointCallableOptions<TParams, TBody>>) => unknown[];
|
|
114
146
|
}
|
|
115
|
-
type ApiGroupProxy<G extends Record<string, RouteDefinition
|
|
116
|
-
[K in keyof G]: EndpointCallable
|
|
147
|
+
type ApiGroupProxy<G extends Record<string, RouteDefinition<any, any, any>>> = {
|
|
148
|
+
[K in keyof G]: EndpointCallable<G[K] extends RouteDefinition<infer R, any, any> ? R : unknown, G[K] extends RouteDefinition<any, infer P, any> ? P : unknown, G[K] extends RouteDefinition<any, any, infer B> ? B : unknown>;
|
|
117
149
|
};
|
|
118
150
|
type ApiProxy<T extends ApiDefinition> = {
|
|
119
151
|
[G in keyof T]: ApiGroupProxy<T[G]>;
|
|
@@ -139,7 +171,7 @@ type EndpointDefinition$1 = RouteDefinition;
|
|
|
139
171
|
* const { data } = useApiQuery(api.cart.list)
|
|
140
172
|
* const mutation = useApiMutation(api.cart.create)
|
|
141
173
|
*/
|
|
142
|
-
declare function endpoint(def: RouteDefinition): RouteDefinition
|
|
174
|
+
declare function endpoint<TResponse = unknown, TParams = unknown, TBody = unknown>(def: RouteDefinition<TResponse, TParams, TBody>): RouteDefinition<TResponse, TParams, TBody>;
|
|
143
175
|
|
|
144
176
|
type EndpointDefinition = RouteDefinition;
|
|
145
177
|
interface ResourceConfig<TEndpoints extends Record<string, EndpointDefinition>> {
|
|
@@ -271,4 +303,4 @@ declare function mapKeysDeep<T>(value: T, keyCase: KeyCase): T;
|
|
|
271
303
|
declare function toCamelCase<T>(value: T): T;
|
|
272
304
|
declare function toSnakeCase<T>(value: T): T;
|
|
273
305
|
|
|
274
|
-
export { type ApiDefinition, type ApiResponse, type CallOptions, type CamelCasedPropertiesDeep, type CamelToSnake, type EndpointCallable, type EndpointDefinition$1 as EndpointDefinition, GenericService, type GenericServiceOptions, type HttpMethod, type Id, type KeyCase, type ParseResult, type ParserSchema, type QueryParams, type ResourceConfig, type ResourceDefinition, type RouteDefinition, type RouteMapper, type RouteParserSchema, type RouteSchema, type RouteSchemaMap, type RouteSchemaValue, type RouteTransform, type RouteTransformMap, type SchemaLike, type ServiceConfig, type SnakeCasedPropertiesDeep, type SnakeToCamel, type UnknownRecord, camelToSnakeKey, createClient$1 as createClient, createClient as createHttpClient, createService, defineApi, endpoint, generateHooks, mapKeysDeep, parseWithSchema, resource, snakeToCamelKey, toCamelCase, toSnakeCase };
|
|
306
|
+
export { type ApiDefinition, type ApiError, type ApiResponse, type CallOptions, type CamelCasedPropertiesDeep, type CamelToSnake, type EndpointCallable, type EndpointCallableOptions, type EndpointDefinition$1 as EndpointDefinition, GenericService, type GenericServiceOptions, type HttpMethod, type Id, type KeyCase, type OptionalIfEmpty, type ParseResult, type ParserSchema, type QueryParams, type ResourceConfig, type ResourceDefinition, type RouteDefinition, type RouteMapper, type RouteParserSchema, type RouteSchema, type RouteSchemaMap, type RouteSchemaValue, type RouteTransform, type RouteTransformMap, type SchemaLike, type ServiceConfig, type SnakeCasedPropertiesDeep, type SnakeToCamel, type UnknownRecord, camelToSnakeKey, createClient$1 as createClient, createClient as createHttpClient, createService, defineApi, endpoint, generateHooks, mapKeysDeep, parseWithSchema, resource, snakeToCamelKey, toCamelCase, toSnakeCase };
|
package/dist/sdk.d.ts
CHANGED
|
@@ -7,6 +7,14 @@ interface ServiceConfig {
|
|
|
7
7
|
timeout?: number;
|
|
8
8
|
retry?: RetryConfig;
|
|
9
9
|
cache?: boolean;
|
|
10
|
+
validateResponse?: boolean;
|
|
11
|
+
onValidationError?: (error: unknown, context: {
|
|
12
|
+
endpoint: string;
|
|
13
|
+
method: string;
|
|
14
|
+
path: string;
|
|
15
|
+
request: unknown;
|
|
16
|
+
response: unknown;
|
|
17
|
+
}) => void;
|
|
10
18
|
}
|
|
11
19
|
interface RetryConfig {
|
|
12
20
|
attempts: number;
|
|
@@ -16,6 +24,7 @@ interface RetryConfig {
|
|
|
16
24
|
|
|
17
25
|
declare class HttpClient {
|
|
18
26
|
private client;
|
|
27
|
+
readonly config: ServiceConfig;
|
|
19
28
|
constructor(config: ServiceConfig);
|
|
20
29
|
private setupInterceptors;
|
|
21
30
|
setToken(token: string): void;
|
|
@@ -56,11 +65,15 @@ interface RouteSchemaMap {
|
|
|
56
65
|
}
|
|
57
66
|
type RouteSchemaValue = RouteTransform | RouteParserSchema;
|
|
58
67
|
type RouteSchema = RouteSchemaValue | RouteSchemaMap;
|
|
59
|
-
interface
|
|
68
|
+
interface ResponseSchema<T> {
|
|
69
|
+
parse(input: unknown): T;
|
|
70
|
+
}
|
|
71
|
+
interface RouteDefinition<TResponse = unknown, TParams = unknown, TBody = unknown> {
|
|
60
72
|
method: HttpMethod;
|
|
61
73
|
path: string;
|
|
62
74
|
auth?: boolean;
|
|
63
75
|
schema?: RouteSchema;
|
|
76
|
+
responseSchema?: ResponseSchema<TResponse>;
|
|
64
77
|
mapper?: RouteMapper;
|
|
65
78
|
headers?: Record<string, string>;
|
|
66
79
|
cache?: unknown;
|
|
@@ -68,10 +81,13 @@ interface RouteDefinition {
|
|
|
68
81
|
body?: Record<string, any>;
|
|
69
82
|
params?: Record<string, any>;
|
|
70
83
|
query?: Record<string, any>;
|
|
84
|
+
_typeResponse?: TResponse;
|
|
85
|
+
_typeParams?: TParams;
|
|
86
|
+
_typeBody?: TBody;
|
|
71
87
|
}
|
|
72
88
|
interface ApiDefinition {
|
|
73
89
|
[group: string]: {
|
|
74
|
-
[action: string]: RouteDefinition
|
|
90
|
+
[action: string]: RouteDefinition<any, any, any>;
|
|
75
91
|
};
|
|
76
92
|
}
|
|
77
93
|
|
|
@@ -99,21 +115,37 @@ declare class TokenManager {
|
|
|
99
115
|
exists(): boolean;
|
|
100
116
|
}
|
|
101
117
|
|
|
102
|
-
type CallOptions = {
|
|
103
|
-
params?:
|
|
118
|
+
type CallOptions<TParams = unknown, TBody = unknown> = {
|
|
119
|
+
params?: TParams;
|
|
104
120
|
query?: Record<string, any>;
|
|
105
|
-
body?:
|
|
121
|
+
body?: TBody;
|
|
106
122
|
headers?: Record<string, string>;
|
|
107
123
|
};
|
|
108
|
-
|
|
109
|
-
|
|
124
|
+
type EndpointCallableOptions<TParams, TBody> = (unknown extends TParams ? {} : {
|
|
125
|
+
params: TParams;
|
|
126
|
+
}) & (unknown extends TBody ? {} : {
|
|
127
|
+
body: TBody;
|
|
128
|
+
}) & {
|
|
129
|
+
query?: Record<string, any>;
|
|
130
|
+
headers?: Record<string, string>;
|
|
131
|
+
};
|
|
132
|
+
type OptionalIfEmpty<T> = keyof Omit<T, 'query' | 'headers'> extends never ? [options?: T] : [options: T];
|
|
133
|
+
interface ApiError {
|
|
134
|
+
message: string;
|
|
135
|
+
status?: number;
|
|
136
|
+
errors?: Record<string, string[]>;
|
|
137
|
+
}
|
|
138
|
+
interface EndpointCallable<TResponse = unknown, TParams = unknown, TBody = unknown> {
|
|
139
|
+
(...args: OptionalIfEmpty<EndpointCallableOptions<TParams, TBody>>): Promise<TResponse>;
|
|
110
140
|
/** Original RouteDefinition — used by useApiQuery / useApiMutation */
|
|
111
|
-
$def: RouteDefinition
|
|
141
|
+
$def: RouteDefinition<TResponse, TParams, TBody>;
|
|
112
142
|
/** Stable TanStack query key: [group, action] */
|
|
113
143
|
$key: string[];
|
|
144
|
+
/** Consistent query key builder that incorporates params/query if provided */
|
|
145
|
+
$queryKey: (...args: OptionalIfEmpty<EndpointCallableOptions<TParams, TBody>>) => unknown[];
|
|
114
146
|
}
|
|
115
|
-
type ApiGroupProxy<G extends Record<string, RouteDefinition
|
|
116
|
-
[K in keyof G]: EndpointCallable
|
|
147
|
+
type ApiGroupProxy<G extends Record<string, RouteDefinition<any, any, any>>> = {
|
|
148
|
+
[K in keyof G]: EndpointCallable<G[K] extends RouteDefinition<infer R, any, any> ? R : unknown, G[K] extends RouteDefinition<any, infer P, any> ? P : unknown, G[K] extends RouteDefinition<any, any, infer B> ? B : unknown>;
|
|
117
149
|
};
|
|
118
150
|
type ApiProxy<T extends ApiDefinition> = {
|
|
119
151
|
[G in keyof T]: ApiGroupProxy<T[G]>;
|
|
@@ -139,7 +171,7 @@ type EndpointDefinition$1 = RouteDefinition;
|
|
|
139
171
|
* const { data } = useApiQuery(api.cart.list)
|
|
140
172
|
* const mutation = useApiMutation(api.cart.create)
|
|
141
173
|
*/
|
|
142
|
-
declare function endpoint(def: RouteDefinition): RouteDefinition
|
|
174
|
+
declare function endpoint<TResponse = unknown, TParams = unknown, TBody = unknown>(def: RouteDefinition<TResponse, TParams, TBody>): RouteDefinition<TResponse, TParams, TBody>;
|
|
143
175
|
|
|
144
176
|
type EndpointDefinition = RouteDefinition;
|
|
145
177
|
interface ResourceConfig<TEndpoints extends Record<string, EndpointDefinition>> {
|
|
@@ -271,4 +303,4 @@ declare function mapKeysDeep<T>(value: T, keyCase: KeyCase): T;
|
|
|
271
303
|
declare function toCamelCase<T>(value: T): T;
|
|
272
304
|
declare function toSnakeCase<T>(value: T): T;
|
|
273
305
|
|
|
274
|
-
export { type ApiDefinition, type ApiResponse, type CallOptions, type CamelCasedPropertiesDeep, type CamelToSnake, type EndpointCallable, type EndpointDefinition$1 as EndpointDefinition, GenericService, type GenericServiceOptions, type HttpMethod, type Id, type KeyCase, type ParseResult, type ParserSchema, type QueryParams, type ResourceConfig, type ResourceDefinition, type RouteDefinition, type RouteMapper, type RouteParserSchema, type RouteSchema, type RouteSchemaMap, type RouteSchemaValue, type RouteTransform, type RouteTransformMap, type SchemaLike, type ServiceConfig, type SnakeCasedPropertiesDeep, type SnakeToCamel, type UnknownRecord, camelToSnakeKey, createClient$1 as createClient, createClient as createHttpClient, createService, defineApi, endpoint, generateHooks, mapKeysDeep, parseWithSchema, resource, snakeToCamelKey, toCamelCase, toSnakeCase };
|
|
306
|
+
export { type ApiDefinition, type ApiError, type ApiResponse, type CallOptions, type CamelCasedPropertiesDeep, type CamelToSnake, type EndpointCallable, type EndpointCallableOptions, type EndpointDefinition$1 as EndpointDefinition, GenericService, type GenericServiceOptions, type HttpMethod, type Id, type KeyCase, type OptionalIfEmpty, type ParseResult, type ParserSchema, type QueryParams, type ResourceConfig, type ResourceDefinition, type RouteDefinition, type RouteMapper, type RouteParserSchema, type RouteSchema, type RouteSchemaMap, type RouteSchemaValue, type RouteTransform, type RouteTransformMap, type SchemaLike, type ServiceConfig, type SnakeCasedPropertiesDeep, type SnakeToCamel, type UnknownRecord, camelToSnakeKey, createClient$1 as createClient, createClient as createHttpClient, createService, defineApi, endpoint, generateHooks, mapKeysDeep, parseWithSchema, resource, snakeToCamelKey, toCamelCase, toSnakeCase };
|
package/dist/sdk.js
CHANGED
|
@@ -87,6 +87,7 @@ function snakeCaseKeys(obj) {
|
|
|
87
87
|
var import_axios = __toESM(require("axios"));
|
|
88
88
|
var HttpClient = class {
|
|
89
89
|
constructor(config) {
|
|
90
|
+
this.config = config;
|
|
90
91
|
this.client = import_axios.default.create({
|
|
91
92
|
baseURL: config.baseURL,
|
|
92
93
|
timeout: config.timeout ?? 1e4,
|
|
@@ -344,14 +345,35 @@ function defineApi(definition, config) {
|
|
|
344
345
|
} else {
|
|
345
346
|
response = await client[method](resolvedPath, body, requestConfig);
|
|
346
347
|
}
|
|
348
|
+
if (client.config.validateResponse && route.responseSchema) {
|
|
349
|
+
try {
|
|
350
|
+
response = route.responseSchema.parse(response);
|
|
351
|
+
} catch (error) {
|
|
352
|
+
if (client.config.onValidationError) {
|
|
353
|
+
client.config.onValidationError(error, {
|
|
354
|
+
endpoint: action,
|
|
355
|
+
method: route.method,
|
|
356
|
+
path: resolvedPath,
|
|
357
|
+
request: { params, query, body, headers: requestConfig.headers },
|
|
358
|
+
response
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
throw error;
|
|
362
|
+
}
|
|
363
|
+
} else if (client.config.validateResponse) {
|
|
364
|
+
response = parseRouteSchema(route, "response", response);
|
|
365
|
+
}
|
|
347
366
|
return applyMapper(
|
|
348
367
|
route,
|
|
349
368
|
"response",
|
|
350
|
-
|
|
369
|
+
response
|
|
351
370
|
);
|
|
352
371
|
};
|
|
353
372
|
callable.$def = route;
|
|
354
373
|
callable.$key = [group, action];
|
|
374
|
+
callable.$queryKey = (options) => {
|
|
375
|
+
return options ? [group, action, options] : [group, action];
|
|
376
|
+
};
|
|
355
377
|
groupProxy[action] = callable;
|
|
356
378
|
}
|
|
357
379
|
;
|
package/dist/sdk.mjs
CHANGED
|
@@ -45,6 +45,7 @@ function snakeCaseKeys(obj) {
|
|
|
45
45
|
import axios from "axios";
|
|
46
46
|
var HttpClient = class {
|
|
47
47
|
constructor(config) {
|
|
48
|
+
this.config = config;
|
|
48
49
|
this.client = axios.create({
|
|
49
50
|
baseURL: config.baseURL,
|
|
50
51
|
timeout: config.timeout ?? 1e4,
|
|
@@ -302,14 +303,35 @@ function defineApi(definition, config) {
|
|
|
302
303
|
} else {
|
|
303
304
|
response = await client[method](resolvedPath, body, requestConfig);
|
|
304
305
|
}
|
|
306
|
+
if (client.config.validateResponse && route.responseSchema) {
|
|
307
|
+
try {
|
|
308
|
+
response = route.responseSchema.parse(response);
|
|
309
|
+
} catch (error) {
|
|
310
|
+
if (client.config.onValidationError) {
|
|
311
|
+
client.config.onValidationError(error, {
|
|
312
|
+
endpoint: action,
|
|
313
|
+
method: route.method,
|
|
314
|
+
path: resolvedPath,
|
|
315
|
+
request: { params, query, body, headers: requestConfig.headers },
|
|
316
|
+
response
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
throw error;
|
|
320
|
+
}
|
|
321
|
+
} else if (client.config.validateResponse) {
|
|
322
|
+
response = parseRouteSchema(route, "response", response);
|
|
323
|
+
}
|
|
305
324
|
return applyMapper(
|
|
306
325
|
route,
|
|
307
326
|
"response",
|
|
308
|
-
|
|
327
|
+
response
|
|
309
328
|
);
|
|
310
329
|
};
|
|
311
330
|
callable.$def = route;
|
|
312
331
|
callable.$key = [group, action];
|
|
332
|
+
callable.$queryKey = (options) => {
|
|
333
|
+
return options ? [group, action, options] : [group, action];
|
|
334
|
+
};
|
|
313
335
|
groupProxy[action] = callable;
|
|
314
336
|
}
|
|
315
337
|
;
|
package/dist/vue.d.mts
CHANGED
|
@@ -9,6 +9,14 @@ interface ServiceConfig {
|
|
|
9
9
|
timeout?: number;
|
|
10
10
|
retry?: RetryConfig;
|
|
11
11
|
cache?: boolean;
|
|
12
|
+
validateResponse?: boolean;
|
|
13
|
+
onValidationError?: (error: unknown, context: {
|
|
14
|
+
endpoint: string;
|
|
15
|
+
method: string;
|
|
16
|
+
path: string;
|
|
17
|
+
request: unknown;
|
|
18
|
+
response: unknown;
|
|
19
|
+
}) => void;
|
|
12
20
|
}
|
|
13
21
|
interface RetryConfig {
|
|
14
22
|
attempts: number;
|
|
@@ -18,6 +26,7 @@ interface RetryConfig {
|
|
|
18
26
|
|
|
19
27
|
declare class HttpClient {
|
|
20
28
|
private client;
|
|
29
|
+
readonly config: ServiceConfig;
|
|
21
30
|
constructor(config: ServiceConfig);
|
|
22
31
|
private setupInterceptors;
|
|
23
32
|
setToken(token: string): void;
|
package/dist/vue.d.ts
CHANGED
|
@@ -9,6 +9,14 @@ interface ServiceConfig {
|
|
|
9
9
|
timeout?: number;
|
|
10
10
|
retry?: RetryConfig;
|
|
11
11
|
cache?: boolean;
|
|
12
|
+
validateResponse?: boolean;
|
|
13
|
+
onValidationError?: (error: unknown, context: {
|
|
14
|
+
endpoint: string;
|
|
15
|
+
method: string;
|
|
16
|
+
path: string;
|
|
17
|
+
request: unknown;
|
|
18
|
+
response: unknown;
|
|
19
|
+
}) => void;
|
|
12
20
|
}
|
|
13
21
|
interface RetryConfig {
|
|
14
22
|
attempts: number;
|
|
@@ -18,6 +26,7 @@ interface RetryConfig {
|
|
|
18
26
|
|
|
19
27
|
declare class HttpClient {
|
|
20
28
|
private client;
|
|
29
|
+
readonly config: ServiceConfig;
|
|
21
30
|
constructor(config: ServiceConfig);
|
|
22
31
|
private setupInterceptors;
|
|
23
32
|
setToken(token: string): void;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "routesync",
|
|
3
|
-
"version": "1.0.
|
|
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",
|
|
@@ -61,7 +61,8 @@
|
|
|
61
61
|
"@types/node": "^20.0.0",
|
|
62
62
|
"tsup": "^8.0.0",
|
|
63
63
|
"turbo": "^2.9.16",
|
|
64
|
-
"typescript": "^5.4.0"
|
|
64
|
+
"typescript": "^5.4.0",
|
|
65
|
+
"vitest": "^4.1.7"
|
|
65
66
|
},
|
|
66
67
|
"engines": {
|
|
67
68
|
"node": ">=20.0.0"
|