upsertDoc method

  1. @protected
Future<TurboResponse<T>> upsertDoc({
  1. Transaction? transaction,
  2. required String id,
  3. required UpsertDocDef<T> doc,
  4. TurboWriteable remoteUpdateRequestBuilder(
    1. T doc
    )?,
  5. bool doNotifyListeners = true,
})

Upserts (updates or inserts) a document both locally and in Firestore.

This method will either update an existing document or create a new one if it doesn't exist. The doc function receives the current document (or null if it doesn't exist) and should return the new document state.

Performs an optimistic upsert by updating the local state first, then syncing with Firestore. If the remote upsert fails, the local state remains updated.

Parameters:

  • transaction - Optional transaction for atomic operations
  • id - The ID of the document to upsert
  • doc - The definition of how to upsert the document
  • remoteUpdateRequestBuilder - Optional builder to modify the document before upserting
  • doNotifyListeners - Whether to notify listeners of the change

Returns a TurboResponse with the upserted document reference

Implementation

@protected
Future<TurboResponse<T>> upsertDoc({
  Transaction? transaction,
  required String id,
  required UpsertDocDef<T> doc,
  TurboWriteable Function(T doc)? remoteUpdateRequestBuilder,
  bool doNotifyListeners = true,
}) async {
  try {
    log.debug('Upserting doc with id: $id');
    final pDoc = upsertLocalDoc(
      id: id,
      doc: doc,
      doNotifyListeners: doNotifyListeners,
    );
    final future = api.createDoc(
      writeable: remoteUpdateRequestBuilder?.call(pDoc) ?? pDoc,
      id: id,
      transaction: transaction,
      merge: true,
    );
    final turboResponse = await future;
    if (transaction != null) {
      turboResponse.throwWhenFail();
    }
    return turboResponse.mapSuccess((_) => pDoc);
  } catch (error, stackTrace) {
    if (transaction != null) rethrow;
    log.error(
      '$error caught while upserting doc',
      error: error,
      stackTrace: stackTrace,
    );
    return TurboResponse.fail(error: error);
  }
}