mutate method

Future<TData?> mutate(
  1. TVariables variables, {
  2. void onSuccess(
    1. TData data,
    2. TVariables variables
    )?,
  3. void onError(
    1. Object error,
    2. TVariables variables
    )?,
  4. void onSettled(
    1. TData? data,
    2. Object? error,
    3. TVariables variables
    )?,
})

Execute the mutation.

You can provide call-time callbacks onSuccess, onError, and onSettled which will run after the mutation-level callbacks defined in the constructor.

Implementation

Future<TData?> mutate(
  TVariables variables, {
  void Function(TData data, TVariables variables)? onSuccess,
  void Function(Object error, TVariables variables)? onError,
  void Function(TData? data, Object? error, TVariables variables)? onSettled,
}) async {
  if (isDisposed) {
    throw StateError('Mutation has been disposed');
  }

  // Reset state
  status.value = ZenMutationStatus.loading;
  _isLoadingNotifier?.value = true;
  error.value = null;
  update();

  Object? context;

  try {
    // 1. Lifecycle: onMutate
    // Run immediately (optimistic updates depend on this)
    if (onMutate != null) {
      context = await onMutate!(variables);
    }

    // 2. Check Offline / Queueing
    if (mutationKey != null && !ZenQueryCache.instance.isOnline) {
      return _queueOfflineMutation(variables);
    }

    // Execute mutation
    final result = await mutationFn(variables);

    if (isDisposed) return null;

    // Update state: Success
    data.value = result;
    status.value = ZenMutationStatus.success;
    _isLoadingNotifier?.value = false;
    update();

    // Lifecycle callbacks...
    this.onSuccess?.call(result, variables, context);
    onSuccess?.call(result, variables);

    this.onSettled?.call(result, null, variables, context);
    onSettled?.call(result, null, variables);

    return result;
  } catch (e) {
    if (isDisposed) return null;

    // Check if we should queue due to network error during execution
    // (Simple check for now, can be improved to check Exception type)
    if (mutationKey != null && !ZenQueryCache.instance.isOnline) {
      return _queueOfflineMutation(variables);
    }

    // Update state: Error
    error.value = e;
    status.value = ZenMutationStatus.error;
    _isLoadingNotifier?.value = false;
    update();

    // Lifecycle callbacks...
    this.onError?.call(e, variables, context);
    onError?.call(e, variables);

    this.onSettled?.call(null, e, variables, context);
    onSettled?.call(null, e, variables);

    return null;
  }
}