text: "use strict";
  /*!
   * Copyright 2018 Google Inc. All Rights Reserved.
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  Object.defineProperty(exports, "__esModule", { value: true });
  const deepEqual = require('deep-equal');
  const validate_1 = require("./validate");
  const validate = validate_1.createValidator();
  /**
   * Sentinel values that can be used when writing documents with set(), create()
   * or update().
   *
   * @class
   */
  class FieldValue {
      /**
       * @private
       * @hideconstructor
       */
      constructor() { }
      /**
       * Returns a sentinel for use with update() or set() with {merge:true} to mark
       * a field for deletion.
       *
       * @returns {FieldValue} The sentinel value to use in your objects.
       *
       * @example
       * let documentRef = firestore.doc('col/doc');
       * let data = { a: 'b', c: 'd' };
       *
       * documentRef.set(data).then(() => {
       *   return documentRef.update({a: Firestore.FieldValue.delete()});
       * }).then(() => {
       *   // Document now only contains { c: 'd' }
       * });
       */
      static delete() {
          return DeleteTransform.DELETE_SENTINEL;
      }
      /**
       * Returns a sentinel used with set(), create() or update() to include a
       * server-generated timestamp in the written data.
       *
       * @return {FieldValue} The FieldValue sentinel for use in a call to set(),
       * create() or update().
       *
       * @example
       * let documentRef = firestore.doc('col/doc');
       *
       * documentRef.set({
       *   time: Firestore.FieldValue.serverTimestamp()
       * }).then(() => {
       *   return documentRef.get();
       * }).then(doc => {
       *   console.log(`Server time set to ${doc.get('time')}`);
       * });
       */
      static serverTimestamp() {
          return ServerTimestampTransform.SERVER_TIMESTAMP_SENTINEL;
      }
      /**
       * Returns a special value that can be used with set(), create() or update()
       * that tells the server to union the given elements with any array value that
       * already exists on the server. Each specified element that doesn't already
       * exist in the array will be added to the end. If the field being modified is
       * not already an array it will be overwritten with an array containing
       * exactly the specified elements.
       *
       * @param {...*} elements The elements to union into the array.
       * @return {FieldValue} The FieldValue sentinel for use in a call to set(),
       * create() or update().
       *
       * @example
       * let documentRef = firestore.doc('col/doc');
       *
       * documentRef.update(
       *   'array', Firestore.FieldValue.arrayUnion('foo')
       * ).then(() => {
       *   return documentRef.get();
       * }).then(doc => {
       *   // doc.get('array') contains field 'foo'
       * });
       */
      static arrayUnion(...elements) {
          validate.minNumberOfArguments('FieldValue.arrayUnion', arguments, 1);
          return new ArrayUnionTransform(elements);
      }
      /**
       * Returns a special value that can be used with set(), create() or update()
       * that tells the server to remove the given elements from any array value
       * that already exists on the server. All instances of each element specified
       * will be removed from the array. If the field being modified is not already
       * an array it will be overwritten with an empty array.
       *
       * @param {...*} elements The elements to remove from the array.
       * @return {FieldValue} The FieldValue sentinel for use in a call to set(),
       * create() or update().
       *
       * @example
       * let documentRef = firestore.doc('col/doc');
       *
       * documentRef.update(
       *   'array', Firestore.FieldValue.arrayRemove('foo')
       * ).then(() => {
       *   return documentRef.get();
       * }).then(doc => {
       *   // doc.get('array') no longer contains field 'foo'
       * });
       */
      static arrayRemove(...elements) {
          validate.minNumberOfArguments('FieldValue.arrayRemove', arguments, 1);
          return new ArrayRemoveTransform(elements);
      }
      /**
       * Returns true if this `FieldValue` is equal to the provided value.
       *
       * @param {*} other The value to compare against.
       * @return {boolean} true if this `FieldValue` is equal to the provided value.
       */
      isEqual(other) {
          return this === other;
      }
  }
  exports.FieldValue = FieldValue;
  /**
   * An internal interface shared by all field transforms.
   *
   * A 'FieldTransform` subclass should implement '.includeInDocumentMask',
   * '.includeInDocumentTransform' and 'toProto' (if '.includeInDocumentTransform'
   * is 'true').
   *
   * @private
   * @abstract
   */
  class FieldTransform extends FieldValue {
  }
  exports.FieldTransform = FieldTransform;
  /**
   * A transform that deletes a field from a Firestore document.
   *
   * @private
   */
  class DeleteTransform extends FieldTransform {
      constructor() {
          super();
      }
      /**
       * Deletes are included in document masks.
       */
      get includeInDocumentMask() {
          return true;
      }
      /**
       * Deletes are are omitted from document transforms.
       */
      get includeInDocumentTransform() {
          return false;
      }
      get methodName() {
          return 'FieldValue.delete';
      }
      validate() {
          return true;
      }
      toProto(serializer, fieldPath) {
          throw new Error('FieldValue.delete() should not be included in a FieldTransform');
      }
  }
  /**
   * Sentinel value for a field delete.
   */
  DeleteTransform.DELETE_SENTINEL = new DeleteTransform();
  exports.DeleteTransform = DeleteTransform;
  /**
   * A transform that sets a field to the Firestore server time.
   *
   * @private
   */
  class ServerTimestampTransform extends FieldTransform {
      constructor() {
          super();
      }
      /**
       * Server timestamps are omitted from document masks.
       *
       * @private
       */
      get includeInDocumentMask() {
          return false;
      }
      /**
       * Server timestamps are included in document transforms.
       *
       * @private
       */
      get includeInDocumentTransform() {
          return true;
      }
      get methodName() {
          return 'FieldValue.serverTimestamp';
      }
      validate() {
          return true;
      }
      toProto(serializer, fieldPath) {
          return {
              fieldPath: fieldPath.formattedName,
              setToServerValue: 'REQUEST_TIME',
          };
      }
  }
  /**
   * Sentinel value for a server timestamp.
   *
   * @private
   */
  ServerTimestampTransform.SERVER_TIMESTAMP_SENTINEL = new ServerTimestampTransform();
  /**
   * Transforms an array value via a union operation.
   *
   * @private
   */
  class ArrayUnionTransform extends FieldTransform {
      constructor(elements) {
          super();
          this.elements = elements;
      }
      /**
       * Array transforms are omitted from document masks.
       */
      get includeInDocumentMask() {
          return false;
      }
      /**
       * Array transforms are included in document transforms.
       */
      get includeInDocumentTransform() {
          return true;
      }
      get methodName() {
          return 'FieldValue.arrayUnion';
      }
      validate(validator) {
          let valid = true;
          for (let i = 0; valid && i < this.elements.length; ++i) {
              valid = validator.isArrayElement(i, this.elements[i], { allowDeletes: 'none', allowTransforms: false });
          }
          return valid;
      }
      toProto(serializer, fieldPath) {
          const encodedElements = serializer.encodeValue(this.elements).arrayValue;
          return {
              fieldPath: fieldPath.formattedName,
              appendMissingElements: encodedElements
          };
      }
      isEqual(other) {
          return (this === other ||
              (other instanceof ArrayUnionTransform &&
                  deepEqual(this.elements, other.elements, { strict: true })));
      }
  }
  /**
   * Transforms an array value via a remove operation.
   *
   * @private
   */
  class ArrayRemoveTransform extends FieldTransform {
      constructor(elements) {
          super();
          this.elements = elements;
      }
      /**
       * Array transforms are omitted from document masks.
       */
      get includeInDocumentMask() {
          return false;
      }
      /**
       * Array transforms are included in document transforms.
       */
      get includeInDocumentTransform() {
          return true;
      }
      get methodName() {
          return 'FieldValue.arrayRemove';
      }
      validate(validator) {
          let valid = true;
          for (let i = 0; valid && i < this.elements.length; ++i) {
              valid = validator.isArrayElement(i, this.elements[i], { allowDeletes: 'none', allowTransforms: false });
          }
          return valid;
      }
      toProto(serializer, fieldPath) {
          const encodedElements = serializer.encodeValue(this.elements).arrayValue;
          return {
              fieldPath: fieldPath.formattedName,
              removeAllFromArray: encodedElements
          };
      }
      isEqual(other) {
          return (this === other ||
              (other instanceof ArrayRemoveTransform &&
                  deepEqual(this.elements, other.elements, { strict: true })));
      }
  }
  //# sourceMappingURL=field-value.js.map