all files / firebase/modules/firestore/ WriteBatch.js

100% Statements 26/26
100% Branches 10/10
100% Functions 5/5
100% Lines 26/26
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108                                                                                                  10× 10×             10×           16× 16×         12×       10× 12× 12× 12× 10×               10× 10×           10×      
/**
 * @flow
 * WriteBatch representation wrapper
 */
import FieldPath from './FieldPath';
import { mergeFieldPathData } from './utils';
import { buildNativeMap } from './utils/serialize';
import { isObject, isString } from '../../utils';
import { getNativeModule } from '../../utils/native';
 
import type DocumentReference from './DocumentReference';
import type Firestore from './';
import type { SetOptions } from './types';
 
type DocumentWrite = {
  data?: Object,
  options?: Object,
  path: string,
  type: 'DELETE' | 'SET' | 'UPDATE',
};
 
/**
 * @class WriteBatch
 */
export default class WriteBatch {
  _firestore: Firestore;
  _writes: DocumentWrite[];
 
  constructor(firestore: Firestore) {
    this._firestore = firestore;
    this._writes = [];
  }
 
  commit(): Promise<void> {
    return getNativeModule(this._firestore).documentBatch(this._writes);
  }
 
  delete(docRef: DocumentReference): WriteBatch {
    // TODO: Validation
    // validate.isDocumentReference('docRef', docRef);
    // validate.isOptionalPrecondition('deleteOptions', deleteOptions);
    this._writes.push({
      path: docRef.path,
      type: 'DELETE',
    });
 
    return this;
  }
 
  set(docRef: DocumentReference, data: Object, options?: SetOptions) {
    // TODO: Validation
    // validate.isDocumentReference('docRef', docRef);
    // validate.isDocument('data', data);
    // validate.isOptionalPrecondition('options', writeOptions);
    const nativeData = buildNativeMap(data);
    this._writes.push({
      data: nativeData,
      options,
      path: docRef.path,
      type: 'SET',
    });
 
    return this;
  }
 
  update(docRef: DocumentReference, ...args: any[]): WriteBatch {
    // TODO: Validation
    // validate.isDocumentReference('docRef', docRef);
    let data = {};
    if (args.length === 1) {
      if (!isObject(args[0])) {
        throw new Error(
          'WriteBatch.update failed: If using two arguments, the second must be an object.'
        );
      }
      // eslint-disable-next-line prefer-destructuring
      data = args[0];
    } else if (args.length % 2 === 1) {
      throw new Error(
        'WriteBatch.update failed: Must have a document reference, followed by either a single object argument, or equal numbers of key/value pairs.'
      );
    } else {
      for (let i = 0; i < args.length; i += 2) {
        const key = args[i];
        const value = args[i + 1];
        if (isString(key)) {
          data[key] = value;
        } else if (key instanceof FieldPath) {
          data = mergeFieldPathData(data, key._segments, value);
        } else {
          throw new Error(
            `WriteBatch.update failed: Argument at index ${i} must be a string or FieldPath`
          );
        }
      }
    }
 
    const nativeData = buildNativeMap(data);
    this._writes.push({
      data: nativeData,
      path: docRef.path,
      type: 'UPDATE',
    });
 
    return this;
  }
}