@ametie/vue-muza-use 1.0.0 → 1.1.1

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
@@ -798,13 +798,15 @@ const { data } = useApi('/messages', {
798
798
  Apply to all `useApi` instances at once:
799
799
 
800
800
  ```typescript
801
- createApiClient({
802
- axios,
801
+ const api = createApiClient({ baseURL: 'https://api.example.com' })
802
+
803
+ app.use(createApi({
804
+ axios: api,
803
805
  globalOptions: {
804
806
  refetchOnFocus: true,
805
807
  refetchOnReconnect: true,
806
808
  },
807
- })
809
+ }))
808
810
  ```
809
811
 
810
812
  Opt individual requests out with `refetchOnFocus: false`:
package/dist/index.cjs CHANGED
@@ -374,6 +374,16 @@ function useApi(url, options = {}) {
374
374
  if (abortController2.value) abortController2.value.abort("Cancelled by new request");
375
375
  const controller = new AbortController();
376
376
  abortController2.value = controller;
377
+ if (config?.signal) {
378
+ const signal = config.signal;
379
+ if (signal.aborted) {
380
+ controller.abort(signal.reason);
381
+ } else {
382
+ signal.addEventListener("abort", () => {
383
+ controller.abort(signal.reason);
384
+ }, { once: true });
385
+ }
386
+ }
377
387
  let globalAbortHandler = null;
378
388
  let subscribedSignal = null;
379
389
  if (globalAbort) {
@@ -608,6 +618,8 @@ function useApiBatch(requests, options = {}) {
608
618
  concurrency,
609
619
  immediate = false,
610
620
  skipErrorNotification = true,
621
+ lazy = false,
622
+ poll = 0,
611
623
  watch: watchSource,
612
624
  onItemSuccess,
613
625
  onItemError,
@@ -632,13 +644,21 @@ function useApiBatch(requests, options = {}) {
632
644
  );
633
645
  const abortControllers = (0, import_vue6.ref)([]);
634
646
  let isAborted = false;
635
- const updateProgress = (succeeded, failed) => {
636
- const currentRequests = getRequests();
647
+ let pollTimer = null;
648
+ const getPollConfig = () => {
649
+ const val = (0, import_vue6.toValue)(poll);
650
+ if (typeof val === "number") return { interval: val, whenHidden: false };
651
+ return {
652
+ interval: (0, import_vue6.toValue)(val.interval),
653
+ whenHidden: (0, import_vue6.toValue)(val.whenHidden) ?? false
654
+ };
655
+ };
656
+ const updateProgress = (succeeded, failed, total) => {
637
657
  const completed = succeeded + failed;
638
658
  const newProgress = {
639
659
  completed,
640
- total: currentRequests.length,
641
- percentage: currentRequests.length > 0 ? Math.round(completed / currentRequests.length * 100) : 0,
660
+ total,
661
+ percentage: total > 0 ? Math.round(completed / total * 100) : 0,
642
662
  succeeded,
643
663
  failed
644
664
  };
@@ -655,7 +675,8 @@ function useApiBatch(requests, options = {}) {
655
675
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
656
676
  ...config.headers && { headers: config.headers },
657
677
  useGlobalAbort: false,
658
- skipErrorNotification
678
+ skipErrorNotification,
679
+ lazy: true
659
680
  }));
660
681
  const { execute: execute2, error: reqError, statusCode, response } = api;
661
682
  try {
@@ -710,7 +731,7 @@ function useApiBatch(requests, options = {}) {
710
731
  scope.stop();
711
732
  }
712
733
  };
713
- const executeWithConcurrency = async (requests2, limit) => {
734
+ const executeWithConcurrency = async (requests2, limit, total) => {
714
735
  const results = new Array(requests2.length);
715
736
  let succeededCount = 0;
716
737
  let failedCount = 0;
@@ -728,8 +749,9 @@ function useApiBatch(requests, options = {}) {
728
749
  errors.value.push(result.error);
729
750
  }
730
751
  }
731
- updateProgress(succeededCount, failedCount);
752
+ updateProgress(succeededCount, failedCount, total);
732
753
  if (!settled && !result.success && result.error) {
754
+ abort("First request failed in non-settled mode");
733
755
  throw result.error;
734
756
  }
735
757
  return result;
@@ -758,7 +780,7 @@ function useApiBatch(requests, options = {}) {
758
780
  errors.value.push(result.error);
759
781
  }
760
782
  }
761
- updateProgress(succeededCount, failedCount);
783
+ updateProgress(succeededCount, failedCount, total);
762
784
  if (!settled && !result.success && result.error) {
763
785
  abort("First request failed in non-settled mode");
764
786
  throw result.error;
@@ -775,6 +797,9 @@ function useApiBatch(requests, options = {}) {
775
797
  return results;
776
798
  };
777
799
  const execute = async () => {
800
+ if (loading.value) {
801
+ abort("Replaced by new execution");
802
+ }
778
803
  const currentRequests = getRequests();
779
804
  isAborted = false;
780
805
  loading.value = true;
@@ -782,20 +807,21 @@ function useApiBatch(requests, options = {}) {
782
807
  errors.value = [];
783
808
  data.value = [];
784
809
  abortControllers.value = [];
785
- updateProgress(0, 0);
810
+ const total = currentRequests.length;
811
+ updateProgress(0, 0, total);
812
+ let finalResults = [];
786
813
  try {
787
- const results = await executeWithConcurrency(currentRequests, concurrency);
788
- data.value = results;
789
- const allFailed = results.every((r) => !r.success);
790
- if (allFailed && results.length > 0) {
814
+ finalResults = await executeWithConcurrency(currentRequests, concurrency, total);
815
+ data.value = finalResults;
816
+ const allFailed = finalResults.every((r) => !r.success);
817
+ if (allFailed && finalResults.length > 0) {
791
818
  error.value = {
792
- message: `All ${results.length} requests failed`,
819
+ message: `All ${finalResults.length} requests failed`,
793
820
  status: 0,
794
821
  code: "BATCH_ALL_FAILED"
795
822
  };
796
823
  }
797
- onFinish?.(results);
798
- return results;
824
+ return finalResults;
799
825
  } catch (err) {
800
826
  if (!settled) {
801
827
  error.value = err;
@@ -804,10 +830,27 @@ function useApiBatch(requests, options = {}) {
804
830
  } finally {
805
831
  loading.value = false;
806
832
  abortControllers.value = [];
833
+ onFinish?.(finalResults);
834
+ if (!isAborted) {
835
+ const { interval, whenHidden } = getPollConfig();
836
+ if (interval > 0) {
837
+ const hidden = typeof document !== "undefined" && document.hidden;
838
+ if (whenHidden || !hidden) {
839
+ pollTimer = setTimeout(() => {
840
+ pollTimer = null;
841
+ execute();
842
+ }, interval);
843
+ }
844
+ }
845
+ }
807
846
  }
808
847
  };
809
848
  const abort = (message = "Batch aborted") => {
810
849
  isAborted = true;
850
+ if (pollTimer) {
851
+ clearTimeout(pollTimer);
852
+ pollTimer = null;
853
+ }
811
854
  for (const controller of abortControllers.value) {
812
855
  controller.abort(message);
813
856
  }
@@ -830,14 +873,26 @@ function useApiBatch(requests, options = {}) {
830
873
  if ((0, import_vue6.getCurrentScope)()) {
831
874
  (0, import_vue6.onScopeDispose)(() => abort("Scope disposed"));
832
875
  }
876
+ if (!lazy && typeof requests === "function") {
877
+ const trackingScope = (0, import_vue6.effectScope)();
878
+ trackingScope.run(() => {
879
+ const requestsComputed = (0, import_vue6.computed)(
880
+ () => requests().map(normalizeRequest)
881
+ );
882
+ (0, import_vue6.watch)(requestsComputed, () => {
883
+ execute();
884
+ }, { deep: true });
885
+ });
886
+ if ((0, import_vue6.getCurrentScope)()) (0, import_vue6.onScopeDispose)(() => trackingScope.stop());
887
+ execute();
888
+ } else if (immediate) {
889
+ execute();
890
+ }
833
891
  if (watchSource) {
834
892
  (0, import_vue6.watch)(watchSource, () => {
835
893
  execute();
836
894
  }, { deep: true });
837
895
  }
838
- if (immediate) {
839
- execute();
840
- }
841
896
  return {
842
897
  data,
843
898
  successfulData,
package/dist/index.d.cts CHANGED
@@ -139,7 +139,7 @@ interface UseApiOptions<T = unknown, D = unknown, TSelected = T> extends ApiRequ
139
139
  * Compatible with `lazy: true` — focus is a browser trigger, not a reactive dep.
140
140
  * Compatible with `poll` — both register separate listeners; `!loading` guard prevents duplicates.
141
141
  *
142
- * Can be set globally via `createApiClient({ globalOptions: { refetchOnFocus: true } })`.
142
+ * Can be set globally via `createApi({ axios, globalOptions: { refetchOnFocus: true } })`.
143
143
  * Per-request value takes precedence over global (including `false` to opt-out).
144
144
  */
145
145
  refetchOnFocus?: boolean | {
@@ -151,7 +151,7 @@ interface UseApiOptions<T = unknown, D = unknown, TSelected = T> extends ApiRequ
151
151
  * No throttle is applied — reconnect is already a rare event.
152
152
  * No refetch fires if a request is already in-flight (`loading: true`).
153
153
  *
154
- * Can be set globally via `createApiClient({ globalOptions: { refetchOnReconnect: true } })`.
154
+ * Can be set globally via `createApi({ axios, globalOptions: { refetchOnReconnect: true } })`.
155
155
  * Per-request value takes precedence over global (including `false` to opt-out).
156
156
  */
157
157
  refetchOnReconnect?: boolean;
@@ -336,7 +336,34 @@ interface UseApiBatchOptions<T = unknown, D = unknown> extends Omit<ApiRequestCo
336
336
  immediate?: boolean;
337
337
  /** Skip individual error notifications */
338
338
  skipErrorNotification?: boolean;
339
- /** Watch sources to trigger re-execution */
339
+ /**
340
+ * Disable auto-tracking. When true, reactive changes to the `requests` getter
341
+ * will NOT trigger re-execution. Use when you want full manual control via execute().
342
+ * Default: false — auto-tracks when `requests` is a function.
343
+ */
344
+ lazy?: boolean;
345
+ /**
346
+ * Polling interval in ms, or advanced config object.
347
+ * - Pass a number: `poll: 5000` — re-execute every 5 seconds.
348
+ * - Pass an object: `poll: { interval: 5000, whenHidden: false }` — skip polling when tab is hidden.
349
+ * Properties inside the object can also be Refs.
350
+ */
351
+ poll?: MaybeRefOrGetter<number | {
352
+ interval: MaybeRefOrGetter<number>;
353
+ whenHidden?: MaybeRefOrGetter<boolean>;
354
+ }>;
355
+ /**
356
+ * @deprecated Use a reactive getter for `requests` with `lazy: false` (default).
357
+ * Auto-tracking will re-execute when the getter's dependencies change.
358
+ * Will be removed in v2.0.
359
+ *
360
+ * @example
361
+ * // Before (deprecated):
362
+ * useApiBatch(() => ids.value.map(id => `/items/${id}`), { watch: ids })
363
+ *
364
+ * // After (preferred):
365
+ * useApiBatch(() => ids.value.map(id => `/items/${id}`))
366
+ */
340
367
  watch?: WatchSource | WatchSource[];
341
368
  /** Callback when a single request succeeds */
342
369
  onItemSuccess?: (item: BatchResultItem<T>, index: number) => void;
@@ -448,7 +475,7 @@ declare function useApiDelete<T = unknown, TSelected = T>(url: MaybeRefOrGetter<
448
475
  * - Abort support for all pending requests
449
476
  * - Detailed per-request results with URL mapping
450
477
  * - Progress tracking
451
- * - Watch option for auto re-execution
478
+ * - Auto-tracking for reactive getter requests (lazy: false default)
452
479
  *
453
480
  * @example
454
481
  * ```ts
@@ -466,11 +493,10 @@ declare function useApiDelete<T = unknown, TSelected = T>(url: MaybeRefOrGetter<
466
493
  * const ids = [1, 2, 3]
467
494
  * useApiBatch(ids.map(id => ({ url: `/users/${id}`, method: 'DELETE' })))
468
495
  *
469
- * // Reactive getter with object configs
496
+ * // Reactive getter auto-tracks deps, re-executes when pages changes
470
497
  * const pages = ref([1, 2, 3])
471
498
  * const { successfulData } = useApiBatch(
472
- * () => pages.value.map(page => ({ url: '/users', params: { page } })),
473
- * { watch: pages, immediate: true }
499
+ * () => pages.value.map(page => ({ url: '/users', params: { page } }))
474
500
  * )
475
501
  * ```
476
502
  */
package/dist/index.d.ts CHANGED
@@ -139,7 +139,7 @@ interface UseApiOptions<T = unknown, D = unknown, TSelected = T> extends ApiRequ
139
139
  * Compatible with `lazy: true` — focus is a browser trigger, not a reactive dep.
140
140
  * Compatible with `poll` — both register separate listeners; `!loading` guard prevents duplicates.
141
141
  *
142
- * Can be set globally via `createApiClient({ globalOptions: { refetchOnFocus: true } })`.
142
+ * Can be set globally via `createApi({ axios, globalOptions: { refetchOnFocus: true } })`.
143
143
  * Per-request value takes precedence over global (including `false` to opt-out).
144
144
  */
145
145
  refetchOnFocus?: boolean | {
@@ -151,7 +151,7 @@ interface UseApiOptions<T = unknown, D = unknown, TSelected = T> extends ApiRequ
151
151
  * No throttle is applied — reconnect is already a rare event.
152
152
  * No refetch fires if a request is already in-flight (`loading: true`).
153
153
  *
154
- * Can be set globally via `createApiClient({ globalOptions: { refetchOnReconnect: true } })`.
154
+ * Can be set globally via `createApi({ axios, globalOptions: { refetchOnReconnect: true } })`.
155
155
  * Per-request value takes precedence over global (including `false` to opt-out).
156
156
  */
157
157
  refetchOnReconnect?: boolean;
@@ -336,7 +336,34 @@ interface UseApiBatchOptions<T = unknown, D = unknown> extends Omit<ApiRequestCo
336
336
  immediate?: boolean;
337
337
  /** Skip individual error notifications */
338
338
  skipErrorNotification?: boolean;
339
- /** Watch sources to trigger re-execution */
339
+ /**
340
+ * Disable auto-tracking. When true, reactive changes to the `requests` getter
341
+ * will NOT trigger re-execution. Use when you want full manual control via execute().
342
+ * Default: false — auto-tracks when `requests` is a function.
343
+ */
344
+ lazy?: boolean;
345
+ /**
346
+ * Polling interval in ms, or advanced config object.
347
+ * - Pass a number: `poll: 5000` — re-execute every 5 seconds.
348
+ * - Pass an object: `poll: { interval: 5000, whenHidden: false }` — skip polling when tab is hidden.
349
+ * Properties inside the object can also be Refs.
350
+ */
351
+ poll?: MaybeRefOrGetter<number | {
352
+ interval: MaybeRefOrGetter<number>;
353
+ whenHidden?: MaybeRefOrGetter<boolean>;
354
+ }>;
355
+ /**
356
+ * @deprecated Use a reactive getter for `requests` with `lazy: false` (default).
357
+ * Auto-tracking will re-execute when the getter's dependencies change.
358
+ * Will be removed in v2.0.
359
+ *
360
+ * @example
361
+ * // Before (deprecated):
362
+ * useApiBatch(() => ids.value.map(id => `/items/${id}`), { watch: ids })
363
+ *
364
+ * // After (preferred):
365
+ * useApiBatch(() => ids.value.map(id => `/items/${id}`))
366
+ */
340
367
  watch?: WatchSource | WatchSource[];
341
368
  /** Callback when a single request succeeds */
342
369
  onItemSuccess?: (item: BatchResultItem<T>, index: number) => void;
@@ -448,7 +475,7 @@ declare function useApiDelete<T = unknown, TSelected = T>(url: MaybeRefOrGetter<
448
475
  * - Abort support for all pending requests
449
476
  * - Detailed per-request results with URL mapping
450
477
  * - Progress tracking
451
- * - Watch option for auto re-execution
478
+ * - Auto-tracking for reactive getter requests (lazy: false default)
452
479
  *
453
480
  * @example
454
481
  * ```ts
@@ -466,11 +493,10 @@ declare function useApiDelete<T = unknown, TSelected = T>(url: MaybeRefOrGetter<
466
493
  * const ids = [1, 2, 3]
467
494
  * useApiBatch(ids.map(id => ({ url: `/users/${id}`, method: 'DELETE' })))
468
495
  *
469
- * // Reactive getter with object configs
496
+ * // Reactive getter auto-tracks deps, re-executes when pages changes
470
497
  * const pages = ref([1, 2, 3])
471
498
  * const { successfulData } = useApiBatch(
472
- * () => pages.value.map(page => ({ url: '/users', params: { page } })),
473
- * { watch: pages, immediate: true }
499
+ * () => pages.value.map(page => ({ url: '/users', params: { page } }))
474
500
  * )
475
501
  * ```
476
502
  */
package/dist/index.mjs CHANGED
@@ -321,6 +321,16 @@ function useApi(url, options = {}) {
321
321
  if (abortController2.value) abortController2.value.abort("Cancelled by new request");
322
322
  const controller = new AbortController();
323
323
  abortController2.value = controller;
324
+ if (config?.signal) {
325
+ const signal = config.signal;
326
+ if (signal.aborted) {
327
+ controller.abort(signal.reason);
328
+ } else {
329
+ signal.addEventListener("abort", () => {
330
+ controller.abort(signal.reason);
331
+ }, { once: true });
332
+ }
333
+ }
324
334
  let globalAbortHandler = null;
325
335
  let subscribedSignal = null;
326
336
  if (globalAbort) {
@@ -555,6 +565,8 @@ function useApiBatch(requests, options = {}) {
555
565
  concurrency,
556
566
  immediate = false,
557
567
  skipErrorNotification = true,
568
+ lazy = false,
569
+ poll = 0,
558
570
  watch: watchSource,
559
571
  onItemSuccess,
560
572
  onItemError,
@@ -579,13 +591,21 @@ function useApiBatch(requests, options = {}) {
579
591
  );
580
592
  const abortControllers = ref4([]);
581
593
  let isAborted = false;
582
- const updateProgress = (succeeded, failed) => {
583
- const currentRequests = getRequests();
594
+ let pollTimer = null;
595
+ const getPollConfig = () => {
596
+ const val = toValue2(poll);
597
+ if (typeof val === "number") return { interval: val, whenHidden: false };
598
+ return {
599
+ interval: toValue2(val.interval),
600
+ whenHidden: toValue2(val.whenHidden) ?? false
601
+ };
602
+ };
603
+ const updateProgress = (succeeded, failed, total) => {
584
604
  const completed = succeeded + failed;
585
605
  const newProgress = {
586
606
  completed,
587
- total: currentRequests.length,
588
- percentage: currentRequests.length > 0 ? Math.round(completed / currentRequests.length * 100) : 0,
607
+ total,
608
+ percentage: total > 0 ? Math.round(completed / total * 100) : 0,
589
609
  succeeded,
590
610
  failed
591
611
  };
@@ -602,7 +622,8 @@ function useApiBatch(requests, options = {}) {
602
622
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
603
623
  ...config.headers && { headers: config.headers },
604
624
  useGlobalAbort: false,
605
- skipErrorNotification
625
+ skipErrorNotification,
626
+ lazy: true
606
627
  }));
607
628
  const { execute: execute2, error: reqError, statusCode, response } = api;
608
629
  try {
@@ -657,7 +678,7 @@ function useApiBatch(requests, options = {}) {
657
678
  scope.stop();
658
679
  }
659
680
  };
660
- const executeWithConcurrency = async (requests2, limit) => {
681
+ const executeWithConcurrency = async (requests2, limit, total) => {
661
682
  const results = new Array(requests2.length);
662
683
  let succeededCount = 0;
663
684
  let failedCount = 0;
@@ -675,8 +696,9 @@ function useApiBatch(requests, options = {}) {
675
696
  errors.value.push(result.error);
676
697
  }
677
698
  }
678
- updateProgress(succeededCount, failedCount);
699
+ updateProgress(succeededCount, failedCount, total);
679
700
  if (!settled && !result.success && result.error) {
701
+ abort("First request failed in non-settled mode");
680
702
  throw result.error;
681
703
  }
682
704
  return result;
@@ -705,7 +727,7 @@ function useApiBatch(requests, options = {}) {
705
727
  errors.value.push(result.error);
706
728
  }
707
729
  }
708
- updateProgress(succeededCount, failedCount);
730
+ updateProgress(succeededCount, failedCount, total);
709
731
  if (!settled && !result.success && result.error) {
710
732
  abort("First request failed in non-settled mode");
711
733
  throw result.error;
@@ -722,6 +744,9 @@ function useApiBatch(requests, options = {}) {
722
744
  return results;
723
745
  };
724
746
  const execute = async () => {
747
+ if (loading.value) {
748
+ abort("Replaced by new execution");
749
+ }
725
750
  const currentRequests = getRequests();
726
751
  isAborted = false;
727
752
  loading.value = true;
@@ -729,20 +754,21 @@ function useApiBatch(requests, options = {}) {
729
754
  errors.value = [];
730
755
  data.value = [];
731
756
  abortControllers.value = [];
732
- updateProgress(0, 0);
757
+ const total = currentRequests.length;
758
+ updateProgress(0, 0, total);
759
+ let finalResults = [];
733
760
  try {
734
- const results = await executeWithConcurrency(currentRequests, concurrency);
735
- data.value = results;
736
- const allFailed = results.every((r) => !r.success);
737
- if (allFailed && results.length > 0) {
761
+ finalResults = await executeWithConcurrency(currentRequests, concurrency, total);
762
+ data.value = finalResults;
763
+ const allFailed = finalResults.every((r) => !r.success);
764
+ if (allFailed && finalResults.length > 0) {
738
765
  error.value = {
739
- message: `All ${results.length} requests failed`,
766
+ message: `All ${finalResults.length} requests failed`,
740
767
  status: 0,
741
768
  code: "BATCH_ALL_FAILED"
742
769
  };
743
770
  }
744
- onFinish?.(results);
745
- return results;
771
+ return finalResults;
746
772
  } catch (err) {
747
773
  if (!settled) {
748
774
  error.value = err;
@@ -751,10 +777,27 @@ function useApiBatch(requests, options = {}) {
751
777
  } finally {
752
778
  loading.value = false;
753
779
  abortControllers.value = [];
780
+ onFinish?.(finalResults);
781
+ if (!isAborted) {
782
+ const { interval, whenHidden } = getPollConfig();
783
+ if (interval > 0) {
784
+ const hidden = typeof document !== "undefined" && document.hidden;
785
+ if (whenHidden || !hidden) {
786
+ pollTimer = setTimeout(() => {
787
+ pollTimer = null;
788
+ execute();
789
+ }, interval);
790
+ }
791
+ }
792
+ }
754
793
  }
755
794
  };
756
795
  const abort = (message = "Batch aborted") => {
757
796
  isAborted = true;
797
+ if (pollTimer) {
798
+ clearTimeout(pollTimer);
799
+ pollTimer = null;
800
+ }
758
801
  for (const controller of abortControllers.value) {
759
802
  controller.abort(message);
760
803
  }
@@ -777,14 +820,26 @@ function useApiBatch(requests, options = {}) {
777
820
  if (getCurrentScope3()) {
778
821
  onScopeDispose3(() => abort("Scope disposed"));
779
822
  }
823
+ if (!lazy && typeof requests === "function") {
824
+ const trackingScope = effectScope2();
825
+ trackingScope.run(() => {
826
+ const requestsComputed = computed2(
827
+ () => requests().map(normalizeRequest)
828
+ );
829
+ watch2(requestsComputed, () => {
830
+ execute();
831
+ }, { deep: true });
832
+ });
833
+ if (getCurrentScope3()) onScopeDispose3(() => trackingScope.stop());
834
+ execute();
835
+ } else if (immediate) {
836
+ execute();
837
+ }
780
838
  if (watchSource) {
781
839
  watch2(watchSource, () => {
782
840
  execute();
783
841
  }, { deep: true });
784
842
  }
785
- if (immediate) {
786
- execute();
787
- }
788
843
  return {
789
844
  data,
790
845
  successfulData,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ametie/vue-muza-use",
3
- "version": "1.0.0",
3
+ "version": "1.1.1",
4
4
  "description": "Powerful Vue 3 API composable (Muza) with Axios, Auto-Refresh & TypeScript",
5
5
  "author": "MortyQ",
6
6
  "license": "MIT",