@braine/quantum-query 1.3.3 → 1.3.4

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/dist/index.cjs CHANGED
@@ -40,6 +40,7 @@ __export(index_exports, {
40
40
  unwrapPromise: () => unwrapPromise,
41
41
  useCombinedQueries: () => useCombinedQueries,
42
42
  useInfiniteQuery: () => useInfiniteQuery,
43
+ useMutation: () => useMutation,
43
44
  usePaginatedQuery: () => usePaginatedQuery,
44
45
  useQueries: () => useQueries,
45
46
  useQuery: () => useQuery,
@@ -2243,9 +2244,156 @@ function useSuspenseQuery(options) {
2243
2244
  };
2244
2245
  }
2245
2246
 
2246
- // src/query/infiniteQuery.ts
2247
+ // src/query/useMutation.ts
2247
2248
  var import_react9 = require("react");
2248
2249
 
2250
+ // src/query/mutationObserver.ts
2251
+ var generateId = () => {
2252
+ if (typeof crypto !== "undefined" && crypto.randomUUID) {
2253
+ return crypto.randomUUID();
2254
+ }
2255
+ return "mutation-" + Date.now() + "-" + Math.random().toString(36).slice(2);
2256
+ };
2257
+ var MutationObserver = class {
2258
+ client;
2259
+ options;
2260
+ currentMutationId = null;
2261
+ // We maintain our own signal for this observer's view of the mutation
2262
+ // This ensures we don't miss updates if we switch IDs.
2263
+ signal;
2264
+ constructor(client, options) {
2265
+ this.client = client;
2266
+ this.options = options;
2267
+ this.signal = createSignal({
2268
+ status: "idle",
2269
+ data: void 0,
2270
+ error: null,
2271
+ variables: void 0,
2272
+ context: void 0,
2273
+ submittedAt: 0
2274
+ });
2275
+ }
2276
+ setOptions(options) {
2277
+ this.options = options;
2278
+ }
2279
+ mutate = (variables) => {
2280
+ const id = generateId();
2281
+ this.currentMutationId = id;
2282
+ this.client.mutationCache.register(id, this.options.mutationKey);
2283
+ const pendingState = {
2284
+ status: "pending",
2285
+ variables,
2286
+ submittedAt: Date.now(),
2287
+ data: void 0,
2288
+ error: null,
2289
+ context: void 0
2290
+ };
2291
+ this.signal.set({
2292
+ ...this.signal.get(),
2293
+ ...pendingState
2294
+ });
2295
+ this.client.mutationCache.notify(id, pendingState);
2296
+ const unsubscribe = this.client.mutationCache.getSignal(id).subscribe((state) => {
2297
+ untracked(() => {
2298
+ const current = this.signal.get();
2299
+ if (current.status !== state.status || current.data !== state.data || current.error !== state.error) {
2300
+ this.signal.set(state);
2301
+ }
2302
+ });
2303
+ });
2304
+ return this.executeMutation(id, variables).finally(() => {
2305
+ });
2306
+ };
2307
+ executeMutation = async (id, variables) => {
2308
+ const { mutationFn, onMutate, onSuccess, onError, onSettled, invalidatesTags, optimistic, mutationKey } = this.options;
2309
+ let context;
2310
+ let optimisticSnapshot;
2311
+ const notify = (update) => {
2312
+ this.client.mutationCache.notify(id, update);
2313
+ };
2314
+ try {
2315
+ if (optimistic) {
2316
+ const { queryKey, update } = optimistic;
2317
+ const signal2 = this.client.getSignal(queryKey);
2318
+ const currentData = signal2.get()?.data;
2319
+ optimisticSnapshot = currentData;
2320
+ const optimisticData = update(variables, currentData);
2321
+ this.client.set(queryKey, optimisticData);
2322
+ }
2323
+ if (onMutate) {
2324
+ context = await onMutate(variables);
2325
+ notify({ context });
2326
+ }
2327
+ const result = await mutationFn(variables);
2328
+ notify({ status: "success", data: result });
2329
+ if (onSuccess) await onSuccess(result, variables, context);
2330
+ if (this.client.invalidateTags && invalidatesTags) {
2331
+ this.client.invalidateTags(invalidatesTags);
2332
+ }
2333
+ if (optimistic) {
2334
+ this.client.invalidate(optimistic.queryKey);
2335
+ }
2336
+ if (onSettled) onSettled(result, null, variables, context);
2337
+ return result;
2338
+ } catch (error) {
2339
+ if (optimistic && optimisticSnapshot !== void 0) {
2340
+ this.client.set(optimistic.queryKey, optimisticSnapshot);
2341
+ }
2342
+ const errorObj = error instanceof Error ? error : new Error(String(error));
2343
+ notify({ status: "error", error: errorObj });
2344
+ if (onError) onError(errorObj, variables, context);
2345
+ if (onSettled) onSettled(void 0, errorObj, variables, context);
2346
+ throw error;
2347
+ }
2348
+ };
2349
+ reset = () => {
2350
+ this.signal.set({
2351
+ status: "idle",
2352
+ data: void 0,
2353
+ error: null,
2354
+ variables: void 0,
2355
+ context: void 0,
2356
+ submittedAt: 0
2357
+ });
2358
+ this.currentMutationId = null;
2359
+ };
2360
+ };
2361
+
2362
+ // src/query/useMutation.ts
2363
+ function useMutation(options) {
2364
+ const client = useQueryClient();
2365
+ const [observer] = (0, import_react9.useState)(() => new MutationObserver(client, options));
2366
+ (0, import_react9.useEffect)(() => {
2367
+ observer.setOptions(options);
2368
+ }, [observer, options]);
2369
+ const state = (0, import_react9.useSyncExternalStore)(
2370
+ (0, import_react9.useCallback)((cb) => observer.signal.subscribe(cb), [observer]),
2371
+ () => observer.signal.get()
2372
+ );
2373
+ const mutateAsync = (0, import_react9.useCallback)((variables) => {
2374
+ return observer.mutate(variables);
2375
+ }, [observer]);
2376
+ const mutate = (0, import_react9.useCallback)((variables) => {
2377
+ observer.mutate(variables).catch(() => {
2378
+ });
2379
+ }, [observer]);
2380
+ return {
2381
+ mutate,
2382
+ mutateAsync,
2383
+ data: state.data,
2384
+ error: state.error,
2385
+ status: state.status,
2386
+ isLoading: state.status === "pending",
2387
+ isError: state.status === "error",
2388
+ isSuccess: state.status === "success",
2389
+ isIdle: state.status === "idle",
2390
+ reset: observer.reset
2391
+ };
2392
+ }
2393
+
2394
+ // src/query/infiniteQuery.ts
2395
+ var import_react10 = require("react");
2396
+
2249
2397
  // src/query/plugins/logger.ts
2250
2398
  var consoleLogger = {
2251
2399
  log: console.log,
@@ -2517,26 +2665,26 @@ var InfiniteQueryObserver = class {
2517
2665
  // src/query/infiniteQuery.ts
2518
2666
  function useInfiniteQuery(options) {
2519
2667
  const client = useQueryClient();
2520
- const [observer] = (0, import_react9.useState)(() => new InfiniteQueryObserver(client, options));
2521
- (0, import_react9.useEffect)(() => {
2668
+ const [observer] = (0, import_react10.useState)(() => new InfiniteQueryObserver(client, options));
2669
+ (0, import_react10.useEffect)(() => {
2522
2670
  observer.setOptions(options);
2523
2671
  }, [observer, options]);
2524
- (0, import_react9.useEffect)(() => {
2672
+ (0, import_react10.useEffect)(() => {
2525
2673
  return () => {
2526
2674
  observer.destroy();
2527
2675
  };
2528
2676
  }, [observer]);
2529
- const subscribe = (0, import_react9.useCallback)((onStoreChange) => {
2677
+ const subscribe = (0, import_react10.useCallback)((onStoreChange) => {
2530
2678
  return observer.result$.subscribe(() => onStoreChange());
2531
2679
  }, [observer]);
2532
- const getSnapshot = (0, import_react9.useCallback)(() => {
2680
+ const getSnapshot = (0, import_react10.useCallback)(() => {
2533
2681
  return observer.result$.get();
2534
2682
  }, [observer]);
2535
- return (0, import_react9.useSyncExternalStore)(subscribe, getSnapshot);
2683
+ return (0, import_react10.useSyncExternalStore)(subscribe, getSnapshot);
2536
2684
  }
2537
2685
 
2538
2686
  // src/query/HydrationBoundary.tsx
2539
- var import_react10 = require("react");
2687
+ var import_react11 = require("react");
2540
2688
 
2541
2689
  // src/query/hydration.ts
2542
2690
  function dehydrate(client) {
@@ -2564,7 +2712,7 @@ function hydrate(client, state) {
2564
2712
  var import_jsx_runtime6 = require("react/jsx-runtime");
2565
2713
  function HydrationBoundary({ state, children }) {
2566
2714
  const client = useQueryClient();
2567
- const hydratedRef = (0, import_react10.useRef)(false);
2715
+ const hydratedRef = (0, import_react11.useRef)(false);
2568
2716
  if (state && !hydratedRef.current) {
2569
2717
  hydrate(client, state);
2570
2718
  hydratedRef.current = true;
@@ -2573,14 +2721,14 @@ function HydrationBoundary({ state, children }) {
2573
2721
  }
2574
2722
 
2575
2723
  // src/query/useQuerySignal.ts
2576
- var import_react11 = require("react");
2724
+ var import_react12 = require("react");
2577
2725
  function useQuery$(options) {
2578
2726
  const client = useQueryClient();
2579
- const [observer] = (0, import_react11.useState)(() => new QueryObserver(client, options));
2580
- (0, import_react11.useEffect)(() => {
2727
+ const [observer] = (0, import_react12.useState)(() => new QueryObserver(client, options));
2728
+ (0, import_react12.useEffect)(() => {
2581
2729
  observer.setOptions(options);
2582
2730
  }, [observer, options.enabled, options.staleTime, options.cacheTime, options.queryKey, options.refetchInterval]);
2583
- (0, import_react11.useEffect)(() => {
2731
+ (0, import_react12.useEffect)(() => {
2584
2732
  const unsubscribe = observer.subscribe(() => {
2585
2733
  });
2586
2734
  return () => {
@@ -2592,18 +2740,18 @@ function useQuery$(options) {
2592
2740
  }
2593
2741
 
2594
2742
  // src/query/useQueries.ts
2595
- var import_react12 = require("react");
2743
+ var import_react13 = require("react");
2596
2744
  function useQueries(queries, client) {
2597
2745
  const queryClient = client || globalThis.__QUANTUM_CLIENT__;
2598
2746
  if (!queryClient) {
2599
2747
  throw new Error("[Quantum] No QueryClient found. Wrap your app with QueryClientProvider or pass a client.");
2600
2748
  }
2601
- const [observers] = (0, import_react12.useState)(
2749
+ const [observers] = (0, import_react13.useState)(
2602
2750
  () => queries.map(
2603
2751
  (options) => new QueryObserver(queryClient, options)
2604
2752
  )
2605
2753
  );
2606
- const results = (0, import_react12.useSyncExternalStore)(
2754
+ const results = (0, import_react13.useSyncExternalStore)(
2607
2755
  (callback) => {
2608
2756
  const unsubscribes = observers.map((observer) => observer.subscribe(callback));
2609
2757
  return () => {
@@ -2613,7 +2761,7 @@ function useQueries(queries, client) {
2613
2761
  () => observers.map((observer) => observer.getSnapshot()),
2614
2762
  () => observers.map((observer) => observer.getSnapshot())
2615
2763
  );
2616
- (0, import_react12.useEffect)(() => {
2764
+ (0, import_react13.useEffect)(() => {
2617
2765
  queries.forEach((options, index) => {
2618
2766
  const observer = observers[index];
2619
2767
  if (observer) {
@@ -2621,7 +2769,7 @@ function useQueries(queries, client) {
2621
2769
  }
2622
2770
  });
2623
2771
  }, [queries, observers]);
2624
- (0, import_react12.useEffect)(() => {
2772
+ (0, import_react13.useEffect)(() => {
2625
2773
  return () => {
2626
2774
  observers.forEach((observer) => observer.destroy());
2627
2775
  };
@@ -2671,6 +2819,7 @@ function useCombinedQueries(queries, client) {
2671
2819
  unwrapPromise,
2672
2820
  useCombinedQueries,
2673
2821
  useInfiniteQuery,
2822
+ useMutation,
2674
2823
  usePaginatedQuery,
2675
2824
  useQueries,
2676
2825
  useQuery,
package/dist/index.d.cts CHANGED
@@ -380,6 +380,33 @@ type SuspenseQueryResult<T> = Omit<UseQueryResult<T, T>, 'data' | 'isLoading' |
380
380
  };
381
381
  declare function useSuspenseQuery<T>(options: UseSuspenseQueryOptions<T>): SuspenseQueryResult<T>;
382
382
 
383
+ interface UseMutationOptions<TData, TVariables, TContext = unknown> {
384
+ mutationFn: (variables: TVariables) => Promise<TData>;
385
+ mutationKey?: unknown[];
386
+ onMutate?: (variables: TVariables) => Promise<TContext> | TContext;
387
+ onSuccess?: (data: TData, variables: TVariables, context: TContext | undefined) => void;
388
+ onError?: (error: Error, variables: TVariables, context: TContext | undefined) => void;
389
+ onSettled?: (data: TData | undefined, error: Error | null, variables: TVariables, context: TContext | undefined) => void;
390
+ invalidatesTags?: string[];
391
+ optimistic?: {
392
+ queryKey: unknown[];
393
+ update: (variables: TVariables, oldData: unknown) => unknown;
394
+ };
395
+ }
396
+ interface MutationResult<TData, TVariables> {
397
+ mutate: (variables: TVariables) => void;
398
+ mutateAsync: (variables: TVariables) => Promise<TData>;
399
+ data: TData | undefined;
400
+ error: Error | null;
401
+ isLoading: boolean;
402
+ isError: boolean;
403
+ isSuccess: boolean;
404
+ isIdle: boolean;
405
+ status: 'idle' | 'pending' | 'success' | 'error';
406
+ reset: () => void;
407
+ }
408
+ declare function useMutation<TData = unknown, TVariables = void, TContext = unknown>(options: UseMutationOptions<TData, TVariables, TContext>): MutationResult<TData, TVariables>;
409
+
383
410
  declare const QueryClientProvider: ({ client, children }: {
384
411
  client: QueryClient;
385
412
  children: ReactNode | undefined;
@@ -521,4 +548,4 @@ declare function useCombinedQueries<T extends readonly UseQueryOptions<any, any>
521
548
  refetchAll: () => Promise<void[]>;
522
549
  };
523
550
 
524
- export { type CacheEntry, HydrationBoundary, Match, MutationCache, type MutationState, type MutationStatus, type PaginatedQueryResult, QuantumDevTools, QueryClient, QueryClientProvider, type QueryKey, type QueryKeyInput, QueryMatch, type QueryPlugin, type QueryStatus, type Signal, SignalValue, type SuspenseQueryResult, type UsePaginatedQueryOptions, type UseQueriesResult, type UseQueryOptions, type UseQueryResult, type UseSuspenseQueryOptions, atom, createHttpClient, dehydrate, enableDevTools, getPromiseState, handlePromise, hydrate, isPromise, scheduleUpdate, unwrapPromise, useCombinedQueries, useInfiniteQuery, usePaginatedQuery, useQueries, useQuery, useQuery$, useQueryClient, useQueryStore, useSuspenseQuery };
551
+ export { type CacheEntry, HydrationBoundary, Match, MutationCache, type MutationResult, type MutationState, type MutationStatus, type PaginatedQueryResult, QuantumDevTools, QueryClient, QueryClientProvider, type QueryKey, type QueryKeyInput, QueryMatch, type QueryPlugin, type QueryStatus, type Signal, SignalValue, type SuspenseQueryResult, type UseMutationOptions, type UsePaginatedQueryOptions, type UseQueriesResult, type UseQueryOptions, type UseQueryResult, type UseSuspenseQueryOptions, atom, createHttpClient, dehydrate, enableDevTools, getPromiseState, handlePromise, hydrate, isPromise, scheduleUpdate, unwrapPromise, useCombinedQueries, useInfiniteQuery, useMutation, usePaginatedQuery, useQueries, useQuery, useQuery$, useQueryClient, useQueryStore, useSuspenseQuery };
package/dist/index.d.ts CHANGED
@@ -380,6 +380,33 @@ type SuspenseQueryResult<T> = Omit<UseQueryResult<T, T>, 'data' | 'isLoading' |
380
380
  };
381
381
  declare function useSuspenseQuery<T>(options: UseSuspenseQueryOptions<T>): SuspenseQueryResult<T>;
382
382
 
383
+ interface UseMutationOptions<TData, TVariables, TContext = unknown> {
384
+ mutationFn: (variables: TVariables) => Promise<TData>;
385
+ mutationKey?: unknown[];
386
+ onMutate?: (variables: TVariables) => Promise<TContext> | TContext;
387
+ onSuccess?: (data: TData, variables: TVariables, context: TContext | undefined) => void;
388
+ onError?: (error: Error, variables: TVariables, context: TContext | undefined) => void;
389
+ onSettled?: (data: TData | undefined, error: Error | null, variables: TVariables, context: TContext | undefined) => void;
390
+ invalidatesTags?: string[];
391
+ optimistic?: {
392
+ queryKey: unknown[];
393
+ update: (variables: TVariables, oldData: unknown) => unknown;
394
+ };
395
+ }
396
+ interface MutationResult<TData, TVariables> {
397
+ mutate: (variables: TVariables) => void;
398
+ mutateAsync: (variables: TVariables) => Promise<TData>;
399
+ data: TData | undefined;
400
+ error: Error | null;
401
+ isLoading: boolean;
402
+ isError: boolean;
403
+ isSuccess: boolean;
404
+ isIdle: boolean;
405
+ status: 'idle' | 'pending' | 'success' | 'error';
406
+ reset: () => void;
407
+ }
408
+ declare function useMutation<TData = unknown, TVariables = void, TContext = unknown>(options: UseMutationOptions<TData, TVariables, TContext>): MutationResult<TData, TVariables>;
409
+
383
410
  declare const QueryClientProvider: ({ client, children }: {
384
411
  client: QueryClient;
385
412
  children: ReactNode | undefined;
@@ -521,4 +548,4 @@ declare function useCombinedQueries<T extends readonly UseQueryOptions<any, any>
521
548
  refetchAll: () => Promise<void[]>;
522
549
  };
523
550
 
524
- export { type CacheEntry, HydrationBoundary, Match, MutationCache, type MutationState, type MutationStatus, type PaginatedQueryResult, QuantumDevTools, QueryClient, QueryClientProvider, type QueryKey, type QueryKeyInput, QueryMatch, type QueryPlugin, type QueryStatus, type Signal, SignalValue, type SuspenseQueryResult, type UsePaginatedQueryOptions, type UseQueriesResult, type UseQueryOptions, type UseQueryResult, type UseSuspenseQueryOptions, atom, createHttpClient, dehydrate, enableDevTools, getPromiseState, handlePromise, hydrate, isPromise, scheduleUpdate, unwrapPromise, useCombinedQueries, useInfiniteQuery, usePaginatedQuery, useQueries, useQuery, useQuery$, useQueryClient, useQueryStore, useSuspenseQuery };
551
+ export { type CacheEntry, HydrationBoundary, Match, MutationCache, type MutationResult, type MutationState, type MutationStatus, type PaginatedQueryResult, QuantumDevTools, QueryClient, QueryClientProvider, type QueryKey, type QueryKeyInput, QueryMatch, type QueryPlugin, type QueryStatus, type Signal, SignalValue, type SuspenseQueryResult, type UseMutationOptions, type UsePaginatedQueryOptions, type UseQueriesResult, type UseQueryOptions, type UseQueryResult, type UseSuspenseQueryOptions, atom, createHttpClient, dehydrate, enableDevTools, getPromiseState, handlePromise, hydrate, isPromise, scheduleUpdate, unwrapPromise, useCombinedQueries, useInfiniteQuery, useMutation, usePaginatedQuery, useQueries, useQuery, useQuery$, useQueryClient, useQueryStore, useSuspenseQuery };
package/dist/index.js CHANGED
@@ -2197,8 +2197,155 @@ function useSuspenseQuery(options) {
2197
2197
  };
2198
2198
  }
2199
2199
 
2200
+ // src/query/useMutation.ts
2201
+ import { useCallback as useCallback3, useEffect as useEffect6, useSyncExternalStore as useSyncExternalStore3, useState as useState7 } from "react";
2202
+
2203
+ // src/query/mutationObserver.ts
2204
+ var generateId = () => {
2205
+ if (typeof crypto !== "undefined" && crypto.randomUUID) {
2206
+ return crypto.randomUUID();
2207
+ }
2208
+ return "mutation-" + Date.now() + "-" + Math.random().toString(36).slice(2);
2209
+ };
2210
+ var MutationObserver = class {
2211
+ client;
2212
+ options;
2213
+ currentMutationId = null;
2214
+ // We maintain our own signal for this observer's view of the mutation
2215
+ // This ensures we don't miss updates if we switch IDs.
2216
+ signal;
2217
+ constructor(client, options) {
2218
+ this.client = client;
2219
+ this.options = options;
2220
+ this.signal = createSignal({
2221
+ status: "idle",
2222
+ data: void 0,
2223
+ error: null,
2224
+ variables: void 0,
2225
+ context: void 0,
2226
+ submittedAt: 0
2227
+ });
2228
+ }
2229
+ setOptions(options) {
2230
+ this.options = options;
2231
+ }
2232
+ mutate = (variables) => {
2233
+ const id = generateId();
2234
+ this.currentMutationId = id;
2235
+ this.client.mutationCache.register(id, this.options.mutationKey);
2236
+ const pendingState = {
2237
+ status: "pending",
2238
+ variables,
2239
+ submittedAt: Date.now(),
2240
+ data: void 0,
2241
+ error: null,
2242
+ context: void 0
2243
+ };
2244
+ this.signal.set({
2245
+ ...this.signal.get(),
2246
+ ...pendingState
2247
+ });
2248
+ this.client.mutationCache.notify(id, pendingState);
2249
+ const unsubscribe = this.client.mutationCache.getSignal(id).subscribe((state) => {
2250
+ untracked(() => {
2251
+ const current = this.signal.get();
2252
+ if (current.status !== state.status || current.data !== state.data || current.error !== state.error) {
2253
+ this.signal.set(state);
2254
+ }
2255
+ });
2256
+ });
2257
+ return this.executeMutation(id, variables).finally(() => {
2258
+ });
2259
+ };
2260
+ executeMutation = async (id, variables) => {
2261
+ const { mutationFn, onMutate, onSuccess, onError, onSettled, invalidatesTags, optimistic, mutationKey } = this.options;
2262
+ let context;
2263
+ let optimisticSnapshot;
2264
+ const notify = (update) => {
2265
+ this.client.mutationCache.notify(id, update);
2266
+ };
2267
+ try {
2268
+ if (optimistic) {
2269
+ const { queryKey, update } = optimistic;
2270
+ const signal2 = this.client.getSignal(queryKey);
2271
+ const currentData = signal2.get()?.data;
2272
+ optimisticSnapshot = currentData;
2273
+ const optimisticData = update(variables, currentData);
2274
+ this.client.set(queryKey, optimisticData);
2275
+ }
2276
+ if (onMutate) {
2277
+ context = await onMutate(variables);
2278
+ notify({ context });
2279
+ }
2280
+ const result = await mutationFn(variables);
2281
+ notify({ status: "success", data: result });
2282
+ if (onSuccess) await onSuccess(result, variables, context);
2283
+ if (this.client.invalidateTags && invalidatesTags) {
2284
+ this.client.invalidateTags(invalidatesTags);
2285
+ }
2286
+ if (optimistic) {
2287
+ this.client.invalidate(optimistic.queryKey);
2288
+ }
2289
+ if (onSettled) onSettled(result, null, variables, context);
2290
+ return result;
2291
+ } catch (error) {
2292
+ if (optimistic && optimisticSnapshot !== void 0) {
2293
+ this.client.set(optimistic.queryKey, optimisticSnapshot);
2294
+ }
2295
+ const errorObj = error instanceof Error ? error : new Error(String(error));
2296
+ notify({ status: "error", error: errorObj });
2297
+ if (onError) onError(errorObj, variables, context);
2298
+ if (onSettled) onSettled(void 0, errorObj, variables, context);
2299
+ throw error;
2300
+ }
2301
+ };
2302
+ reset = () => {
2303
+ this.signal.set({
2304
+ status: "idle",
2305
+ data: void 0,
2306
+ error: null,
2307
+ variables: void 0,
2308
+ context: void 0,
2309
+ submittedAt: 0
2310
+ });
2311
+ this.currentMutationId = null;
2312
+ };
2313
+ };
2314
+
2315
+ // src/query/useMutation.ts
2316
+ function useMutation(options) {
2317
+ const client = useQueryClient();
2318
+ const [observer] = useState7(() => new MutationObserver(client, options));
2319
+ useEffect6(() => {
2320
+ observer.setOptions(options);
2321
+ }, [observer, options]);
2322
+ const state = useSyncExternalStore3(
2323
+ useCallback3((cb) => observer.signal.subscribe(cb), [observer]),
2324
+ () => observer.signal.get()
2325
+ );
2326
+ const mutateAsync = useCallback3((variables) => {
2327
+ return observer.mutate(variables);
2328
+ }, [observer]);
2329
+ const mutate = useCallback3((variables) => {
2330
+ observer.mutate(variables).catch(() => {
2331
+ });
2332
+ }, [observer]);
2333
+ return {
2334
+ mutate,
2335
+ mutateAsync,
2336
+ data: state.data,
2337
+ error: state.error,
2338
+ status: state.status,
2339
+ isLoading: state.status === "pending",
2340
+ isError: state.status === "error",
2341
+ isSuccess: state.status === "success",
2342
+ isIdle: state.status === "idle",
2343
+ reset: observer.reset
2344
+ };
2345
+ }
2346
+
2200
2347
  // src/query/infiniteQuery.ts
2201
- import { useState as useState7, useEffect as useEffect6, useCallback as useCallback3, useSyncExternalStore as useSyncExternalStore3 } from "react";
2348
+ import { useState as useState8, useEffect as useEffect7, useCallback as useCallback4, useSyncExternalStore as useSyncExternalStore4 } from "react";
2202
2349
 
2203
2350
  // src/query/plugins/logger.ts
2204
2351
  var consoleLogger = {
@@ -2471,22 +2618,22 @@ var InfiniteQueryObserver = class {
2471
2618
  // src/query/infiniteQuery.ts
2472
2619
  function useInfiniteQuery(options) {
2473
2620
  const client = useQueryClient();
2474
- const [observer] = useState7(() => new InfiniteQueryObserver(client, options));
2475
- useEffect6(() => {
2621
+ const [observer] = useState8(() => new InfiniteQueryObserver(client, options));
2622
+ useEffect7(() => {
2476
2623
  observer.setOptions(options);
2477
2624
  }, [observer, options]);
2478
- useEffect6(() => {
2625
+ useEffect7(() => {
2479
2626
  return () => {
2480
2627
  observer.destroy();
2481
2628
  };
2482
2629
  }, [observer]);
2483
- const subscribe = useCallback3((onStoreChange) => {
2630
+ const subscribe = useCallback4((onStoreChange) => {
2484
2631
  return observer.result$.subscribe(() => onStoreChange());
2485
2632
  }, [observer]);
2486
- const getSnapshot = useCallback3(() => {
2633
+ const getSnapshot = useCallback4(() => {
2487
2634
  return observer.result$.get();
2488
2635
  }, [observer]);
2489
- return useSyncExternalStore3(subscribe, getSnapshot);
2636
+ return useSyncExternalStore4(subscribe, getSnapshot);
2490
2637
  }
2491
2638
 
2492
2639
  // src/query/HydrationBoundary.tsx
@@ -2527,14 +2674,14 @@ function HydrationBoundary({ state, children }) {
2527
2674
  }
2528
2675
 
2529
2676
  // src/query/useQuerySignal.ts
2530
- import { useEffect as useEffect7, useState as useState8 } from "react";
2677
+ import { useEffect as useEffect8, useState as useState9 } from "react";
2531
2678
  function useQuery$(options) {
2532
2679
  const client = useQueryClient();
2533
- const [observer] = useState8(() => new QueryObserver(client, options));
2534
- useEffect7(() => {
2680
+ const [observer] = useState9(() => new QueryObserver(client, options));
2681
+ useEffect8(() => {
2535
2682
  observer.setOptions(options);
2536
2683
  }, [observer, options.enabled, options.staleTime, options.cacheTime, options.queryKey, options.refetchInterval]);
2537
- useEffect7(() => {
2684
+ useEffect8(() => {
2538
2685
  const unsubscribe = observer.subscribe(() => {
2539
2686
  });
2540
2687
  return () => {
@@ -2546,18 +2693,18 @@ function useQuery$(options) {
2546
2693
  }
2547
2694
 
2548
2695
  // src/query/useQueries.ts
2549
- import { useEffect as useEffect8, useState as useState9, useSyncExternalStore as useSyncExternalStore4 } from "react";
2696
+ import { useEffect as useEffect9, useState as useState10, useSyncExternalStore as useSyncExternalStore5 } from "react";
2550
2697
  function useQueries(queries, client) {
2551
2698
  const queryClient = client || globalThis.__QUANTUM_CLIENT__;
2552
2699
  if (!queryClient) {
2553
2700
  throw new Error("[Quantum] No QueryClient found. Wrap your app with QueryClientProvider or pass a client.");
2554
2701
  }
2555
- const [observers] = useState9(
2702
+ const [observers] = useState10(
2556
2703
  () => queries.map(
2557
2704
  (options) => new QueryObserver(queryClient, options)
2558
2705
  )
2559
2706
  );
2560
- const results = useSyncExternalStore4(
2707
+ const results = useSyncExternalStore5(
2561
2708
  (callback) => {
2562
2709
  const unsubscribes = observers.map((observer) => observer.subscribe(callback));
2563
2710
  return () => {
@@ -2567,7 +2714,7 @@ function useQueries(queries, client) {
2567
2714
  () => observers.map((observer) => observer.getSnapshot()),
2568
2715
  () => observers.map((observer) => observer.getSnapshot())
2569
2716
  );
2570
- useEffect8(() => {
2717
+ useEffect9(() => {
2571
2718
  queries.forEach((options, index) => {
2572
2719
  const observer = observers[index];
2573
2720
  if (observer) {
@@ -2575,7 +2722,7 @@ function useQueries(queries, client) {
2575
2722
  }
2576
2723
  });
2577
2724
  }, [queries, observers]);
2578
- useEffect8(() => {
2725
+ useEffect9(() => {
2579
2726
  return () => {
2580
2727
  observers.forEach((observer) => observer.destroy());
2581
2728
  };
@@ -2624,6 +2771,7 @@ export {
2624
2771
  unwrapPromise,
2625
2772
  useCombinedQueries,
2626
2773
  useInfiniteQuery,
2774
+ useMutation,
2627
2775
  usePaginatedQuery,
2628
2776
  useQueries,
2629
2777
  useQuery,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@braine/quantum-query",
3
- "version": "1.3.3",
3
+ "version": "1.3.4",
4
4
  "type": "module",
5
5
  "main": "index.js",
6
6
  "scripts": {