{"version":3,"file":"mutationObserver.cjs","names":["Subscribable","shallowEqualObjects","hashKey","getDefaultState"],"sources":["../../src/mutationObserver.ts"],"sourcesContent":["import { getDefaultState } from './mutation'\nimport { notifyManager } from './notifyManager'\nimport { Subscribable } from './subscribable'\nimport { hashKey, shallowEqualObjects } from './utils'\nimport type { QueryClient } from './queryClient'\nimport type {\n  DefaultError,\n  MutateOptions,\n  MutationFunctionContext,\n  MutationObserverOptions,\n  MutationObserverResult,\n} from './types'\nimport type { Action, Mutation } from './mutation'\n\n// TYPES\n\ntype MutationObserverListener<TData, TError, TVariables, TOnMutateResult> = (\n  result: MutationObserverResult<TData, TError, TVariables, TOnMutateResult>,\n) => void\n\n// CLASS\n\n/**\n * Observes a single mutation and derives a `MutationObserverResult` from it.\n * A framework hook like `useMutation` creates one `MutationObserver` per hook\n * call, keeps it stable across re-renders, calls `setOptions` when the options\n * passed to the hook change, subscribes to it to re-render on updates, and\n * reads `getCurrentResult()` for the value to return. Calling `mutate()`\n * builds a new underlying `Mutation` in the `MutationCache` and executes it.\n * @example\n * ```ts\n * const observer = new MutationObserver(queryClient, {\n *   mutationFn: (variables: { title: string }) => addPost(variables),\n * })\n * ```\n */\nexport class MutationObserver<\n  TData = unknown,\n  TError = DefaultError,\n  TVariables = void,\n  TOnMutateResult = unknown,\n> extends Subscribable<\n  MutationObserverListener<TData, TError, TVariables, TOnMutateResult>\n> {\n  options!: MutationObserverOptions<TData, TError, TVariables, TOnMutateResult>\n\n  #client: QueryClient\n  #currentResult: MutationObserverResult<\n    TData,\n    TError,\n    TVariables,\n    TOnMutateResult\n  > = undefined!\n  #currentMutation?: Mutation<TData, TError, TVariables, TOnMutateResult>\n  #mutateOptions?: MutateOptions<TData, TError, TVariables, TOnMutateResult>\n\n  constructor(\n    client: QueryClient,\n    options: MutationObserverOptions<\n      TData,\n      TError,\n      TVariables,\n      TOnMutateResult\n    >,\n  ) {\n    super()\n\n    this.#client = client\n    this.setOptions(options)\n    this.bindMethods()\n    this.#updateResult()\n  }\n\n  /**\n   * Binds the methods of the result (`mutate` and `reset`) to the observer, so they keep working when\n   * destructured from it.\n   */\n  protected bindMethods(): void {\n    this.mutate = this.mutate.bind(this)\n    this.reset = this.reset.bind(this)\n  }\n\n  /**\n   * Updates the observer's options.\n   *\n   * If the new `mutationKey` differs from the previous one (and both were\n   * defined), the observer is reset, detaching it from the mutation it was\n   * observing. Otherwise, if the currently observed mutation is still\n   * `pending`, its options are updated in place as well.\n   * @param options - The new mutation observer options. They are defaulted with {@link\n   * QueryClient#defaultMutationOptions} before being applied.\n   * @example\n   * ```ts\n   * observer.setOptions({\n   *   mutationFn: (variables: { title: string }) => addPost(variables),\n   *   onSuccess: (data) => console.log(data),\n   * })\n   * ```\n   */\n  setOptions(\n    options: MutationObserverOptions<\n      TData,\n      TError,\n      TVariables,\n      TOnMutateResult\n    >,\n  ) {\n    const prevOptions = this.options as\n      | MutationObserverOptions<TData, TError, TVariables, TOnMutateResult>\n      | undefined\n    this.options = this.#client.defaultMutationOptions(options)\n    if (!shallowEqualObjects(this.options, prevOptions)) {\n      this.#client.getMutationCache().notify({\n        type: 'observerOptionsUpdated',\n        mutation: this.#currentMutation,\n        observer: this,\n      })\n    }\n\n    if (\n      prevOptions?.mutationKey &&\n      this.options.mutationKey &&\n      hashKey(prevOptions.mutationKey) !== hashKey(this.options.mutationKey)\n    ) {\n      this.reset()\n    } else if (this.#currentMutation?.state.status === 'pending') {\n      this.#currentMutation.setOptions(this.options)\n    }\n  }\n\n  protected override onSubscribe(): void {\n    if (this.listeners.size === 1 && this.#currentMutation) {\n      this.#currentMutation.addObserver(this)\n\n      this.#updateResult()\n    }\n  }\n\n  protected override onUnsubscribe(): void {\n    if (!this.hasListeners()) {\n      this.#currentMutation?.removeObserver(this)\n    }\n  }\n\n  /**\n   * Updates the observer's result when the observed mutation changes, and notifies its listeners.\n   * @internal\n   * @param action - The action that updated the observed mutation, passed on to the observer's\n   * callbacks.\n   */\n  onMutationUpdate(\n    action: Action<TData, TError, TVariables, TOnMutateResult>,\n  ): void {\n    this.#updateResult()\n\n    this.#notify(action)\n  }\n\n  /**\n   * Returns the observer's current result, derived from the observed\n   * mutation's state (or the default, `idle` state if no mutation has been\n   * built yet, e.g. before the first `mutate()` call or after `reset()`).\n   * @returns The observer's latest result.\n   */\n  getCurrentResult(): MutationObserverResult<\n    TData,\n    TError,\n    TVariables,\n    TOnMutateResult\n  > {\n    return this.#currentResult\n  }\n\n  /**\n   * Detaches the observer from the mutation it is currently observing (if\n   * any) and resets the observed result back to its default, `idle` state.\n   *\n   * This does not cancel an in-flight mutation; the mutation itself keeps\n   * running to completion and its own callbacks still fire, but this\n   * observer stops reflecting its state and a subsequent `mutate()` call\n   * will build a brand new mutation.\n   * @see {@link MutationObserver#mutate}\n   * @example\n   * ```ts\n   * observer.reset()\n   * ```\n   */\n  reset(): void {\n    // reset needs to remove the observer from the mutation because there is no way to \"get it back\"\n    // another mutate call will yield a new mutation!\n    this.#currentMutation?.removeObserver(this)\n    this.#currentMutation = undefined\n    this.#updateResult()\n    this.#notify()\n  }\n\n  /**\n   * Builds a new `Mutation` in the `MutationCache` using the observer's\n   * current options, detaches this observer from any previously observed\n   * mutation, attaches it to the new one, and executes it with the given\n   * variables.\n   *\n   * The optional per-call `options` (`onSuccess`/`onError`/`onSettled`) are\n   * invoked once the mutation settles, in addition to any callbacks defined\n   * on the observer's own options.\n   * @param variables - The variables passed to the `mutationFn`.\n   * @param options - Per-call `onSuccess`, `onError`, and `onSettled` callbacks.\n   * @returns A promise that resolves with the mutation's data, or rejects with its error.\n   * @example\n   * ```ts\n   * await observer.mutate(\n   *   { title: 'New post' },\n   *   { onSuccess: (data) => console.log(data) },\n   * )\n   * ```\n   */\n  mutate(\n    variables: TVariables,\n    options?: MutateOptions<TData, TError, TVariables, TOnMutateResult>,\n  ): Promise<TData> {\n    this.#mutateOptions = options\n\n    this.#currentMutation?.removeObserver(this)\n\n    this.#currentMutation = this.#client\n      .getMutationCache()\n      .build(this.#client, this.options)\n\n    this.#currentMutation.addObserver(this)\n\n    return this.#currentMutation.execute(variables)\n  }\n\n  #updateResult(): void {\n    const state =\n      this.#currentMutation?.state ??\n      getDefaultState<TData, TError, TVariables, TOnMutateResult>()\n\n    this.#currentResult = {\n      ...state,\n      isPending: state.status === 'pending',\n      isSuccess: state.status === 'success',\n      isError: state.status === 'error',\n      isIdle: state.status === 'idle',\n      mutate: this.mutate,\n      reset: this.reset,\n    } as MutationObserverResult<TData, TError, TVariables, TOnMutateResult>\n  }\n\n  #notify(action?: Action<TData, TError, TVariables, TOnMutateResult>): void {\n    notifyManager.batch(() => {\n      // First trigger the mutate callbacks\n      // Snapshot mutateOptions before dispatching — a callback (e.g. onSuccess)\n      // may call mutate() again, which overwrites this.#mutateOptions in place.\n      // Without the snapshot, onSettled would fire with the *next* mutation's\n      // options but the *current* mutation's data/variables.\n      const mutateOptions = this.#mutateOptions\n      if (mutateOptions && this.hasListeners()) {\n        const variables = this.#currentResult.variables!\n        const onMutateResult = this.#currentResult.context\n\n        const context = {\n          client: this.#client,\n          meta: this.options.meta,\n          mutationKey: this.options.mutationKey,\n        } satisfies MutationFunctionContext\n\n        if (action?.type === 'success') {\n          try {\n            mutateOptions.onSuccess?.(\n              action.data,\n              variables,\n              onMutateResult,\n              context,\n            )\n          } catch (e) {\n            void Promise.reject(e)\n          }\n          try {\n            mutateOptions.onSettled?.(\n              action.data,\n              null,\n              variables,\n              onMutateResult,\n              context,\n            )\n          } catch (e) {\n            void Promise.reject(e)\n          }\n        } else if (action?.type === 'error') {\n          try {\n            mutateOptions.onError?.(\n              action.error,\n              variables,\n              onMutateResult,\n              context,\n            )\n          } catch (e) {\n            void Promise.reject(e)\n          }\n          try {\n            mutateOptions.onSettled?.(\n              undefined,\n              action.error,\n              variables,\n              onMutateResult,\n              context,\n            )\n          } catch (e) {\n            void Promise.reject(e)\n          }\n        }\n      }\n\n      // Then trigger the listeners\n      this.listeners.forEach((listener) => {\n        listener(this.#currentResult)\n      })\n    })\n  }\n}\n"],"mappings":"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"}