export function objectToValueProto()

in src/providers/firestore.ts [150:246]


export function objectToValueProto(data: object) {
  const encodeHelper = (val) => {
    if (typeof val === 'string') {
      return {
        stringValue: val,
      };
    }
    if (typeof val === 'boolean') {
      return {
        booleanValue: val,
      };
    }
    if (typeof val === 'number') {
      if (val % 1 === 0) {
        return {
          integerValue: val,
        };
      }
      return {
        doubleValue: val,
      };
    }
    if (val instanceof Date) {
      return {
        timestampValue: val.toISOString(),
      };
    }
    if (val instanceof Array) {
      let encodedElements = [];
      for (const elem of val) {
        const enc = encodeHelper(elem);
        if (enc) {
          encodedElements.push(enc);
        }
      }
      return {
        arrayValue: {
          values: encodedElements,
        },
      };
    }
    if (val === null) {
      // TODO: Look this up. This is a google.protobuf.NulLValue,
      // and everything in google.protobuf has a customized JSON encoder.
      // OTOH, Firestore's generated .d.ts files don't take this into
      // account and have the default proto layout.
      return {
        nullValue: 'NULL_VALUE',
      };
    }
    if (val instanceof Buffer || val instanceof Uint8Array) {
      return {
        bytesValue: val,
      };
    }
    if (val instanceof firestore.DocumentReference) {
      const projectId: string = get(val, '_referencePath.projectId');
      const database: string = get(val, '_referencePath.databaseId');
      const referenceValue: string = [
        'projects',
        projectId,
        'databases',
        database,
        val.path,
      ].join('/');
      return { referenceValue };
    }
    if (val instanceof firestore.Timestamp) {
      return {
        timestampValue: val.toDate().toISOString(),
      };
    }
    if (val instanceof firestore.GeoPoint) {
      return {
        geoPointValue: {
          latitude: val.latitude,
          longitude: val.longitude,
        },
      };
    }
    if (isPlainObject(val)) {
      return {
        mapValue: {
          fields: objectToValueProto(val),
        },
      };
    }
    throw new Error(
      'Cannot encode ' +
        val +
        'to a Firestore Value.' +
        ` Local testing does not yet support objects of type ${val?.constructor?.name}.`
    );
  };

  return mapValues(data, encodeHelper);
}