vue-api-kit 1.6.0 → 1.8.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 +143 -12
- package/dist/core/types.d.ts +5 -0
- package/dist/index.js +133 -119
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -251,7 +251,8 @@ const api = createApiClient({
|
|
|
251
251
|
headers: {
|
|
252
252
|
'Authorization': 'Bearer token'
|
|
253
253
|
},
|
|
254
|
-
withCredentials: true,
|
|
254
|
+
withCredentials: true, // Enable cookies
|
|
255
|
+
withXSRFToken: true, // Enable automatic XSRF token handling
|
|
255
256
|
|
|
256
257
|
// CSRF Token Protection
|
|
257
258
|
csrfRefreshEndpoint: '/sanctum/csrf-cookie', // Auto-refresh CSRF token on 403/419 errors
|
|
@@ -289,6 +290,133 @@ const api = createApiClient({
|
|
|
289
290
|
});
|
|
290
291
|
```
|
|
291
292
|
|
|
293
|
+
## 🎯 Per-Query and Per-Mutation Request Interceptors
|
|
294
|
+
|
|
295
|
+
In addition to global request interceptors, you can define `onBeforeRequest` hooks for individual queries and mutations. This is useful when you need to append specific headers or modify the request configuration for certain endpoints only.
|
|
296
|
+
|
|
297
|
+
### Query-Level onBeforeRequest
|
|
298
|
+
|
|
299
|
+
You can define `onBeforeRequest` in two ways for queries:
|
|
300
|
+
|
|
301
|
+
**1. In the query definition:**
|
|
302
|
+
|
|
303
|
+
```typescript
|
|
304
|
+
const api = createApiClient({
|
|
305
|
+
baseURL: 'https://api.example.com',
|
|
306
|
+
queries: {
|
|
307
|
+
getUser: {
|
|
308
|
+
path: '/users/{id}',
|
|
309
|
+
params: z.object({ id: z.number() }),
|
|
310
|
+
response: z.object({ id: z.number(), name: z.string() }),
|
|
311
|
+
// Query-level interceptor
|
|
312
|
+
onBeforeRequest: async (config) => {
|
|
313
|
+
config.headers['X-Custom-Query-Header'] = 'special-value';
|
|
314
|
+
return config;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
});
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
**2. In the query options when calling it:**
|
|
322
|
+
|
|
323
|
+
```typescript
|
|
324
|
+
const { result, isLoading } = api.query.getUser({
|
|
325
|
+
params: { id: 1 },
|
|
326
|
+
// Runtime interceptor
|
|
327
|
+
onBeforeRequest: async (config) => {
|
|
328
|
+
const token = await getAuthToken();
|
|
329
|
+
config.headers.Authorization = `Bearer ${token}`;
|
|
330
|
+
return config;
|
|
331
|
+
}
|
|
332
|
+
});
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
### Mutation-Level onBeforeRequest
|
|
336
|
+
|
|
337
|
+
Similarly, you can define `onBeforeRequest` for mutations:
|
|
338
|
+
|
|
339
|
+
**1. In the mutation definition:**
|
|
340
|
+
|
|
341
|
+
```typescript
|
|
342
|
+
const api = createApiClient({
|
|
343
|
+
baseURL: 'https://api.example.com',
|
|
344
|
+
mutations: {
|
|
345
|
+
createUser: {
|
|
346
|
+
method: 'POST',
|
|
347
|
+
path: '/users',
|
|
348
|
+
data: z.object({ name: z.string(), email: z.string() }),
|
|
349
|
+
response: z.object({ id: z.number(), name: z.string() }),
|
|
350
|
+
// Mutation-level interceptor
|
|
351
|
+
onBeforeRequest: async (config) => {
|
|
352
|
+
config.headers['X-Action'] = 'create-user';
|
|
353
|
+
return config;
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
});
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
**2. In the mutation options when calling it:**
|
|
361
|
+
|
|
362
|
+
```typescript
|
|
363
|
+
const { mutate } = api.mutation.createUser({
|
|
364
|
+
// Runtime interceptor
|
|
365
|
+
onBeforeRequest: async (config) => {
|
|
366
|
+
const csrfToken = document.querySelector('meta[name="csrf-token"]')?.content;
|
|
367
|
+
if (csrfToken) {
|
|
368
|
+
config.headers['X-CSRF-Token'] = csrfToken;
|
|
369
|
+
}
|
|
370
|
+
return config;
|
|
371
|
+
}
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
await mutate({ data: { name: 'John', email: 'john@example.com' } });
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
### Execution Order
|
|
378
|
+
|
|
379
|
+
When multiple `onBeforeRequest` hooks are defined, they execute in the following order:
|
|
380
|
+
|
|
381
|
+
1. **Global interceptor** (defined in `createApiClient` options) - Applied via axios interceptor
|
|
382
|
+
2. **Query/Mutation definition interceptor** (defined in query/mutation object)
|
|
383
|
+
3. **Options interceptor** (defined when calling the query/mutation)
|
|
384
|
+
|
|
385
|
+
Each hook can modify the config, and later hooks can see and override changes made by earlier hooks.
|
|
386
|
+
|
|
387
|
+
### Use Cases
|
|
388
|
+
|
|
389
|
+
- **Authentication**: Add tokens for specific endpoints that require authentication
|
|
390
|
+
- **Custom Headers**: Append API keys, correlation IDs, or feature flags for specific requests
|
|
391
|
+
- **Request Transformation**: Modify request data or parameters before sending
|
|
392
|
+
- **Conditional Logic**: Apply different configurations based on runtime conditions
|
|
393
|
+
- **Debugging**: Add request IDs or trace headers for specific endpoints
|
|
394
|
+
|
|
395
|
+
### Example: Dynamic Authorization
|
|
396
|
+
|
|
397
|
+
```typescript
|
|
398
|
+
const api = createApiClient({
|
|
399
|
+
baseURL: 'https://api.example.com',
|
|
400
|
+
queries: {
|
|
401
|
+
getProtectedData: {
|
|
402
|
+
path: '/protected/data',
|
|
403
|
+
response: z.object({ data: z.string() }),
|
|
404
|
+
onBeforeRequest: async (config) => {
|
|
405
|
+
// This query always needs fresh token
|
|
406
|
+
const token = await refreshAndGetToken();
|
|
407
|
+
config.headers.Authorization = `Bearer ${token}`;
|
|
408
|
+
return config;
|
|
409
|
+
}
|
|
410
|
+
},
|
|
411
|
+
getPublicData: {
|
|
412
|
+
path: '/public/data',
|
|
413
|
+
response: z.object({ data: z.string() })
|
|
414
|
+
// No onBeforeRequest needed for public endpoint
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
});
|
|
418
|
+
```
|
|
419
|
+
|
|
292
420
|
## 🧩 Modular API Definitions
|
|
293
421
|
|
|
294
422
|
For large applications, you can organize your API definitions into separate files and merge them together with full type safety.
|
|
@@ -459,9 +587,10 @@ The client includes built-in CSRF token protection, perfect for Laravel Sanctum
|
|
|
459
587
|
### How it works
|
|
460
588
|
|
|
461
589
|
**Automatic XSRF Token Handling:**
|
|
462
|
-
1.
|
|
463
|
-
2.
|
|
464
|
-
3.
|
|
590
|
+
1. Set `withCredentials: true` to enable cookie-based authentication
|
|
591
|
+
2. Set `withXSRFToken: true` to enable automatic XSRF token handling
|
|
592
|
+
3. Axios automatically reads `XSRF-TOKEN` cookie and sends it as `X-XSRF-TOKEN` header
|
|
593
|
+
4. This satisfies Laravel Sanctum's CSRF protection requirements
|
|
465
594
|
|
|
466
595
|
**Automatic CSRF Refresh:**
|
|
467
596
|
1. Detects CSRF errors (403 or 419 status codes)
|
|
@@ -474,9 +603,9 @@ The client includes built-in CSRF token protection, perfect for Laravel Sanctum
|
|
|
474
603
|
```typescript
|
|
475
604
|
const api = createApiClient({
|
|
476
605
|
baseURL: 'https://api.example.com',
|
|
477
|
-
withCredentials: true,
|
|
606
|
+
withCredentials: true, // Enable cookies for authentication
|
|
607
|
+
withXSRFToken: true, // Enable automatic XSRF token handling
|
|
478
608
|
csrfRefreshEndpoint: '/sanctum/csrf-cookie', // Laravel Sanctum endpoint
|
|
479
|
-
|
|
480
609
|
queries: { /* ... */ },
|
|
481
610
|
mutations: { /* ... */ }
|
|
482
611
|
});
|
|
@@ -491,10 +620,9 @@ import { z } from 'zod';
|
|
|
491
620
|
|
|
492
621
|
export const api = createApiClient({
|
|
493
622
|
baseURL: 'https://api.example.com',
|
|
494
|
-
withCredentials: true,
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
mutations: {
|
|
623
|
+
withCredentials: true, // Enables cookies
|
|
624
|
+
withXSRFToken: true, // Enables automatic XSRF-TOKEN header
|
|
625
|
+
csrfRefreshEndpoint: '/sanctum/csrf-cookie', // Laravel's CSRF endpoint mutations: {
|
|
498
626
|
login: {
|
|
499
627
|
method: 'POST',
|
|
500
628
|
path: '/login',
|
|
@@ -524,7 +652,8 @@ export const api = createApiClient({
|
|
|
524
652
|
|
|
525
653
|
### Benefits
|
|
526
654
|
|
|
527
|
-
- ✅ **
|
|
655
|
+
- ✅ **Separate Options**: `withCredentials` and `withXSRFToken` can be configured independently
|
|
656
|
+
- ✅ **Built-in XSRF Support**: Axios `withXSRFToken` handles token automatically
|
|
528
657
|
- ✅ **Automatic Recovery**: No manual token refresh needed
|
|
529
658
|
- ✅ **Seamless UX**: Users don't experience authentication errors
|
|
530
659
|
- ✅ **Race Condition Safe**: Multiple simultaneous requests share the same refresh
|
|
@@ -533,7 +662,9 @@ export const api = createApiClient({
|
|
|
533
662
|
|
|
534
663
|
### Important Notes
|
|
535
664
|
|
|
536
|
-
1. **
|
|
665
|
+
1. **Two separate options**:
|
|
666
|
+
- `withCredentials: true` - Enables sending cookies with requests
|
|
667
|
+
- `withXSRFToken: true` - Enables automatic XSRF token header handling
|
|
537
668
|
2. **Cookie Domain**: Ensure your API sets cookies with the correct domain (e.g., `.localhost` for local development)
|
|
538
669
|
3. **CORS Configuration**: Your Laravel backend must allow credentials:
|
|
539
670
|
```php
|
package/dist/core/types.d.ts
CHANGED
|
@@ -42,6 +42,7 @@ export interface ApiQuery<TParams extends ZodType<any> | undefined = ZodType<any
|
|
|
42
42
|
params?: TParams;
|
|
43
43
|
data?: TData;
|
|
44
44
|
response?: TResponse;
|
|
45
|
+
onBeforeRequest?: (config: InternalAxiosRequestConfig<any>) => Promise<any> | void | any;
|
|
45
46
|
}
|
|
46
47
|
/**
|
|
47
48
|
* Defines a mutation (POST, PUT, PATCH, DELETE) endpoint configuration
|
|
@@ -63,6 +64,7 @@ export interface ApiMutation<TData extends ZodType<any> | undefined = ZodType<an
|
|
|
63
64
|
data?: TData;
|
|
64
65
|
response?: TResponse;
|
|
65
66
|
isMultipart?: boolean;
|
|
67
|
+
onBeforeRequest?: (config: InternalAxiosRequestConfig<any>) => Promise<any> | void | any;
|
|
66
68
|
}
|
|
67
69
|
/**
|
|
68
70
|
* Configuration options for creating an API client
|
|
@@ -83,6 +85,7 @@ export interface ApiClientOptions<Q extends Record<string, ApiQuery> = Record<st
|
|
|
83
85
|
baseURL: string;
|
|
84
86
|
headers?: Record<string, string>;
|
|
85
87
|
withCredentials?: boolean;
|
|
88
|
+
withXSRFToken?: boolean;
|
|
86
89
|
csrfRefreshEndpoint?: string;
|
|
87
90
|
queries?: Q;
|
|
88
91
|
mutations?: M;
|
|
@@ -125,6 +128,7 @@ export interface UseQueryOptions<TParams = any, TData = any, TResult = any> {
|
|
|
125
128
|
onResult?: (result: TResult) => void;
|
|
126
129
|
onError?: (error: AxiosError | ZodError | Error) => void;
|
|
127
130
|
onZodError?: (issues: Omit<$ZodIssue, "input">[]) => void;
|
|
131
|
+
onBeforeRequest?: (config: InternalAxiosRequestConfig<any>) => Promise<any> | void | any;
|
|
128
132
|
}
|
|
129
133
|
/**
|
|
130
134
|
* Options for configuring a mutation hook
|
|
@@ -141,6 +145,7 @@ export interface UseMutationOptions<TResult = any> {
|
|
|
141
145
|
onError?: (error: AxiosError | ZodError | Error) => void;
|
|
142
146
|
onZodError?: (issues: Omit<$ZodIssue, "input">[]) => void;
|
|
143
147
|
onUploadProgress?: (progress: number) => void;
|
|
148
|
+
onBeforeRequest?: (config: InternalAxiosRequestConfig<any>) => Promise<any> | void | any;
|
|
144
149
|
}
|
|
145
150
|
/**
|
|
146
151
|
* Return type from a query hook
|
package/dist/index.js
CHANGED
|
@@ -1,190 +1,204 @@
|
|
|
1
1
|
import { ZodError as S } from "zod";
|
|
2
|
-
import * as
|
|
2
|
+
import * as U from "zod";
|
|
3
3
|
import L, { AxiosError as F } from "axios";
|
|
4
|
-
import { AxiosError as
|
|
5
|
-
import { nextTick as
|
|
6
|
-
import { debounce as
|
|
7
|
-
function
|
|
8
|
-
const
|
|
9
|
-
baseURL:
|
|
4
|
+
import { AxiosError as K } from "axios";
|
|
5
|
+
import { nextTick as T, ref as m, onMounted as k, watch as Z, onBeforeUnmount as x } from "vue";
|
|
6
|
+
import { debounce as N } from "lodash-es";
|
|
7
|
+
function V(s) {
|
|
8
|
+
const R = L.create({
|
|
9
|
+
baseURL: s.baseURL,
|
|
10
10
|
headers: {
|
|
11
11
|
"Content-Type": "application/json",
|
|
12
12
|
Accept: "application/json",
|
|
13
|
-
...
|
|
13
|
+
...s.headers
|
|
14
14
|
},
|
|
15
|
-
withCredentials:
|
|
15
|
+
withCredentials: s.withCredentials ?? !1,
|
|
16
|
+
withXSRFToken: s.withXSRFToken ?? !1
|
|
16
17
|
});
|
|
17
|
-
let C = !1,
|
|
18
|
-
|
|
18
|
+
let C = !1, j = null;
|
|
19
|
+
s.onBeforeRequest && R.interceptors.request.use(
|
|
19
20
|
async (e) => {
|
|
20
21
|
try {
|
|
21
|
-
return await
|
|
22
|
+
return await s.onBeforeRequest(e) || e;
|
|
22
23
|
} catch (r) {
|
|
23
24
|
return Promise.reject(r);
|
|
24
25
|
}
|
|
25
26
|
},
|
|
26
27
|
(e) => Promise.reject(e)
|
|
27
|
-
),
|
|
28
|
+
), s.onStartRequest && R.interceptors.request.use(
|
|
28
29
|
async (e) => {
|
|
29
30
|
try {
|
|
30
|
-
return await
|
|
31
|
+
return await s.onStartRequest(), e;
|
|
31
32
|
} catch (r) {
|
|
32
33
|
return Promise.reject(r);
|
|
33
34
|
}
|
|
34
35
|
},
|
|
35
36
|
(e) => Promise.reject(e)
|
|
36
|
-
),
|
|
37
|
-
(e) => (
|
|
38
|
-
(e) => (
|
|
39
|
-
),
|
|
37
|
+
), s.onFinishRequest && R.interceptors.response.use(
|
|
38
|
+
(e) => (s.onFinishRequest(), e),
|
|
39
|
+
(e) => (s.onFinishRequest(), Promise.reject(e))
|
|
40
|
+
), R.interceptors.request.use((e) => {
|
|
40
41
|
if (!e.url) return e;
|
|
41
42
|
const r = (a) => {
|
|
42
43
|
if (a)
|
|
43
|
-
for (const [
|
|
44
|
-
const
|
|
45
|
-
e.url.includes(
|
|
46
|
-
|
|
47
|
-
encodeURIComponent(String(
|
|
48
|
-
), delete a[
|
|
44
|
+
for (const [t, p] of Object.entries(a)) {
|
|
45
|
+
const f = `{${t}}`;
|
|
46
|
+
e.url.includes(f) && (e.url = e.url.replace(
|
|
47
|
+
f,
|
|
48
|
+
encodeURIComponent(String(p))
|
|
49
|
+
), delete a[t]);
|
|
49
50
|
}
|
|
50
51
|
};
|
|
51
52
|
return e.method !== "get" && e.data?.params && r(e.data.params), r(e.params), e;
|
|
52
|
-
}),
|
|
53
|
-
const r = document.cookie.split("; ").find((a) => a.startsWith("XSRF-TOKEN="))?.split("=")[1];
|
|
54
|
-
return r && (e.headers["X-XSRF-TOKEN"] = decodeURIComponent(r)), e;
|
|
55
|
-
}), t.csrfRefreshEndpoint && p.interceptors.response.use(
|
|
53
|
+
}), s.csrfRefreshEndpoint && R.interceptors.response.use(
|
|
56
54
|
(e) => e,
|
|
57
55
|
async (e) => {
|
|
58
56
|
const r = e.config;
|
|
59
|
-
if (r?.url ===
|
|
57
|
+
if (r?.url === s.csrfRefreshEndpoint)
|
|
60
58
|
return Promise.reject(e);
|
|
61
59
|
if (e.response && (e.response.status === 403 || e.response.status === 419) && !r?._retry) {
|
|
62
60
|
r._retry = !0;
|
|
63
61
|
try {
|
|
64
|
-
return C &&
|
|
65
|
-
C = !1,
|
|
66
|
-
}), await
|
|
62
|
+
return C && j ? await j : (C = !0, j = R.get(s.csrfRefreshEndpoint).then(() => {
|
|
63
|
+
C = !1, j = null;
|
|
64
|
+
}), await j), R.request(r);
|
|
67
65
|
} catch (a) {
|
|
68
|
-
return C = !1,
|
|
66
|
+
return C = !1, j = null, Promise.reject(a);
|
|
69
67
|
}
|
|
70
68
|
}
|
|
71
69
|
return Promise.reject(e);
|
|
72
70
|
}
|
|
73
|
-
),
|
|
71
|
+
), R.interceptors.response.use(
|
|
74
72
|
(e) => e,
|
|
75
|
-
(e) => (
|
|
73
|
+
(e) => (T(() => {
|
|
76
74
|
e.code;
|
|
77
75
|
}), Promise.reject(e))
|
|
78
76
|
);
|
|
79
|
-
const P =
|
|
77
|
+
const P = s.queries ?? {}, M = {};
|
|
80
78
|
for (const e in P) {
|
|
81
79
|
const r = P[e];
|
|
82
80
|
r && (M[e] = (a) => {
|
|
83
|
-
let
|
|
84
|
-
a && typeof a == "object" && ("loadOnMount" in a || "debounce" in a || "onResult" in a || "onError" in a || "data" in a ?
|
|
85
|
-
const
|
|
86
|
-
let
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
},
|
|
90
|
-
|
|
81
|
+
let t;
|
|
82
|
+
a && typeof a == "object" && ("loadOnMount" in a || "debounce" in a || "onResult" in a || "onError" in a || "onZodError" in a || "onBeforeRequest" in a || "data" in a ? t = a : t = { params: a });
|
|
83
|
+
const p = m(), f = m(), g = m(), E = m(!1), y = m(!1), A = m(!0);
|
|
84
|
+
let b = new AbortController();
|
|
85
|
+
const i = () => {
|
|
86
|
+
b?.abort(), b = new AbortController();
|
|
87
|
+
}, l = async () => {
|
|
88
|
+
E.value && i(), E.value = !0, f.value = void 0;
|
|
91
89
|
try {
|
|
92
|
-
r.params &&
|
|
93
|
-
let o =
|
|
90
|
+
r.params && t?.params && r.params.parse(t.params);
|
|
91
|
+
let o = t?.data;
|
|
94
92
|
r.data && o && r.data.parse(o);
|
|
95
|
-
const
|
|
93
|
+
const u = {
|
|
96
94
|
method: r.method ?? "GET",
|
|
97
95
|
url: r.path,
|
|
98
|
-
params:
|
|
99
|
-
signal:
|
|
96
|
+
params: t?.params,
|
|
97
|
+
signal: b.signal
|
|
100
98
|
};
|
|
101
|
-
r.method === "POST" && o && (
|
|
102
|
-
|
|
103
|
-
|
|
99
|
+
if (r.method === "POST" && o && (u.data = o), r.onBeforeRequest) {
|
|
100
|
+
const c = await r.onBeforeRequest(u);
|
|
101
|
+
c !== void 0 && Object.assign(u, c);
|
|
102
|
+
}
|
|
103
|
+
if (t?.onBeforeRequest) {
|
|
104
|
+
const c = await t.onBeforeRequest(u);
|
|
105
|
+
c !== void 0 && Object.assign(u, c);
|
|
106
|
+
}
|
|
107
|
+
const h = await R.request(u), n = r.response ? r.response.parse(h.data) : h.data;
|
|
108
|
+
p.value = n, t?.onResult?.(n);
|
|
104
109
|
} catch (o) {
|
|
105
110
|
if (o instanceof F) {
|
|
106
111
|
if (o.code !== "ERR_CANCELED") {
|
|
107
|
-
const
|
|
108
|
-
|
|
112
|
+
const u = o.response?.data?.message || o.message || "An error occurred", h = o.response?.status, n = o.code, c = o.response?.data;
|
|
113
|
+
f.value = u, t?.onError?.(o), s.onErrorRequest?.({ message: u, status: h, code: n, data: c });
|
|
109
114
|
}
|
|
110
115
|
} else if (o instanceof S) {
|
|
111
|
-
|
|
112
|
-
const
|
|
113
|
-
(
|
|
116
|
+
g.value = o.issues || [];
|
|
117
|
+
const h = `Validation error: ${g.value.map(
|
|
118
|
+
(n) => `${n.path.join(".")}: ${n.message}`
|
|
114
119
|
).join(", ")}`;
|
|
115
|
-
|
|
120
|
+
f.value = h, t?.onError?.(o), t?.onZodError?.(g.value), s.onErrorRequest?.({ message: h, code: "VALIDATION_ERROR" }), s.onZodError && s.onZodError(g.value);
|
|
116
121
|
} else {
|
|
117
|
-
const
|
|
118
|
-
|
|
122
|
+
const u = o.message || "An error occurred";
|
|
123
|
+
f.value = u, t?.onError?.(u), s.onErrorRequest?.({ message: u });
|
|
119
124
|
}
|
|
120
125
|
} finally {
|
|
121
|
-
|
|
126
|
+
E.value = !1, y.value = !0;
|
|
122
127
|
}
|
|
123
|
-
},
|
|
128
|
+
}, v = t?.debounce ? N(l, t.debounce) : l;
|
|
124
129
|
let d = null;
|
|
125
|
-
return (
|
|
126
|
-
d && d(), d =
|
|
127
|
-
() => JSON.stringify({ params:
|
|
130
|
+
return (t?.params || t?.data) && (k(() => {
|
|
131
|
+
d && d(), d = Z(
|
|
132
|
+
() => JSON.stringify({ params: t.params, data: t.data }),
|
|
128
133
|
() => {
|
|
129
|
-
|
|
134
|
+
v();
|
|
130
135
|
},
|
|
131
136
|
{ immediate: !1 }
|
|
132
137
|
);
|
|
133
138
|
}), x(() => {
|
|
134
|
-
d && d(),
|
|
135
|
-
})), (
|
|
139
|
+
d && d(), b?.abort();
|
|
140
|
+
})), (t?.loadOnMount === void 0 || t.loadOnMount) && !y.value && (A.value ? (A.value = !1, l()) : v()), { result: p, errorMessage: f, zodErrors: g, isLoading: E, isDone: y, refetch: l };
|
|
136
141
|
});
|
|
137
142
|
}
|
|
138
|
-
const
|
|
139
|
-
for (const e in
|
|
140
|
-
const r =
|
|
141
|
-
r && (
|
|
142
|
-
const
|
|
143
|
-
return { result:
|
|
144
|
-
if (!
|
|
145
|
-
|
|
143
|
+
const B = s.mutations ?? {}, D = {};
|
|
144
|
+
for (const e in B) {
|
|
145
|
+
const r = B[e];
|
|
146
|
+
r && (D[e] = (a) => {
|
|
147
|
+
const t = m(), p = m(), f = m(), g = m(!1), E = m(!1), y = m(0);
|
|
148
|
+
return { result: t, errorMessage: p, zodErrors: f, isLoading: g, isDone: E, uploadProgress: y, mutate: async (b) => {
|
|
149
|
+
if (!g.value) {
|
|
150
|
+
g.value = !0, p.value = void 0, y.value = 0;
|
|
146
151
|
try {
|
|
147
|
-
const { data:
|
|
148
|
-
let
|
|
152
|
+
const { data: i = {}, params: l } = b ?? {};
|
|
153
|
+
let v = i ?? {}, d = {};
|
|
149
154
|
if (r.isMultipart) {
|
|
150
155
|
const n = new FormData();
|
|
151
|
-
for (const [
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
}) : typeof
|
|
155
|
-
|
|
156
|
-
} else r.data && r.data.parse(
|
|
157
|
-
r.params &&
|
|
158
|
-
const o =
|
|
156
|
+
for (const [c, q] of Object.entries(i))
|
|
157
|
+
q instanceof File || q instanceof Blob ? n.append(c, q) : Array.isArray(q) ? q.forEach((w) => {
|
|
158
|
+
w instanceof File || w instanceof Blob ? n.append(c, w) : n.append(c, JSON.stringify(w));
|
|
159
|
+
}) : typeof q == "object" && q !== null ? n.append(c, JSON.stringify(q)) : n.append(c, String(q));
|
|
160
|
+
v = n, d["Content-Type"] = "multipart/form-data";
|
|
161
|
+
} else r.data && r.data.parse(i);
|
|
162
|
+
r.params && l && r.params.parse(l);
|
|
163
|
+
const o = {
|
|
159
164
|
method: r.method,
|
|
160
165
|
url: r.path,
|
|
161
|
-
data:
|
|
162
|
-
params:
|
|
166
|
+
data: v,
|
|
167
|
+
params: l,
|
|
163
168
|
headers: d,
|
|
164
169
|
onUploadProgress: (n) => {
|
|
165
170
|
if (n.total) {
|
|
166
|
-
const
|
|
167
|
-
y.value =
|
|
171
|
+
const c = Math.round(n.loaded * 100 / n.total);
|
|
172
|
+
y.value = c, a?.onUploadProgress?.(c);
|
|
168
173
|
}
|
|
169
174
|
}
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
175
|
+
};
|
|
176
|
+
if (r.onBeforeRequest) {
|
|
177
|
+
const n = await r.onBeforeRequest(o);
|
|
178
|
+
n !== void 0 && Object.assign(o, n);
|
|
179
|
+
}
|
|
180
|
+
if (a?.onBeforeRequest) {
|
|
181
|
+
const n = await a.onBeforeRequest(o);
|
|
182
|
+
n !== void 0 && Object.assign(o, n);
|
|
183
|
+
}
|
|
184
|
+
const u = await R.request(o), h = r.response ? r.response.parse(u.data) : u.data;
|
|
185
|
+
t.value = h, a?.onResult?.(h);
|
|
186
|
+
} catch (i) {
|
|
187
|
+
if (i instanceof F) {
|
|
188
|
+
const l = i.response?.data?.message || i.message || "An error occurred", v = i.response?.status, d = i.code;
|
|
189
|
+
p.value = l, a?.onError?.(i), s.onErrorRequest?.({ message: l, status: v, code: d });
|
|
190
|
+
} else if (i instanceof S) {
|
|
191
|
+
f.value = i.issues || [];
|
|
192
|
+
const v = `Validation error: ${f.value.map(
|
|
179
193
|
(d) => `${d.path.join(".")}: ${d.message}`
|
|
180
194
|
).join(", ")}`;
|
|
181
|
-
|
|
195
|
+
p.value = v, a?.onError?.(i), a?.onZodError?.(f.value), s.onErrorRequest?.({ message: v, code: "VALIDATION_ERROR" }), s.onZodError && s.onZodError(f.value);
|
|
182
196
|
} else {
|
|
183
|
-
const
|
|
184
|
-
|
|
197
|
+
const l = i.message || "An error occurred";
|
|
198
|
+
p.value = l, a?.onError?.(i), s.onErrorRequest?.({ message: l });
|
|
185
199
|
}
|
|
186
200
|
} finally {
|
|
187
|
-
|
|
201
|
+
g.value = !1, E.value = !0;
|
|
188
202
|
}
|
|
189
203
|
}
|
|
190
204
|
} };
|
|
@@ -192,27 +206,27 @@ function z(t) {
|
|
|
192
206
|
}
|
|
193
207
|
return {
|
|
194
208
|
query: M,
|
|
195
|
-
mutation:
|
|
209
|
+
mutation: D
|
|
196
210
|
};
|
|
197
211
|
}
|
|
198
|
-
function
|
|
199
|
-
return
|
|
212
|
+
function J(s) {
|
|
213
|
+
return s;
|
|
200
214
|
}
|
|
201
|
-
function
|
|
202
|
-
return
|
|
215
|
+
function Q(s) {
|
|
216
|
+
return s;
|
|
203
217
|
}
|
|
204
|
-
function
|
|
205
|
-
return Object.assign({}, ...
|
|
218
|
+
function W(...s) {
|
|
219
|
+
return Object.assign({}, ...s);
|
|
206
220
|
}
|
|
207
|
-
function
|
|
208
|
-
return Object.assign({}, ...
|
|
221
|
+
function X(...s) {
|
|
222
|
+
return Object.assign({}, ...s);
|
|
209
223
|
}
|
|
210
224
|
export {
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
225
|
+
K as AxiosError,
|
|
226
|
+
V as createApiClient,
|
|
227
|
+
Q as defineMutation,
|
|
228
|
+
J as defineQuery,
|
|
229
|
+
X as mergeMutations,
|
|
230
|
+
W as mergeQueries,
|
|
231
|
+
U as z
|
|
218
232
|
};
|
package/package.json
CHANGED