createDoc method

Future<FeedbackResponse<DocumentReference<Object?>>> createDoc({
  1. required Writeable writeable,
  2. String? id,
  3. WriteBatch? writeBatch,
  4. TimestampType createTimeStampType = TimestampType.createdAndUpdated,
  5. TimestampType updateTimeStampType = TimestampType.updated,
  6. bool merge = false,
  7. List<FieldPath>? mergeFields,
  8. String? collectionPathOverride,
  9. Transaction? transaction,
})

Creates/writes data based on given writeable.

Passing in an id will give your document that id.

Passing in a writeBatch will close the WriteBatch and perform the last commit. If you want to add more to your WriteBatch then use the batchCreateDoc method instead.

The createTimeStampType determines the type of automatically added _createdFieldName and/or _updatedFieldName field(s) of Timestamp when merge is false. Pass in a TimestampType.none to avoid any of this automatic behaviour.

The updateTimeStampType determines the type of automatically added _createdFieldName and/or _updatedFieldName field(s) of Timestamp when merge is true or mergeFields != null. Pass in a TimestampType.none to avoid any of this automatic behaviour.

When merge is true this method will attempt an upsert if the document exists. If the document does not exist it will default to a regular create.

The mergeFields determine which fields to upsert, leave blank to upsert the entire object.

Implementation

Future<FeedbackResponse<DocumentReference>> createDoc({
  required Writeable writeable,
  String? id,
  WriteBatch? writeBatch,
  TimestampType createTimeStampType = TimestampType.createdAndUpdated,
  TimestampType updateTimeStampType = TimestampType.updated,
  bool merge = false,
  List<FieldPath>? mergeFields,
  String? collectionPathOverride,
  Transaction? transaction,
}) async {
  assert(
    _isCollectionGroup == (collectionPathOverride != null),
    'Firestore does not support finding a document by id when communicating with a collection group, '
    'therefore, you must specify the collectionPathOverride containing all parent collection and document ids '
    'in order to make this method work.',
  );
  try {
    _log.info(
        message: 'Checking if writeable is valid..', sensitiveData: null);
    final isValidResponse = writeable.isValidResponse();
    if (isValidResponse.isSuccess) {
      _log.success(message: 'Writeable is valid!', sensitiveData: null);
      _log.info(
        message: 'Creating document..',
        sensitiveData: _shouldNotSensitiveInfo
            ? null
            : SensitiveData(
                path: collectionPathOverride ?? _collectionPath(),
                id: id,
                isBatch: writeBatch != null,
                createTimeStampType: createTimeStampType,
                updateTimeStampType: updateTimeStampType,
                isMerge: merge,
                mergeFields: mergeFields,
                isTransaction: transaction != null,
              ),
      );
      final DocumentReference documentReference;
      if (writeBatch != null) {
        _log.info(
            message: 'WriteBatch was not null! Creating with batch..',
            sensitiveData: null);
        final lastBatchResponse = await batchCreateDoc(
          writeable: writeable,
          id: id,
          writeBatch: writeBatch,
          createTimeStampType: createTimeStampType,
          updateTimeStampType: updateTimeStampType,
          collectionPathOverride: collectionPathOverride,
          merge: merge,
          mergeFields: mergeFields,
        );
        _log.info(
            message: 'Checking if batchCreate was successful..',
            sensitiveData: null);
        if (lastBatchResponse.isSuccess) {
          final writeBatchWithReference = lastBatchResponse.result!;
          _log.info(
              message: 'Last batch was added with success! Committing..',
              sensitiveData: null);
          await writeBatchWithReference.writeBatch.commit();
          _log.success(
              message: 'Committing writeBatch done!', sensitiveData: null);
          documentReference = writeBatchWithReference.documentReference;
        } else {
          _log.error(message: 'Last batch failed!', sensitiveData: null);
          return _responseConfig.createFailedResponse(isPlural: true);
        }
      } else {
        _log.info(
            message: 'WriteBatch was null! Creating without batch..',
            sensitiveData: null);
        documentReference = id != null
            ? findDocRef(
                id: id,
                collectionPathOverride: collectionPathOverride,
              )
            : _firebaseFirestore
                .collection(collectionPathOverride ?? _collectionPath())
                .doc();
        _log.info(
          message: 'Creating JSON..',
          sensitiveData: null,
        );
        final writeableAsJson = (merge || mergeFields != null) &&
                (await documentReference.get(_getOptions)).exists
            ? updateTimeStampType.add(
                writeable.toJson(),
                updatedFieldName: _updatedFieldName,
                createdFieldName: _createdFieldName,
              )
            : createTimeStampType.add(
                writeable.toJson(),
                createdFieldName: _createdFieldName,
                updatedFieldName: _updatedFieldName,
              );
        var setOptions = SetOptions(
          merge: mergeFields == null ? merge : null,
          mergeFields: mergeFields,
        );
        if (transaction == null) {
          _log.info(
            message: 'Setting data with documentReference.set..',
            sensitiveData: _shouldNotSensitiveInfo
                ? null
                : SensitiveData(
                    path: collectionPathOverride ?? _collectionPath(),
                    id: documentReference.id,
                    data: writeableAsJson,
                  ),
          );
          await documentReference.set(
            writeableAsJson,
            setOptions,
          );
        } else {
          _log.info(
            message: 'Setting data with transaction.set..',
            sensitiveData: _shouldNotSensitiveInfo
                ? null
                : SensitiveData(
                    path: collectionPathOverride ?? _collectionPath(),
                    id: documentReference.id,
                    data: writeableAsJson,
                  ),
          );
          transaction.set(
            findDocRef(id: documentReference.id),
            writeableAsJson,
            setOptions,
          );
        }
      }
      _log.success(
        message: 'Setting data done!',
        sensitiveData: null,
      );
      return _responseConfig.createSuccessResponse(
        isPlural: writeBatch != null,
        result: documentReference,
      );
    }
    _log.warning(
      message: 'Writeable was invalid!',
      sensitiveData: null,
    );
    return FeedbackResponse.error(
      title: isValidResponse.title,
      message: isValidResponse.message,
    );
  } catch (error, stackTrace) {
    _log.error(
      message: 'Unable to create document',
      sensitiveData: _shouldNotSensitiveError
          ? null
          : SensitiveData(
              path: collectionPathOverride ?? _collectionPath(),
              id: id,
              isBatch: writeBatch != null,
              createTimeStampType: createTimeStampType,
              updateTimeStampType: updateTimeStampType,
              isMerge: merge,
              mergeFields: mergeFields,
              isTransaction: transaction != null,
            ),
      error: error,
      stackTrace: stackTrace,
    );
    return _responseConfig.createFailedResponse(isPlural: writeBatch != null);
  }
}