vue-api-kit 1.3.0 → 1.4.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
@@ -1,5 +1,14 @@
1
+
2
+
1
3
  # 🚀 vue-api-kit
2
4
 
5
+ [![NPM Version](https://img.shields.io/npm/v/vue-api-kit.svg?style=flat-square)](https://www.npmjs.com/package/vue-api-kit)
6
+ [![Install Size](https://img.shields.io/badge/dynamic/json?url=https://packagephobia.com/v2/api.json?p=vue-api-kit&query=$.install.pretty&label=install%20size&style=flat-square)](https://packagephobia.now.sh/result?p=vue-api-kit)
7
+ [![Bundle Size](https://img.shields.io/bundlephobia/minzip/vue-api-kit?style=flat-square)](https://bundlephobia.com/result?p=vue-api-kit)
8
+ [![NPM Downloads](https://img.shields.io/npm/dm/vue-api-kit.svg?style=flat-square)](https://npm-stat.com/charts.html?package=vue-api-kit)
9
+ [![CI Status](https://img.shields.io/github/actions/workflow/status/MelvishNiz/vue-api-kit/release.yml?label=CI&logo=github&style=flat-square)](https://github.com/MelvishNiz/vue-api-kit/actions)
10
+ [![License](https://img.shields.io/npm/l/vue-api-kit.svg?style=flat-square)](https://github.com/MelvishNiz/vue-api-kit/blob/main/LICENSE)
11
+
3
12
  A powerful and type-safe API client for Vue 3 applications with built-in validation using Zod.
4
13
 
5
14
  ## 📦 Installation
@@ -166,7 +175,7 @@ const handleSearch = () => {
166
175
  <div>
167
176
  <input v-model="searchTerm" @keyup.enter="handleSearch" />
168
177
  <button @click="handleSearch" :disabled="isLoading">Search</button>
169
-
178
+
170
179
  <div v-if="isLoading">Searching...</div>
171
180
  <div v-else-if="result">
172
181
  <div v-for="user in result" :key="user.id">
@@ -224,6 +233,7 @@ async function handleSubmit() {
224
233
  - ✅ **Lightweight**: ~7kB minified (2.2kB gzipped) - optimized for production
225
234
  - ✅ **Auto Loading States**: Built-in loading, error, and success states
226
235
  - ✅ **POST Queries**: Support for both GET and POST methods in queries for complex data retrieval
236
+ - ✅ **Modular APIs**: Merge queries and mutations from separate files with full type safety
227
237
  - ✅ **File Upload**: Support for multipart/form-data in mutations
228
238
  - ✅ **Path Parameters**: Automatic path parameter replacement
229
239
  - ✅ **Debouncing**: Built-in request debouncing
@@ -275,6 +285,138 @@ const api = createApiClient({
275
285
  });
276
286
  ```
277
287
 
288
+ ## 🧩 Modular API Definitions
289
+
290
+ For large applications, you can organize your API definitions into separate files and merge them together with full type safety.
291
+
292
+ ### Step 1: Define API modules in separate files
293
+
294
+ **user-api.ts** - User-related queries and mutations
295
+ ```typescript
296
+ import { z, defineQuery, defineMutation } from 'vue-api-kit';
297
+
298
+ export const userQueries = {
299
+ getUsers: defineQuery({
300
+ method: 'GET',
301
+ path: '/users',
302
+ response: z.array(z.object({
303
+ id: z.number(),
304
+ name: z.string(),
305
+ email: z.string().email()
306
+ }))
307
+ }),
308
+ getUser: defineQuery({
309
+ method: 'GET',
310
+ path: '/users/{id}',
311
+ params: z.object({ id: z.number() }),
312
+ response: z.object({
313
+ id: z.number(),
314
+ name: z.string(),
315
+ email: z.string().email()
316
+ })
317
+ })
318
+ };
319
+
320
+ export const userMutations = {
321
+ createUser: defineMutation({
322
+ method: 'POST',
323
+ path: '/users',
324
+ data: z.object({
325
+ name: z.string(),
326
+ email: z.string().email()
327
+ }),
328
+ response: z.object({
329
+ id: z.number(),
330
+ name: z.string(),
331
+ email: z.string().email()
332
+ })
333
+ }),
334
+ updateUser: defineMutation({
335
+ method: 'PUT',
336
+ path: '/users/{id}',
337
+ params: z.object({ id: z.number() }),
338
+ data: z.object({
339
+ name: z.string().optional(),
340
+ email: z.string().email().optional()
341
+ }),
342
+ response: z.object({
343
+ id: z.number(),
344
+ name: z.string(),
345
+ email: z.string().email()
346
+ })
347
+ })
348
+ };
349
+ ```
350
+
351
+ **post-api.ts** - Post-related queries and mutations
352
+ ```typescript
353
+ import { z, defineQuery, defineMutation } from 'vue-api-kit';
354
+
355
+ export const postQueries = {
356
+ getPosts: defineQuery({
357
+ method: 'GET',
358
+ path: '/posts',
359
+ response: z.array(z.object({
360
+ id: z.number(),
361
+ title: z.string(),
362
+ body: z.string()
363
+ }))
364
+ })
365
+ };
366
+
367
+ export const postMutations = {
368
+ createPost: defineMutation({
369
+ method: 'POST',
370
+ path: '/posts',
371
+ data: z.object({
372
+ title: z.string(),
373
+ body: z.string()
374
+ }),
375
+ response: z.object({
376
+ id: z.number(),
377
+ title: z.string(),
378
+ body: z.string()
379
+ })
380
+ })
381
+ };
382
+ ```
383
+
384
+ ### Step 2: Merge API definitions
385
+
386
+ **api.ts** - Main API client with merged definitions
387
+ ```typescript
388
+ import { createApiClient, mergeQueries, mergeMutations } from 'vue-api-kit';
389
+ import { userQueries, userMutations } from './user-api';
390
+ import { postQueries, postMutations } from './post-api';
391
+
392
+ // Approach 1: Merge queries and mutations separately
393
+ export const api = createApiClient({
394
+ baseURL: 'https://api.example.com',
395
+
396
+ // Merge all queries from different modules
397
+ queries: mergeQueries(userQueries, postQueries),
398
+
399
+ // Merge all mutations from different modules
400
+ mutations: mergeMutations(userMutations, postMutations)
401
+ });
402
+
403
+ // Now you can use all queries and mutations with full type safety!
404
+ // api.query.getUsers() ✓ Fully typed
405
+ // api.query.getPosts() ✓ Fully typed
406
+ // api.mutation.createUser ✓ Fully typed
407
+ // api.mutation.createPost ✓ Fully typed
408
+ ```
409
+
410
+ ### Benefits of Modular Approach
411
+
412
+ - **Separation of Concerns**: Keep related API endpoints together in dedicated files
413
+ - **Reusability**: Import and reuse API definitions across multiple clients
414
+ - **Team Collaboration**: Different team members can work on different API modules independently
415
+ - **Full Type Safety**: TypeScript infers all types correctly, no loss of type information when merging
416
+ - **No Manual Type Assertions**: Use `defineQuery()` and `defineMutation()` helpers instead of `as const`
417
+ - **Easy Testing**: Test individual API modules in isolation
418
+ - **Better Organization**: Manage large APIs without cluttering a single file
419
+
278
420
  ## 📤 File Upload Example
279
421
 
280
422
  File uploads are supported in mutations using the `isMultipart` flag.
@@ -0,0 +1,78 @@
1
+ import { ApiQuery, ApiMutation } from './types';
2
+ /**
3
+ * Helper function to define a query with proper type inference
4
+ * Eliminates the need for 'as const' assertions
5
+ * @template T - Query definition type
6
+ * @param query - Query definition object
7
+ * @returns The same query with proper type inference
8
+ * @example
9
+ * export const userQueries = {
10
+ * getUsers: defineQuery({
11
+ * method: 'GET',
12
+ * path: '/users',
13
+ * response: z.array(UserSchema)
14
+ * })
15
+ * };
16
+ */
17
+ export declare function defineQuery<T extends ApiQuery>(query: T): T;
18
+ /**
19
+ * Helper function to define a mutation with proper type inference
20
+ * Eliminates the need for 'as const' assertions
21
+ * @template T - Mutation definition type
22
+ * @param mutation - Mutation definition object
23
+ * @returns The same mutation with proper type inference
24
+ * @example
25
+ * export const userMutations = {
26
+ * createUser: defineMutation({
27
+ * method: 'POST',
28
+ * path: '/users',
29
+ * data: CreateUserSchema,
30
+ * response: UserSchema
31
+ * })
32
+ * };
33
+ */
34
+ export declare function defineMutation<T extends ApiMutation>(mutation: T): T;
35
+ /**
36
+ * Merges multiple query definitions into a single queries object with full type safety
37
+ * @template T - Array of query definition objects
38
+ * @param queryDefinitions - Array of query definition objects to merge
39
+ * @returns Combined queries object with all properties from input objects
40
+ * @example
41
+ * const userQueries = {
42
+ * getUsers: { path: '/users', response: z.array(UserSchema) },
43
+ * getUser: { path: '/users/{id}', params: z.object({ id: z.number() }), response: UserSchema }
44
+ * };
45
+ *
46
+ * const postQueries = {
47
+ * getPosts: { path: '/posts', response: z.array(PostSchema) }
48
+ * };
49
+ *
50
+ * const allQueries = mergeQueries(userQueries, postQueries);
51
+ * // Result: { getUsers, getUser, getPosts } with full type inference
52
+ */
53
+ export declare function mergeQueries<T extends Array<Record<string, ApiQuery>>>(...queryDefinitions: T): UnionToIntersection<T[number]>;
54
+ /**
55
+ * Merges multiple mutation definitions into a single mutations object with full type safety
56
+ * @template T - Array of mutation definition objects
57
+ * @param mutationDefinitions - Array of mutation definition objects to merge
58
+ * @returns Combined mutations object with all properties from input objects
59
+ * @example
60
+ * const userMutations = {
61
+ * createUser: { method: 'POST', path: '/users', data: CreateUserSchema, response: UserSchema },
62
+ * updateUser: { method: 'PUT', path: '/users/{id}', params: z.object({ id: z.number() }), data: UpdateUserSchema, response: UserSchema }
63
+ * };
64
+ *
65
+ * const postMutations = {
66
+ * createPost: { method: 'POST', path: '/posts', data: CreatePostSchema, response: PostSchema }
67
+ * };
68
+ *
69
+ * const allMutations = mergeMutations(userMutations, postMutations);
70
+ * // Result: { createUser, updateUser, createPost } with full type inference
71
+ */
72
+ export declare function mergeMutations<T extends Array<Record<string, ApiMutation>>>(...mutationDefinitions: T): UnionToIntersection<T[number]>;
73
+ /**
74
+ * Utility type to convert union types to intersection types
75
+ * This enables proper type merging for API definitions
76
+ */
77
+ type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
78
+ export {};
@@ -122,7 +122,6 @@ export interface UseQueryOptions<TParams = any, TData = any, TResult = any> {
122
122
  onResult?: (result: TResult) => void;
123
123
  onError?: (error: AxiosError | ZodError | Error) => void;
124
124
  onZodError?: (issues: Omit<$ZodIssue, "input">[]) => void;
125
- onUploadProgress?: (progress: number) => void;
126
125
  }
127
126
  /**
128
127
  * Options for configuring a mutation hook
@@ -157,7 +156,6 @@ export interface QueryResult<TResult> {
157
156
  zodErrors: Ref<Omit<$ZodIssue, "input">[] | undefined>;
158
157
  isLoading: Ref<boolean>;
159
158
  isDone: Ref<boolean>;
160
- uploadProgress: Ref<number>;
161
159
  refetch: () => Promise<void>;
162
160
  }
163
161
  /**
package/dist/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  export * as z from 'zod';
2
2
  export { createApiClient } from './core/client';
3
+ export { mergeQueries, mergeMutations, defineQuery, defineMutation } from './core/merge';
3
4
  export type * from './core/types';
4
5
  export type { ZodError } from 'zod';
5
6
  export { AxiosError } from 'axios';
package/dist/index.js CHANGED
@@ -1,173 +1,168 @@
1
- import { ZodError as w } from "zod";
1
+ import { ZodError as P } from "zod";
2
2
  import * as k from "zod";
3
- import S, { AxiosError as L } from "axios";
4
- import { AxiosError as J } from "axios";
5
- import { nextTick as U, ref as d, onMounted as x, watch as N, onBeforeUnmount as T } from "vue";
3
+ import L, { AxiosError as w } from "axios";
4
+ import { AxiosError as G } from "axios";
5
+ import { nextTick as S, ref as m, onMounted as x, watch as N, onBeforeUnmount as T } from "vue";
6
6
  import { debounce as Z } from "lodash-es";
7
- function z(t) {
8
- const g = S.create({
9
- baseURL: t.baseURL,
7
+ function I(r) {
8
+ const g = L.create({
9
+ baseURL: r.baseURL,
10
10
  headers: {
11
11
  "Content-Type": "application/json",
12
12
  Accept: "application/json",
13
- ...t.headers
13
+ ...r.headers
14
14
  },
15
- withCredentials: t.withCredentials ?? !1
15
+ withCredentials: r.withCredentials ?? !1
16
16
  });
17
- t.onBeforeRequest && g.interceptors.request.use(
17
+ r.onBeforeRequest && g.interceptors.request.use(
18
18
  async (e) => {
19
19
  try {
20
- return await t.onBeforeRequest(e) || e;
21
- } catch (r) {
22
- return Promise.reject(r);
20
+ return await r.onBeforeRequest(e) || e;
21
+ } catch (a) {
22
+ return Promise.reject(a);
23
23
  }
24
24
  },
25
25
  (e) => Promise.reject(e)
26
- ), t.onStartRequest && g.interceptors.request.use(
26
+ ), r.onStartRequest && g.interceptors.request.use(
27
27
  async (e) => {
28
28
  try {
29
- return await t.onStartRequest(), e;
30
- } catch (r) {
31
- return Promise.reject(r);
29
+ return await r.onStartRequest(), e;
30
+ } catch (a) {
31
+ return Promise.reject(a);
32
32
  }
33
33
  },
34
34
  (e) => Promise.reject(e)
35
- ), t.onFinishRequest && g.interceptors.response.use(
36
- (e) => (t.onFinishRequest(), e),
35
+ ), r.onFinishRequest && g.interceptors.response.use(
36
+ (e) => (r.onFinishRequest(), e),
37
37
  (e) => Promise.reject(e)
38
38
  ), g.interceptors.request.use((e) => {
39
39
  if (!e.url) return e;
40
- const r = (n) => {
41
- if (n)
42
- for (const [a, p] of Object.entries(n)) {
43
- const i = `{${a}}`;
44
- e.url.includes(i) && (e.url = e.url.replace(
45
- i,
46
- encodeURIComponent(String(p))
47
- ), delete n[a]);
40
+ const a = (o) => {
41
+ if (o)
42
+ for (const [t, v] of Object.entries(o)) {
43
+ const l = `{${t}}`;
44
+ e.url.includes(l) && (e.url = e.url.replace(
45
+ l,
46
+ encodeURIComponent(String(v))
47
+ ), delete o[t]);
48
48
  }
49
49
  };
50
- return e.method !== "get" && e.data?.params && r(e.data.params), r(e.params), e;
50
+ return e.method !== "get" && e.data?.params && a(e.data.params), a(e.params), e;
51
51
  }), g.interceptors.response.use(
52
52
  (e) => e,
53
- (e) => (U(() => {
53
+ (e) => (S(() => {
54
54
  e.code;
55
55
  }), Promise.reject(e))
56
56
  );
57
- const b = t.queries ?? {}, C = {};
58
- for (const e in b) {
59
- const r = b[e];
60
- r && (C[e] = (n) => {
61
- let a;
62
- n && typeof n == "object" && ("loadOnMount" in n || "debounce" in n || "onResult" in n || "onError" in n || "data" in n ? a = n : a = { params: n });
63
- const p = d(), i = d(), v = d(), q = d(!1), y = d(!1), A = d(0), P = d(!0);
64
- let u = new AbortController();
65
- const f = () => {
66
- u?.abort(), u = new AbortController();
67
- }, m = async () => {
68
- q.value && f(), q.value = !0, i.value = void 0, A.value = 0;
57
+ const j = r.queries ?? {}, C = {};
58
+ for (const e in j) {
59
+ const a = j[e];
60
+ a && (C[e] = (o) => {
61
+ let t;
62
+ o && typeof o == "object" && ("loadOnMount" in o || "debounce" in o || "onResult" in o || "onError" in o || "data" in o ? t = o : t = { params: o });
63
+ const v = m(), l = m(), E = m(), R = m(!1), y = m(!1), A = m(!0);
64
+ let q = new AbortController();
65
+ const u = () => {
66
+ q?.abort(), q = new AbortController();
67
+ }, i = async () => {
68
+ R.value && u(), R.value = !0, l.value = void 0;
69
69
  try {
70
- r.params && a?.params && r.params.parse(a.params);
71
- let o = a?.data;
72
- r.data && o && r.data.parse(o);
73
- const s = {
74
- method: r.method ?? "GET",
75
- url: r.path,
76
- params: a?.params,
77
- signal: u.signal
70
+ a.params && t?.params && a.params.parse(t.params);
71
+ let s = t?.data;
72
+ a.data && s && a.data.parse(s);
73
+ const f = {
74
+ method: a.method ?? "GET",
75
+ url: a.path,
76
+ params: t?.params,
77
+ signal: q.signal
78
78
  };
79
- r.method === "POST" && o && (s.data = o, s.onUploadProgress = (E) => {
80
- if (E.total) {
81
- const M = Math.round(E.loaded * 100 / E.total);
82
- A.value = M, a?.onUploadProgress?.(M);
83
- }
84
- });
85
- const c = await g.request(s), l = r.response ? r.response.parse(c.data) : c.data;
86
- p.value = l, a?.onResult?.(l);
87
- } catch (o) {
88
- if (o instanceof L) {
89
- if (o.code !== "ERR_CANCELED") {
90
- const s = o.response?.data?.message || o.message || "An error occurred", c = o.response?.status, l = o.code, E = o.response?.data;
91
- i.value = s, a?.onError?.(o), t.onErrorRequest?.({ message: s, status: c, code: l, data: E });
79
+ a.method === "POST" && s && (f.data = s);
80
+ const n = await g.request(f), c = a.response ? a.response.parse(n.data) : n.data;
81
+ v.value = c, t?.onResult?.(c);
82
+ } catch (s) {
83
+ if (s instanceof w) {
84
+ if (s.code !== "ERR_CANCELED") {
85
+ const f = s.response?.data?.message || s.message || "An error occurred", n = s.response?.status, c = s.code, p = s.response?.data;
86
+ l.value = f, t?.onError?.(s), r.onErrorRequest?.({ message: f, status: n, code: c, data: p });
92
87
  }
93
- } else if (o instanceof w) {
94
- v.value = o.issues || [];
95
- const c = `Validation error: ${v.value.map(
96
- (l) => `${l.path.join(".")}: ${l.message}`
88
+ } else if (s instanceof P) {
89
+ E.value = s.issues || [];
90
+ const n = `Validation error: ${E.value.map(
91
+ (c) => `${c.path.join(".")}: ${c.message}`
97
92
  ).join(", ")}`;
98
- i.value = c, a?.onError?.(o), a?.onZodError?.(v.value), t.onErrorRequest?.({ message: c, code: "VALIDATION_ERROR" }), t.onZodError && t.onZodError(v.value);
93
+ l.value = n, t?.onError?.(s), t?.onZodError?.(E.value), r.onErrorRequest?.({ message: n, code: "VALIDATION_ERROR" }), r.onZodError && r.onZodError(E.value);
99
94
  } else {
100
- const s = o.message || "An error occurred";
101
- i.value = s, a?.onError?.(s), t.onErrorRequest?.({ message: s });
95
+ const f = s.message || "An error occurred";
96
+ l.value = f, t?.onError?.(f), r.onErrorRequest?.({ message: f });
102
97
  }
103
98
  } finally {
104
- q.value = !1, y.value = !0;
99
+ R.value = !1, y.value = !0;
105
100
  }
106
- }, h = a?.debounce ? Z(m, a.debounce) : m;
107
- let R = null;
108
- return (a?.params || a?.data) && (x(() => {
109
- R && R(), R = N(
110
- () => JSON.stringify({ params: a.params, data: a.data }),
101
+ }, h = t?.debounce ? Z(i, t.debounce) : i;
102
+ let d = null;
103
+ return (t?.params || t?.data) && (x(() => {
104
+ d && d(), d = N(
105
+ () => JSON.stringify({ params: t.params, data: t.data }),
111
106
  () => {
112
107
  h();
113
108
  },
114
109
  { immediate: !1 }
115
110
  );
116
111
  }), T(() => {
117
- R && R(), u?.abort();
118
- })), (a?.loadOnMount === void 0 || a.loadOnMount) && !y.value && (P.value ? (P.value = !1, m()) : h()), { result: p, errorMessage: i, zodErrors: v, isLoading: q, isDone: y, uploadProgress: A, refetch: m };
112
+ d && d(), q?.abort();
113
+ })), (t?.loadOnMount === void 0 || t.loadOnMount) && !y.value && (A.value ? (A.value = !1, i()) : h()), { result: v, errorMessage: l, zodErrors: E, isLoading: R, isDone: y, refetch: i };
119
114
  });
120
115
  }
121
- const j = t.mutations ?? {}, D = {};
122
- for (const e in j) {
123
- const r = j[e];
124
- r && (D[e] = (n) => {
125
- const a = d(), p = d(), i = d(), v = d(!1), q = d(!1), y = d(0);
126
- return { result: a, errorMessage: p, zodErrors: i, isLoading: v, isDone: q, uploadProgress: y, mutate: async (P) => {
127
- if (!v.value) {
128
- v.value = !0, p.value = void 0, y.value = 0;
116
+ const M = r.mutations ?? {}, D = {};
117
+ for (const e in M) {
118
+ const a = M[e];
119
+ a && (D[e] = (o) => {
120
+ const t = m(), v = m(), l = m(), E = m(!1), R = m(!1), y = m(0);
121
+ return { result: t, errorMessage: v, zodErrors: l, isLoading: E, isDone: R, uploadProgress: y, mutate: async (q) => {
122
+ if (!E.value) {
123
+ E.value = !0, v.value = void 0, y.value = 0;
129
124
  try {
130
- const { data: u, params: f } = P;
131
- let m = u ?? {}, h = {};
132
- if (r.isMultipart) {
133
- const s = new FormData();
134
- for (const [c, l] of Object.entries(u))
135
- l instanceof File || l instanceof Blob ? s.append(c, l) : Array.isArray(l) ? l.forEach((E) => {
136
- E instanceof File || E instanceof Blob ? s.append(c, E) : s.append(c, JSON.stringify(E));
137
- }) : typeof l == "object" && l !== null ? s.append(c, JSON.stringify(l)) : s.append(c, String(l));
138
- m = s, h["Content-Type"] = "multipart/form-data";
139
- } else r.data && r.data.parse(u);
140
- r.params && f && r.params.parse(f);
141
- const R = await g.request({
142
- method: r.method,
143
- url: r.path,
144
- data: m,
145
- params: f,
146
- headers: h,
147
- onUploadProgress: (s) => {
148
- if (s.total) {
149
- const c = Math.round(s.loaded * 100 / s.total);
150
- y.value = c, n?.onUploadProgress?.(c);
125
+ const { data: u, params: i } = q;
126
+ let h = u ?? {}, d = {};
127
+ if (a.isMultipart) {
128
+ const n = new FormData();
129
+ for (const [c, p] of Object.entries(u))
130
+ p instanceof File || p instanceof Blob ? n.append(c, p) : Array.isArray(p) ? p.forEach((b) => {
131
+ b instanceof File || b instanceof Blob ? n.append(c, b) : n.append(c, JSON.stringify(b));
132
+ }) : typeof p == "object" && p !== null ? n.append(c, JSON.stringify(p)) : n.append(c, String(p));
133
+ h = n, d["Content-Type"] = "multipart/form-data";
134
+ } else a.data && a.data.parse(u);
135
+ a.params && i && a.params.parse(i);
136
+ const s = await g.request({
137
+ method: a.method,
138
+ url: a.path,
139
+ data: h,
140
+ params: i,
141
+ headers: d,
142
+ onUploadProgress: (n) => {
143
+ if (n.total) {
144
+ const c = Math.round(n.loaded * 100 / n.total);
145
+ y.value = c, o?.onUploadProgress?.(c);
151
146
  }
152
147
  }
153
- }), o = r.response ? r.response.parse(R.data) : R.data;
154
- a.value = o, n?.onResult?.(o);
148
+ }), f = a.response ? a.response.parse(s.data) : s.data;
149
+ t.value = f, o?.onResult?.(f);
155
150
  } catch (u) {
156
- if (u instanceof L) {
157
- const f = u.response?.data?.message || u.message || "An error occurred", m = u.response?.status, h = u.code;
158
- p.value = f, n?.onError?.(u), t.onErrorRequest?.({ message: f, status: m, code: h });
159
- } else if (u instanceof w) {
160
- i.value = u.issues || [];
161
- const m = `Validation error: ${i.value.map(
162
- (h) => `${h.path.join(".")}: ${h.message}`
151
+ if (u instanceof w) {
152
+ const i = u.response?.data?.message || u.message || "An error occurred", h = u.response?.status, d = u.code;
153
+ v.value = i, o?.onError?.(u), r.onErrorRequest?.({ message: i, status: h, code: d });
154
+ } else if (u instanceof P) {
155
+ l.value = u.issues || [];
156
+ const h = `Validation error: ${l.value.map(
157
+ (d) => `${d.path.join(".")}: ${d.message}`
163
158
  ).join(", ")}`;
164
- p.value = m, n?.onError?.(u), n?.onZodError?.(i.value), t.onErrorRequest?.({ message: m, code: "VALIDATION_ERROR" }), t.onZodError && t.onZodError(i.value);
159
+ v.value = h, o?.onError?.(u), o?.onZodError?.(l.value), r.onErrorRequest?.({ message: h, code: "VALIDATION_ERROR" }), r.onZodError && r.onZodError(l.value);
165
160
  } else {
166
- const f = u.message || "An error occurred";
167
- p.value = f, n?.onError?.(u), t.onErrorRequest?.({ message: f });
161
+ const i = u.message || "An error occurred";
162
+ v.value = i, o?.onError?.(u), r.onErrorRequest?.({ message: i });
168
163
  }
169
164
  } finally {
170
- v.value = !1, q.value = !0;
165
+ E.value = !1, R.value = !0;
171
166
  }
172
167
  }
173
168
  } };
@@ -178,8 +173,24 @@ function z(t) {
178
173
  mutation: D
179
174
  };
180
175
  }
176
+ function z(r) {
177
+ return r;
178
+ }
179
+ function V(r) {
180
+ return r;
181
+ }
182
+ function _(...r) {
183
+ return Object.assign({}, ...r);
184
+ }
185
+ function J(...r) {
186
+ return Object.assign({}, ...r);
187
+ }
181
188
  export {
182
- J as AxiosError,
183
- z as createApiClient,
189
+ G as AxiosError,
190
+ I as createApiClient,
191
+ V as defineMutation,
192
+ z as defineQuery,
193
+ J as mergeMutations,
194
+ _ as mergeQueries,
184
195
  k as z
185
196
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "vue-api-kit",
3
3
  "type": "module",
4
- "version": "1.3.0",
4
+ "version": "1.4.0",
5
5
  "description": "A powerful and flexible API client for Vue 3 applications, built with TypeScript and Zod for type-safe API interactions.",
6
6
  "keywords": [
7
7
  "vue3",