vue-api-kit 1.1.1 → 1.3.0

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/README.md CHANGED
@@ -34,6 +34,23 @@ const api = createApiClient({
34
34
  name: z.string(),
35
35
  email: z.string()
36
36
  })
37
+ },
38
+ // POST query for complex searches
39
+ searchUsers: {
40
+ method: 'POST',
41
+ path: '/users/search',
42
+ data: z.object({
43
+ query: z.string(),
44
+ filters: z.object({
45
+ active: z.boolean().optional(),
46
+ role: z.string().optional()
47
+ }).optional()
48
+ }),
49
+ response: z.array(z.object({
50
+ id: z.number(),
51
+ name: z.string(),
52
+ email: z.string()
53
+ }))
37
54
  }
38
55
  },
39
56
  mutations: {
@@ -70,7 +87,11 @@ const api = createApiClient({
70
87
 
71
88
  ## 📖 Usage in Vue Components
72
89
 
73
- ### Queries (GET requests)
90
+ ### Queries (GET and POST requests)
91
+
92
+ Queries support both GET and POST methods, allowing you to fetch data with complex search criteria.
93
+
94
+ #### GET Queries
74
95
 
75
96
  ```vue
76
97
  <script setup lang="ts">
@@ -111,6 +132,51 @@ const { result: data } = api.query.getUsers({
111
132
  </template>
112
133
  ```
113
134
 
135
+ #### POST Queries
136
+
137
+ POST queries are perfect for complex searches, filtering, or any operation that requires sending data in the request body.
138
+
139
+ ```vue
140
+ <script setup lang="ts">
141
+ import { api } from './api';
142
+ import { ref } from 'vue';
143
+
144
+ const searchTerm = ref('');
145
+
146
+ const { result, isLoading, refetch } = api.query.searchUsers({
147
+ data: {
148
+ query: searchTerm.value,
149
+ filters: {
150
+ active: true,
151
+ role: 'admin'
152
+ }
153
+ },
154
+ loadOnMount: false,
155
+ onResult: (data) => {
156
+ console.log('Search results:', data);
157
+ }
158
+ });
159
+
160
+ const handleSearch = () => {
161
+ refetch();
162
+ };
163
+ </script>
164
+
165
+ <template>
166
+ <div>
167
+ <input v-model="searchTerm" @keyup.enter="handleSearch" />
168
+ <button @click="handleSearch" :disabled="isLoading">Search</button>
169
+
170
+ <div v-if="isLoading">Searching...</div>
171
+ <div v-else-if="result">
172
+ <div v-for="user in result" :key="user.id">
173
+ {{ user.name }}
174
+ </div>
175
+ </div>
176
+ </div>
177
+ </template>
178
+ ```
179
+
114
180
  ### Mutations (POST, PUT, DELETE)
115
181
 
116
182
  ```vue
@@ -155,12 +221,16 @@ async function handleSubmit() {
155
221
  - ✅ **Type-Safe**: Full TypeScript support with automatic type inference
156
222
  - ✅ **Zod Validation**: Built-in request/response validation
157
223
  - ✅ **Vue 3 Composition API**: Reactive state management
224
+ - ✅ **Lightweight**: ~7kB minified (2.2kB gzipped) - optimized for production
158
225
  - ✅ **Auto Loading States**: Built-in loading, error, and success states
159
- - ✅ **File Upload**: Support for multipart/form-data
226
+ - ✅ **POST Queries**: Support for both GET and POST methods in queries for complex data retrieval
227
+ - ✅ **File Upload**: Support for multipart/form-data in mutations
160
228
  - ✅ **Path Parameters**: Automatic path parameter replacement
161
229
  - ✅ **Debouncing**: Built-in request debouncing
162
230
  - ✅ **Global Error Handling**: Centralized error management
163
231
  - ✅ **Request Interceptors**: Modify requests before sending
232
+ - ✅ **Fully Typed**: Complete type inference for params, data, and response
233
+ - ✅ **Tree-Shakeable**: Only bundles what you use
164
234
 
165
235
  ## 🔧 Advanced Configuration
166
236
 
@@ -207,6 +277,8 @@ const api = createApiClient({
207
277
 
208
278
  ## 📤 File Upload Example
209
279
 
280
+ File uploads are supported in mutations using the `isMultipart` flag.
281
+
210
282
  ```typescript
211
283
  const api = createApiClient({
212
284
  baseURL: 'https://api.example.com',
@@ -230,7 +302,7 @@ const { mutate, uploadProgress } = api.mutation.uploadImage({
230
302
  });
231
303
 
232
304
  async function handleUpload(file: File) {
233
- await mutate({ file });
305
+ await mutate({ data: { file } });
234
306
  }
235
307
  ```
236
308
 
@@ -42,6 +42,6 @@ import { ApiClientOptions, ApiMutation, ApiQuery, Infer, MutationResult, QueryRe
42
42
  * const { mutate } = api.mutation.createUser();
43
43
  */
44
44
  export declare function createApiClient<Q extends Record<string, ApiQuery>, M extends Record<string, ApiMutation>>(options: ApiClientOptions<Q, M>): {
45
- query: { [K in keyof Q]: (options?: UseQueryOptions<Infer<Q[K]["params"]>, Infer<Q[K]["response"]>>) => QueryResult<Infer<Q[K]["response"]>>; };
45
+ query: { [K in keyof Q]: (options?: UseQueryOptions<Infer<Q[K]["params"]>, Infer<Q[K]["data"]>, Infer<Q[K]["response"]>>) => QueryResult<Infer<Q[K]["response"]>>; };
46
46
  mutation: { [K_1 in keyof M]: (options?: UseMutationOptions<Infer<M[K_1]["response"]>>) => MutationResult<Infer<M[K_1]["response"]>, Infer<M[K_1]["data"]>, Infer<M[K_1]["params"]>>; };
47
47
  };
@@ -17,8 +17,9 @@ export type HTTPMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
17
17
  */
18
18
  export type Infer<T> = T extends ZodType<infer U> ? U : any;
19
19
  /**
20
- * Defines a query (GET request) endpoint configuration
21
- * @template TParams - Zod schema for query parameters
20
+ * Defines a query endpoint configuration (supports GET and POST methods)
21
+ * @template TParams - Zod schema for query/path parameters
22
+ * @template TData - Zod schema for request body (POST only)
22
23
  * @template TResponse - Zod schema for response data
23
24
  * @example
24
25
  * const getUsers: ApiQuery = {
@@ -27,11 +28,19 @@ export type Infer<T> = T extends ZodType<infer U> ? U : any;
27
28
  * params: z.object({ page: z.number() }),
28
29
  * response: z.array(z.object({ id: z.number(), name: z.string() }))
29
30
  * };
31
+ * @example
32
+ * const searchUsers: ApiQuery = {
33
+ * method: "POST",
34
+ * path: "/users/search",
35
+ * data: z.object({ query: z.string() }),
36
+ * response: z.array(z.object({ id: z.number(), name: z.string() }))
37
+ * };
30
38
  */
31
- export interface ApiQuery<TParams extends ZodType<any> | undefined = ZodType<any> | undefined, TResponse extends ZodType<any> | undefined = ZodType<any> | undefined> {
32
- method?: Extract<HTTPMethod, "GET">;
39
+ export interface ApiQuery<TParams extends ZodType<any> | undefined = ZodType<any> | undefined, TData extends ZodType<any> | undefined = ZodType<any> | undefined, TResponse extends ZodType<any> | undefined = ZodType<any> | undefined> {
40
+ method?: Extract<HTTPMethod, "GET" | "POST">;
33
41
  path: string;
34
42
  params?: TParams;
43
+ data?: TData;
35
44
  response?: TResponse;
36
45
  }
37
46
  /**
@@ -88,6 +97,7 @@ export interface ApiClientOptions<Q extends Record<string, ApiQuery> = Record<st
88
97
  /**
89
98
  * Options for configuring a query hook
90
99
  * @template TParams - Type of query parameters
100
+ * @template TData - Type of request body data (for POST queries)
91
101
  * @template TResult - Type of result data
92
102
  * @example
93
103
  * const options: UseQueryOptions = {
@@ -97,14 +107,22 @@ export interface ApiClientOptions<Q extends Record<string, ApiQuery> = Record<st
97
107
  * onResult: (data) => console.log(data),
98
108
  * onError: (error) => console.error(error)
99
109
  * };
110
+ * @example
111
+ * const options: UseQueryOptions = {
112
+ * data: { query: "search term" },
113
+ * loadOnMount: true,
114
+ * onResult: (data) => console.log(data)
115
+ * };
100
116
  */
101
- export interface UseQueryOptions<TParams = any, TResult = any> {
117
+ export interface UseQueryOptions<TParams = any, TData = any, TResult = any> {
102
118
  params?: TParams;
119
+ data?: TData;
103
120
  loadOnMount?: boolean;
104
121
  debounce?: number;
105
122
  onResult?: (result: TResult) => void;
106
123
  onError?: (error: AxiosError | ZodError | Error) => void;
107
124
  onZodError?: (issues: Omit<$ZodIssue, "input">[]) => void;
125
+ onUploadProgress?: (progress: number) => void;
108
126
  }
109
127
  /**
110
128
  * Options for configuring a mutation hook
@@ -131,6 +149,7 @@ export interface UseMutationOptions<TResult = any> {
131
149
  * // isLoading.value indicates loading state
132
150
  * // errorMessage.value contains any error message
133
151
  * // refetch() to manually trigger a new request
152
+ * // uploadProgress.value shows upload progress (0-100) for POST queries with file uploads
134
153
  */
135
154
  export interface QueryResult<TResult> {
136
155
  result: Ref<TResult | undefined>;
@@ -138,6 +157,7 @@ export interface QueryResult<TResult> {
138
157
  zodErrors: Ref<Omit<$ZodIssue, "input">[] | undefined>;
139
158
  isLoading: Ref<boolean>;
140
159
  isDone: Ref<boolean>;
160
+ uploadProgress: Ref<number>;
141
161
  refetch: () => Promise<void>;
142
162
  }
143
163
  /**