@ametie/vue-muza-use 0.0.2 → 0.1.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 +44 -8
- package/dist/index.cjs +6 -2
- package/dist/index.d.cts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.mjs +7 -2
- package/package.json +5 -1
package/README.md
CHANGED
|
@@ -11,6 +11,9 @@
|
|
|
11
11
|
|
|
12
12
|
---
|
|
13
13
|
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
14
17
|
## 🚀 Why is this cool?
|
|
15
18
|
|
|
16
19
|
* 🛡 **Zombie Retry Protection**
|
|
@@ -148,21 +151,52 @@ const { execute } = useApiPost('/auth/register', {
|
|
|
148
151
|
})
|
|
149
152
|
```
|
|
150
153
|
|
|
151
|
-
###
|
|
152
|
-
|
|
154
|
+
### 🔄 Auto-Refetching (Watch & Debounce)
|
|
155
|
+
You can automatically trigger the request whenever specific Refs change. This is perfect for **Live Search** or **Auto-Save** forms.
|
|
156
|
+
|
|
157
|
+
> **💡 Pro Tip:** When watching text inputs (like search), **always** use `debounce` to prevent flooding your server with requests on every keystroke.
|
|
153
158
|
|
|
159
|
+
#### Live Search
|
|
154
160
|
```typescript
|
|
155
161
|
const searchQuery = ref('')
|
|
162
|
+
// Use a computed URL so it updates when execute() is triggered
|
|
163
|
+
const url = computed(() => `/search?q=${searchQuery.value}`)
|
|
156
164
|
|
|
157
|
-
const { data,
|
|
165
|
+
const { data, loading } = useApi(url, {
|
|
158
166
|
method: 'GET',
|
|
159
|
-
|
|
160
|
-
|
|
167
|
+
watch: searchQuery, // 👀 Auto-execute when this ref changes
|
|
168
|
+
debounce: 500, // ⏳ Wait 500ms after user stops typing
|
|
169
|
+
abortPrevious: true // Kill previous request if it's still running
|
|
161
170
|
})
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
#### Filters (Immediate Refetch)
|
|
174
|
+
For inputs like Selects, Toggles, or Tabs where you want instant updates without delay. `watch` accepts an array of Refs.
|
|
175
|
+
|
|
176
|
+
```typescript
|
|
177
|
+
const category = ref('all')
|
|
178
|
+
const inStock = ref(true)
|
|
162
179
|
|
|
163
|
-
//
|
|
164
|
-
|
|
165
|
-
|
|
180
|
+
// URL updates reactively
|
|
181
|
+
const url = computed(() =>
|
|
182
|
+
`/products?cat=${category.value}&stock=${inStock.value}`
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
const { data } = useApi(url, {
|
|
186
|
+
watch: [category, inStock], // 👀 Re-fetch instantly when any filter changes
|
|
187
|
+
// default debounce is 0
|
|
188
|
+
})
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
#### Auto-Save Form
|
|
192
|
+
```typescript
|
|
193
|
+
const settings = ref({ theme: 'dark', notifications: true })
|
|
194
|
+
|
|
195
|
+
useApiPost('/user/settings', {
|
|
196
|
+
data: settings, // Passing ref: library automatically unwraps it
|
|
197
|
+
watch: settings, // Watch the form for changes (deep watch supported)
|
|
198
|
+
debounce: 1000, // Save after 1 second of inactivity
|
|
199
|
+
onSuccess: () => console.log('Settings saved!')
|
|
166
200
|
})
|
|
167
201
|
```
|
|
168
202
|
|
|
@@ -206,6 +240,7 @@ The main composable.
|
|
|
206
240
|
| `immediate` | `boolean` | `false` | Trigger request automatically on creation. |
|
|
207
241
|
| `retry` | `boolean \| number` | `false` | Number of retries on failure. |
|
|
208
242
|
| `debounce` | `number` | `0` | Debounce time in ms. |
|
|
243
|
+
| `watch` | `WatchSource \| WatchSource[]` | `undefined` | Ref(s) to watch for auto-execution. |
|
|
209
244
|
| `authMode` | `'default' \| 'public'` | `'default'` | `'public'` skips token injection. |
|
|
210
245
|
| `initialData` | `T` | `null` | Initial value for `data` ref. |
|
|
211
246
|
| `onSuccess` | `(res) => void` | - | Callback on 2xx response. |
|
|
@@ -246,6 +281,7 @@ interface CreateApiClientOptions {
|
|
|
246
281
|
|
|
247
282
|
---
|
|
248
283
|
|
|
284
|
+
|
|
249
285
|
## 🔐 Auth & Refresh Logic
|
|
250
286
|
|
|
251
287
|
`vue-muza-use` implements a robust **Interceptor Queue** pattern for handling JWTs.
|
package/dist/index.cjs
CHANGED
|
@@ -273,6 +273,11 @@ function useApi(url, options = {}) {
|
|
|
273
273
|
state.reset();
|
|
274
274
|
state.setLoading(false);
|
|
275
275
|
};
|
|
276
|
+
if (options.watch) {
|
|
277
|
+
(0, import_vue4.watch)(options.watch, () => {
|
|
278
|
+
execute();
|
|
279
|
+
}, { deep: true });
|
|
280
|
+
}
|
|
276
281
|
if ((0, import_vue4.getCurrentScope)()) {
|
|
277
282
|
(0, import_vue4.onScopeDispose)(() => abort("Scope disposed"));
|
|
278
283
|
}
|
|
@@ -299,7 +304,6 @@ function useApiDelete(url, options) {
|
|
|
299
304
|
var import_axios = __toESM(require("axios"), 1);
|
|
300
305
|
|
|
301
306
|
// src/features/monitor.ts
|
|
302
|
-
var import_meta = {};
|
|
303
307
|
var AuthEventType = /* @__PURE__ */ ((AuthEventType2) => {
|
|
304
308
|
AuthEventType2["REFRESH_START"] = "AUTH_REFRESH_START";
|
|
305
309
|
AuthEventType2["REQUEST_QUEUED"] = "AUTH_REQUEST_QUEUED";
|
|
@@ -308,7 +312,7 @@ var AuthEventType = /* @__PURE__ */ ((AuthEventType2) => {
|
|
|
308
312
|
return AuthEventType2;
|
|
309
313
|
})(AuthEventType || {});
|
|
310
314
|
var defaultMonitor = (type, payload) => {
|
|
311
|
-
const isDev = typeof process !== "undefined" && process.env?.NODE_ENV === "development"
|
|
315
|
+
const isDev = typeof process !== "undefined" && process.env?.NODE_ENV === "development";
|
|
312
316
|
if (isDev) {
|
|
313
317
|
console.debug(`[AuthMonitor] ${type}`, payload);
|
|
314
318
|
}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as vue from 'vue';
|
|
2
|
-
import { MaybeRefOrGetter, Ref, App } from 'vue';
|
|
2
|
+
import { MaybeRefOrGetter, WatchSource, Ref, App } from 'vue';
|
|
3
3
|
import { AxiosInstance, AxiosRequestConfig, AxiosResponse, CreateAxiosDefaults } from 'axios';
|
|
4
4
|
|
|
5
5
|
interface ApiError {
|
|
@@ -33,6 +33,7 @@ interface UseApiOptions<T = unknown, D = unknown> extends ApiRequestConfig<D> {
|
|
|
33
33
|
debounce?: number;
|
|
34
34
|
useGlobalAbort?: boolean;
|
|
35
35
|
initialLoading?: boolean;
|
|
36
|
+
watch?: WatchSource | WatchSource[];
|
|
36
37
|
}
|
|
37
38
|
interface UseApiReturn<T = unknown, D = unknown> {
|
|
38
39
|
data: Ref<T | null>;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as vue from 'vue';
|
|
2
|
-
import { MaybeRefOrGetter, Ref, App } from 'vue';
|
|
2
|
+
import { MaybeRefOrGetter, WatchSource, Ref, App } from 'vue';
|
|
3
3
|
import { AxiosInstance, AxiosRequestConfig, AxiosResponse, CreateAxiosDefaults } from 'axios';
|
|
4
4
|
|
|
5
5
|
interface ApiError {
|
|
@@ -33,6 +33,7 @@ interface UseApiOptions<T = unknown, D = unknown> extends ApiRequestConfig<D> {
|
|
|
33
33
|
debounce?: number;
|
|
34
34
|
useGlobalAbort?: boolean;
|
|
35
35
|
initialLoading?: boolean;
|
|
36
|
+
watch?: WatchSource | WatchSource[];
|
|
36
37
|
}
|
|
37
38
|
interface UseApiReturn<T = unknown, D = unknown> {
|
|
38
39
|
data: Ref<T | null>;
|
package/dist/index.mjs
CHANGED
|
@@ -34,7 +34,7 @@ function debounceFn(fn, delay) {
|
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
// src/useApi.ts
|
|
37
|
-
import { ref as ref3, getCurrentScope, onScopeDispose, toValue } from "vue";
|
|
37
|
+
import { ref as ref3, getCurrentScope, onScopeDispose, toValue, watch } from "vue";
|
|
38
38
|
|
|
39
39
|
// src/utils/errorParser.ts
|
|
40
40
|
function parseApiError(error) {
|
|
@@ -223,6 +223,11 @@ function useApi(url, options = {}) {
|
|
|
223
223
|
state.reset();
|
|
224
224
|
state.setLoading(false);
|
|
225
225
|
};
|
|
226
|
+
if (options.watch) {
|
|
227
|
+
watch(options.watch, () => {
|
|
228
|
+
execute();
|
|
229
|
+
}, { deep: true });
|
|
230
|
+
}
|
|
226
231
|
if (getCurrentScope()) {
|
|
227
232
|
onScopeDispose(() => abort("Scope disposed"));
|
|
228
233
|
}
|
|
@@ -257,7 +262,7 @@ var AuthEventType = /* @__PURE__ */ ((AuthEventType2) => {
|
|
|
257
262
|
return AuthEventType2;
|
|
258
263
|
})(AuthEventType || {});
|
|
259
264
|
var defaultMonitor = (type, payload) => {
|
|
260
|
-
const isDev = typeof process !== "undefined" && process.env?.NODE_ENV === "development"
|
|
265
|
+
const isDev = typeof process !== "undefined" && process.env?.NODE_ENV === "development";
|
|
261
266
|
if (isDev) {
|
|
262
267
|
console.debug(`[AuthMonitor] ${type}`, payload);
|
|
263
268
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ametie/vue-muza-use",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"description": "Powerful Vue 3 API composable (Muza Kit) with Axios, Auto-Refresh & TypeScript",
|
|
5
5
|
"author": "MortyQ",
|
|
6
6
|
"license": "MIT",
|
|
@@ -49,8 +49,12 @@
|
|
|
49
49
|
"vue": "^3.3.0"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
|
+
"@semantic-release/git": "^10.0.1",
|
|
53
|
+
"@semantic-release/github": "^12.0.3",
|
|
54
|
+
"@semantic-release/npm": "^13.1.3",
|
|
52
55
|
"@types/node": "^24.10.10",
|
|
53
56
|
"axios": "^1.13.4",
|
|
57
|
+
"semantic-release": "^25.0.3",
|
|
54
58
|
"tsup": "^8.5.1",
|
|
55
59
|
"typescript": "^5.9.3",
|
|
56
60
|
"vue": "^3.5.27"
|