commit
86a8385f2a
|
@ -1,14 +1,15 @@
|
||||||
package io.invertase.firebase.firestore;
|
package io.invertase.firebase.firestore;
|
||||||
|
|
||||||
|
import android.util.Base64;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.facebook.react.bridge.Arguments;
|
import com.facebook.react.bridge.Arguments;
|
||||||
import com.facebook.react.bridge.ReadableArray;
|
import com.facebook.react.bridge.ReadableArray;
|
||||||
import com.facebook.react.bridge.ReadableMap;
|
import com.facebook.react.bridge.ReadableMap;
|
||||||
import com.facebook.react.bridge.ReadableMapKeySetIterator;
|
import com.facebook.react.bridge.ReadableMapKeySetIterator;
|
||||||
import com.facebook.react.bridge.ReadableType;
|
|
||||||
import com.facebook.react.bridge.WritableArray;
|
import com.facebook.react.bridge.WritableArray;
|
||||||
import com.facebook.react.bridge.WritableMap;
|
import com.facebook.react.bridge.WritableMap;
|
||||||
|
import com.google.firebase.firestore.Blob;
|
||||||
import com.google.firebase.firestore.DocumentChange;
|
import com.google.firebase.firestore.DocumentChange;
|
||||||
import com.google.firebase.firestore.DocumentReference;
|
import com.google.firebase.firestore.DocumentReference;
|
||||||
import com.google.firebase.firestore.DocumentSnapshot;
|
import com.google.firebase.firestore.DocumentSnapshot;
|
||||||
|
@ -18,15 +19,11 @@ import com.google.firebase.firestore.FirebaseFirestore;
|
||||||
import com.google.firebase.firestore.GeoPoint;
|
import com.google.firebase.firestore.GeoPoint;
|
||||||
import com.google.firebase.firestore.QuerySnapshot;
|
import com.google.firebase.firestore.QuerySnapshot;
|
||||||
|
|
||||||
import java.text.DateFormat;
|
|
||||||
import java.text.ParseException;
|
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.TimeZone;
|
|
||||||
|
|
||||||
import io.invertase.firebase.Utils;
|
import io.invertase.firebase.Utils;
|
||||||
|
|
||||||
|
@ -214,6 +211,9 @@ public class FirestoreSerialize {
|
||||||
} else if (value instanceof Date) {
|
} else if (value instanceof Date) {
|
||||||
typeMap.putString("type", "date");
|
typeMap.putString("type", "date");
|
||||||
typeMap.putDouble("value", ((Date) value).getTime());
|
typeMap.putDouble("value", ((Date) value).getTime());
|
||||||
|
} else if (value instanceof Blob) {
|
||||||
|
typeMap.putString("type", "blob");
|
||||||
|
typeMap.putString("value", Base64.encodeToString(((Blob) value).toBytes(), Base64.NO_WRAP));
|
||||||
} else {
|
} else {
|
||||||
Log.e(TAG, "buildTypeMap: Cannot convert object of type " + value.getClass());
|
Log.e(TAG, "buildTypeMap: Cannot convert object of type " + value.getClass());
|
||||||
typeMap.putString("type", "null");
|
typeMap.putString("type", "null");
|
||||||
|
@ -266,6 +266,9 @@ public class FirestoreSerialize {
|
||||||
} else if ("geopoint".equals(type)) {
|
} else if ("geopoint".equals(type)) {
|
||||||
ReadableMap geoPoint = typeMap.getMap("value");
|
ReadableMap geoPoint = typeMap.getMap("value");
|
||||||
return new GeoPoint(geoPoint.getDouble("latitude"), geoPoint.getDouble("longitude"));
|
return new GeoPoint(geoPoint.getDouble("latitude"), geoPoint.getDouble("longitude"));
|
||||||
|
} else if ("blob".equals(type)) {
|
||||||
|
String base64String = typeMap.getString("value");
|
||||||
|
return Blob.fromBytes(Base64.decode(base64String, Base64.NO_WRAP));
|
||||||
} else if ("date".equals(type)) {
|
} else if ("date".equals(type)) {
|
||||||
Double time = typeMap.getDouble("value");
|
Double time = typeMap.getDouble("value");
|
||||||
return new Date(time.longValue());
|
return new Date(time.longValue());
|
||||||
|
|
|
@ -0,0 +1,132 @@
|
||||||
|
const testObject = { hello: 'world', testRunId };
|
||||||
|
const testString = JSON.stringify(testObject);
|
||||||
|
const testBuffer = Buffer.from(testString);
|
||||||
|
const testBase64 = testBuffer.toString('base64');
|
||||||
|
|
||||||
|
const testObjectLarge = new Array(5000).fill(testObject);
|
||||||
|
const testStringLarge = JSON.stringify(testObjectLarge);
|
||||||
|
const testBufferLarge = Buffer.from(testStringLarge);
|
||||||
|
const testBase64Large = testBufferLarge.toString('base64');
|
||||||
|
|
||||||
|
// function sizeInKiloBytes(base64String) {
|
||||||
|
// return 4 * Math.ceil(base64String.length / 3) / 1000;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// console.log(sizeInKiloBytes(testBase64));
|
||||||
|
// console.log(sizeInKiloBytes(testBase64Large));
|
||||||
|
|
||||||
|
/** ----------------
|
||||||
|
* CLASS TESTS
|
||||||
|
* -----------------*/
|
||||||
|
describe('firestore', () => {
|
||||||
|
it('should export Blob class on statics', async () => {
|
||||||
|
const { Blob } = firebase.firestore;
|
||||||
|
should.exist(Blob);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Blob', () => {
|
||||||
|
it('.constructor() -> returns new instance of Blob', async () => {
|
||||||
|
const { Blob } = firebase.firestore;
|
||||||
|
const myBlob = new Blob(testStringLarge);
|
||||||
|
myBlob.should.be.instanceOf(Blob);
|
||||||
|
myBlob._binaryString.should.equal(testStringLarge);
|
||||||
|
myBlob.toBase64().should.equal(testBase64Large);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('.fromBase64String() -> returns new instance of Blob', async () => {
|
||||||
|
const { Blob } = firebase.firestore;
|
||||||
|
const myBlob = Blob.fromBase64String(testBase64);
|
||||||
|
myBlob.should.be.instanceOf(Blob);
|
||||||
|
myBlob._binaryString.should.equal(testString);
|
||||||
|
should.deepEqual(
|
||||||
|
JSON.parse(myBlob._binaryString),
|
||||||
|
testObject,
|
||||||
|
'Expected Blob _binaryString internals to serialize to json and match test object'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('.fromUint8Array() -> returns new instance of Blob', async () => {
|
||||||
|
const testUInt8Array = new Uint8Array(testBuffer);
|
||||||
|
const { Blob } = firebase.firestore;
|
||||||
|
const myBlob = Blob.fromUint8Array(testUInt8Array);
|
||||||
|
myBlob.should.be.instanceOf(Blob);
|
||||||
|
const json = JSON.parse(myBlob._binaryString);
|
||||||
|
json.hello.should.equal('world');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Blob instance', () => {
|
||||||
|
it('.toString() -> returns string representation of blob instance', async () => {
|
||||||
|
const { Blob } = firebase.firestore;
|
||||||
|
const myBlob = Blob.fromBase64String(testBase64);
|
||||||
|
myBlob.should.be.instanceOf(Blob);
|
||||||
|
should.equal(
|
||||||
|
myBlob.toString().includes(testBase64),
|
||||||
|
true,
|
||||||
|
'toString() should return a string that includes the base64'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('.toBase64() -> returns base64 string', async () => {
|
||||||
|
const { Blob } = firebase.firestore;
|
||||||
|
const myBlob = Blob.fromBase64String(testBase64);
|
||||||
|
myBlob.should.be.instanceOf(Blob);
|
||||||
|
myBlob.toBase64().should.equal(testBase64);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('.toUint8Array() -> returns Uint8Array', async () => {
|
||||||
|
const { Blob } = firebase.firestore;
|
||||||
|
const myBlob = Blob.fromBase64String(testBase64);
|
||||||
|
const testUInt8Array = new Uint8Array(testBuffer);
|
||||||
|
const testUInt8Array2 = new Uint8Array();
|
||||||
|
|
||||||
|
myBlob.should.be.instanceOf(Blob);
|
||||||
|
should.deepEqual(myBlob.toUint8Array(), testUInt8Array);
|
||||||
|
should.notDeepEqual(myBlob.toUint8Array(), testUInt8Array2);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
/** ----------------
|
||||||
|
* USAGE TESTS
|
||||||
|
* -----------------*/
|
||||||
|
|
||||||
|
describe('firestore', () => {
|
||||||
|
describe('Blob', () => {
|
||||||
|
it('reads and writes small blobs', async () => {
|
||||||
|
const { Blob } = firebase.firestore;
|
||||||
|
|
||||||
|
await firebase
|
||||||
|
.firestore()
|
||||||
|
.doc('blob-tests/small')
|
||||||
|
.set({ blobby: Blob.fromBase64String(testBase64) });
|
||||||
|
|
||||||
|
const snapshot = await firebase
|
||||||
|
.firestore()
|
||||||
|
.doc('blob-tests/small')
|
||||||
|
.get();
|
||||||
|
|
||||||
|
const blob = snapshot.data().blobby;
|
||||||
|
blob._binaryString.should.equal(testString);
|
||||||
|
blob.toBase64().should.equal(testBase64);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('reads and writes large blobs', async () => {
|
||||||
|
const { Blob } = firebase.firestore;
|
||||||
|
|
||||||
|
await firebase
|
||||||
|
.firestore()
|
||||||
|
.doc('blob-tests/large')
|
||||||
|
.set({ blobby: Blob.fromBase64String(testBase64Large) });
|
||||||
|
|
||||||
|
const snapshot = await firebase
|
||||||
|
.firestore()
|
||||||
|
.doc('blob-tests/large')
|
||||||
|
.get();
|
||||||
|
|
||||||
|
const blob = snapshot.data().blobby;
|
||||||
|
blob._binaryString.should.equal(testStringLarge);
|
||||||
|
blob.toBase64().should.equal(testBase64Large);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -9,6 +9,38 @@ Object.defineProperty(global, 'firebase', {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// TODO move as part of bridge
|
||||||
|
const { Uint8Array } = global;
|
||||||
|
Object.defineProperty(global, 'Uint8Array', {
|
||||||
|
get() {
|
||||||
|
const { stack } = new Error();
|
||||||
|
if (
|
||||||
|
(stack.includes('Context.it') || stack.includes('Context.beforeEach')) &&
|
||||||
|
global.bridge &&
|
||||||
|
global.bridge.context
|
||||||
|
) {
|
||||||
|
return bridge.context.window.Uint8Array;
|
||||||
|
}
|
||||||
|
return Uint8Array;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// TODO move as part of bridge
|
||||||
|
const { Array } = global;
|
||||||
|
Object.defineProperty(global, 'Array', {
|
||||||
|
get() {
|
||||||
|
const { stack } = new Error();
|
||||||
|
if (
|
||||||
|
(stack.includes('Context.it') || stack.includes('Context.beforeEach')) &&
|
||||||
|
global.bridge &&
|
||||||
|
global.bridge.context
|
||||||
|
) {
|
||||||
|
return bridge.context.window.Array;
|
||||||
|
}
|
||||||
|
return Array;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
global.isObject = function isObject(item) {
|
global.isObject = function isObject(item) {
|
||||||
return item
|
return item
|
||||||
? typeof item === 'object' && !Array.isArray(item) && item !== null
|
? typeof item === 'object' && !Array.isArray(item) && item !== null
|
||||||
|
@ -30,11 +62,17 @@ global.randomString = (length, chars) => {
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
global.firebaseAdmin = require('firebase-admin');
|
|
||||||
|
|
||||||
global.testRunId = randomString(4, 'aA#');
|
global.testRunId = randomString(4, 'aA#');
|
||||||
|
|
||||||
|
/** ------------------
|
||||||
|
* Init WEB SDK
|
||||||
|
---------------------*/
|
||||||
|
|
||||||
|
/** ------------------
|
||||||
|
* Init ADMIN SDK
|
||||||
|
---------------------*/
|
||||||
|
global.firebaseAdmin = require('firebase-admin');
|
||||||
|
|
||||||
firebaseAdmin.initializeApp({
|
firebaseAdmin.initializeApp({
|
||||||
credential: firebaseAdmin.credential.cert(require('./service-account')),
|
credential: firebaseAdmin.credential.cert(require('./service-account')),
|
||||||
databaseURL: 'https://rnfirebase-b9ad4.firebaseio.com',
|
databaseURL: 'https://rnfirebase-b9ad4.firebaseio.com',
|
||||||
|
|
|
@ -208,6 +208,10 @@ static NSMutableDictionary *_listeners;
|
||||||
typeMap[@"type"] = @"number";
|
typeMap[@"type"] = @"number";
|
||||||
}
|
}
|
||||||
typeMap[@"value"] = value;
|
typeMap[@"value"] = value;
|
||||||
|
} else if ([value isKindOfClass:[NSData class]]) {
|
||||||
|
typeMap[@"type"] = @"blob";
|
||||||
|
NSData *blob = (NSData *)value;
|
||||||
|
typeMap[@"value"] = [blob base64EncodedStringWithOptions:0];
|
||||||
} else {
|
} else {
|
||||||
// TODO: Log an error
|
// TODO: Log an error
|
||||||
typeMap[@"type"] = @"null";
|
typeMap[@"type"] = @"null";
|
||||||
|
@ -248,6 +252,8 @@ static NSMutableDictionary *_listeners;
|
||||||
return [RNFirebaseFirestoreDocumentReference parseJSMap:firestore jsMap:value];
|
return [RNFirebaseFirestoreDocumentReference parseJSMap:firestore jsMap:value];
|
||||||
} else if ([type isEqualToString:@"reference"]) {
|
} else if ([type isEqualToString:@"reference"]) {
|
||||||
return [firestore documentWithPath:value];
|
return [firestore documentWithPath:value];
|
||||||
|
} else if ([type isEqualToString:@"blob"]) {
|
||||||
|
return [[NSData alloc] initWithBase64EncodedString:(NSString *) value options:0];
|
||||||
} else if ([type isEqualToString:@"geopoint"]) {
|
} else if ([type isEqualToString:@"geopoint"]) {
|
||||||
NSDictionary *geopoint = (NSDictionary*)value;
|
NSDictionary *geopoint = (NSDictionary*)value;
|
||||||
NSNumber *latitude = geopoint[@"latitude"];
|
NSNumber *latitude = geopoint[@"latitude"];
|
||||||
|
|
|
@ -0,0 +1,85 @@
|
||||||
|
import Base64 from './utils/Base64';
|
||||||
|
|
||||||
|
export default class Blob {
|
||||||
|
_binaryString: string;
|
||||||
|
|
||||||
|
constructor(binaryString) {
|
||||||
|
this._binaryString = binaryString;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new Blob from the given Base64 string
|
||||||
|
*
|
||||||
|
* @url https://firebase.google.com/docs/reference/js/firebase.firestore.Blob#.fromBase64String
|
||||||
|
* @param base64 string
|
||||||
|
*/
|
||||||
|
static fromBase64String(base64: string): Blob {
|
||||||
|
return new Blob(Base64.atob(base64));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new Blob from the given Uint8Array.
|
||||||
|
*
|
||||||
|
* @url https://firebase.google.com/docs/reference/js/firebase.firestore.Blob#.fromUint8Array
|
||||||
|
* @param array Array
|
||||||
|
*/
|
||||||
|
static fromUint8Array(array: Uint8Array): Blob {
|
||||||
|
if (!(array instanceof Uint8Array)) {
|
||||||
|
throw new Error(
|
||||||
|
'firestore.Blob.fromUint8Array expects an instance of Uint8Array'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Blob(
|
||||||
|
Array.prototype.map
|
||||||
|
.call(array, (char: number) => String.fromCharCode(char))
|
||||||
|
.join('')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns 'true' if this Blob is equal to the provided one.
|
||||||
|
* @url https://firebase.google.com/docs/reference/js/firebase.firestore.Blob#isEqual
|
||||||
|
* @param {*} blob Blob The Blob to compare against. Value must not be null.
|
||||||
|
* @returns boolean 'true' if this Blob is equal to the provided one.
|
||||||
|
*/
|
||||||
|
isEqual(blob: Blob): boolean {
|
||||||
|
if (!(blob instanceof Blob)) {
|
||||||
|
throw new Error('firestore.Blob.isEqual expects an instance of Blob');
|
||||||
|
}
|
||||||
|
|
||||||
|
return this._binaryString === blob._binaryString;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the bytes of a Blob as a Base64-encoded string.
|
||||||
|
*
|
||||||
|
* @url https://firebase.google.com/docs/reference/js/firebase.firestore.Blob#toBase64
|
||||||
|
* @returns string The Base64-encoded string created from the Blob object.
|
||||||
|
*/
|
||||||
|
toBase64(): string {
|
||||||
|
return Base64.btoa(this._binaryString);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the bytes of a Blob in a new Uint8Array.
|
||||||
|
*
|
||||||
|
* @url https://firebase.google.com/docs/reference/js/firebase.firestore.Blob#toUint8Array
|
||||||
|
* @returns non-null Uint8Array The Uint8Array created from the Blob object.
|
||||||
|
*/
|
||||||
|
toUint8Array(): Uint8Array {
|
||||||
|
return new Uint8Array(
|
||||||
|
this._binaryString.split('').map(c => c.charCodeAt(0))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a string representation of this blob instance
|
||||||
|
*
|
||||||
|
* @returns {string}
|
||||||
|
* @memberof Blob
|
||||||
|
*/
|
||||||
|
toString(): string {
|
||||||
|
return `firestore.Blob(base64: ${this.toBase64()})`;
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,6 +11,7 @@ import DocumentReference from './DocumentReference';
|
||||||
import FieldPath from './FieldPath';
|
import FieldPath from './FieldPath';
|
||||||
import FieldValue from './FieldValue';
|
import FieldValue from './FieldValue';
|
||||||
import GeoPoint from './GeoPoint';
|
import GeoPoint from './GeoPoint';
|
||||||
|
import Blob from './Blob';
|
||||||
import Path from './Path';
|
import Path from './Path';
|
||||||
import WriteBatch from './WriteBatch';
|
import WriteBatch from './WriteBatch';
|
||||||
import TransactionHandler from './TransactionHandler';
|
import TransactionHandler from './TransactionHandler';
|
||||||
|
@ -258,6 +259,7 @@ export const statics = {
|
||||||
FieldPath,
|
FieldPath,
|
||||||
FieldValue,
|
FieldValue,
|
||||||
GeoPoint,
|
GeoPoint,
|
||||||
|
Blob,
|
||||||
enableLogging(enabled: boolean): void {
|
enableLogging(enabled: boolean): void {
|
||||||
// DEPRECATED: Remove method in v4.1.0
|
// DEPRECATED: Remove method in v4.1.0
|
||||||
console.warn(
|
console.warn(
|
||||||
|
|
|
@ -42,6 +42,7 @@ export type NativeTypeMap = {
|
||||||
| 'array'
|
| 'array'
|
||||||
| 'boolean'
|
| 'boolean'
|
||||||
| 'date'
|
| 'date'
|
||||||
|
| 'blob'
|
||||||
| 'documentid'
|
| 'documentid'
|
||||||
| 'fieldvalue'
|
| 'fieldvalue'
|
||||||
| 'geopoint'
|
| 'geopoint'
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
// @flow
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
const CHARS =
|
||||||
|
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
/**
|
||||||
|
* window.btoa
|
||||||
|
*/
|
||||||
|
btoa(input: string = ''): string {
|
||||||
|
let map;
|
||||||
|
let i = 0;
|
||||||
|
let block = 0;
|
||||||
|
let output = '';
|
||||||
|
|
||||||
|
// eslint-disable-next-line
|
||||||
|
for (
|
||||||
|
block = 0, i = 0, map = CHARS;
|
||||||
|
input.charAt(i | 0) || ((map = '='), i % 1);
|
||||||
|
output += map.charAt(63 & (block >> (8 - (i % 1) * 8)))
|
||||||
|
) {
|
||||||
|
const charCode = input.charCodeAt((i += 3 / 4));
|
||||||
|
|
||||||
|
if (charCode > 0xff) {
|
||||||
|
throw new Error(
|
||||||
|
"'firestore.utils.btoa' failed: The string to be encoded contains characters outside of the Latin1 range."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
block = (block << 8) | charCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* window.atob
|
||||||
|
*/
|
||||||
|
atob(input: string = ''): string {
|
||||||
|
let i = 0;
|
||||||
|
let bc = 0;
|
||||||
|
let bs = 0;
|
||||||
|
let buffer;
|
||||||
|
let output = '';
|
||||||
|
|
||||||
|
const str = input.replace(/=+$/, '');
|
||||||
|
|
||||||
|
if (str.length % 4 === 1) {
|
||||||
|
throw new Error(
|
||||||
|
"'firestore.utils.atob' failed: The string to be decoded is not correctly encoded."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line
|
||||||
|
for (
|
||||||
|
bc = 0, bs = 0, i = 0;
|
||||||
|
(buffer = str.charAt(i++));
|
||||||
|
~buffer && ((bs = bc % 4 ? bs * 64 + buffer : buffer), bc++ % 4)
|
||||||
|
? (output += String.fromCharCode(255 & (bs >> ((-2 * bc) & 6))))
|
||||||
|
: 0
|
||||||
|
) {
|
||||||
|
buffer = CHARS.indexOf(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
},
|
||||||
|
};
|
|
@ -3,6 +3,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import DocumentReference from '../DocumentReference';
|
import DocumentReference from '../DocumentReference';
|
||||||
|
import Blob from '../Blob';
|
||||||
import { DOCUMENT_ID } from '../FieldPath';
|
import { DOCUMENT_ID } from '../FieldPath';
|
||||||
import {
|
import {
|
||||||
DELETE_FIELD_VALUE,
|
DELETE_FIELD_VALUE,
|
||||||
|
@ -98,6 +99,11 @@ export const buildTypeMap = (value: any): NativeTypeMap | null => {
|
||||||
type: 'date',
|
type: 'date',
|
||||||
value: value.getTime(),
|
value: value.getTime(),
|
||||||
};
|
};
|
||||||
|
} else if (value instanceof Blob) {
|
||||||
|
return {
|
||||||
|
type: 'blob',
|
||||||
|
value: value.toBase64(),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
|
@ -156,6 +162,8 @@ const parseTypeMap = (firestore: Firestore, typeMap: NativeTypeMap): any => {
|
||||||
return new GeoPoint(value.latitude, value.longitude);
|
return new GeoPoint(value.latitude, value.longitude);
|
||||||
} else if (type === 'date') {
|
} else if (type === 'date') {
|
||||||
return new Date(value);
|
return new Date(value);
|
||||||
|
} else if (type === 'blob') {
|
||||||
|
return Blob.fromBase64String(value);
|
||||||
}
|
}
|
||||||
console.warn(`Unknown data type received ${type}`);
|
console.warn(`Unknown data type received ${type}`);
|
||||||
return value;
|
return value;
|
||||||
|
|
Loading…
Reference in New Issue