2017-11-17 11:07:52 +00:00
|
|
|
/**
|
|
|
|
* @flow
|
|
|
|
*/
|
2017-10-10 14:36:08 +00:00
|
|
|
|
|
|
|
import DocumentReference from '../DocumentReference';
|
2018-05-03 19:13:51 +00:00
|
|
|
import Blob from '../Blob';
|
2018-01-11 18:28:14 +00:00
|
|
|
import { DOCUMENT_ID } from '../FieldPath';
|
2018-01-25 18:25:39 +00:00
|
|
|
import {
|
|
|
|
DELETE_FIELD_VALUE,
|
|
|
|
SERVER_TIMESTAMP_FIELD_VALUE,
|
|
|
|
} from '../FieldValue';
|
2017-10-10 14:36:08 +00:00
|
|
|
import GeoPoint from '../GeoPoint';
|
|
|
|
import Path from '../Path';
|
|
|
|
import { typeOf } from '../../../utils';
|
|
|
|
|
2017-11-17 11:07:52 +00:00
|
|
|
import type Firestore from '../';
|
2018-02-14 13:00:19 +00:00
|
|
|
import type { NativeTypeMap } from '../types';
|
2017-11-17 11:07:52 +00:00
|
|
|
|
2017-10-10 14:36:08 +00:00
|
|
|
/*
|
|
|
|
* Functions that build up the data needed to represent
|
|
|
|
* the different types available within Firestore
|
|
|
|
* for transmission to the native side
|
|
|
|
*/
|
|
|
|
|
2018-02-14 13:00:19 +00:00
|
|
|
export const buildNativeMap = (data: Object): { [string]: NativeTypeMap } => {
|
2017-10-10 14:36:08 +00:00
|
|
|
const nativeData = {};
|
|
|
|
if (data) {
|
2018-01-25 18:25:39 +00:00
|
|
|
Object.keys(data).forEach(key => {
|
2017-11-17 11:07:52 +00:00
|
|
|
const typeMap = buildTypeMap(data[key]);
|
|
|
|
if (typeMap) {
|
|
|
|
nativeData[key] = typeMap;
|
|
|
|
}
|
2017-10-10 14:36:08 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
return nativeData;
|
|
|
|
};
|
|
|
|
|
2018-02-14 13:00:19 +00:00
|
|
|
export const buildNativeArray = (array: Object[]): NativeTypeMap[] => {
|
2017-10-10 14:36:08 +00:00
|
|
|
const nativeArray = [];
|
|
|
|
if (array) {
|
2018-01-25 18:25:39 +00:00
|
|
|
array.forEach(value => {
|
2017-11-17 11:07:52 +00:00
|
|
|
const typeMap = buildTypeMap(value);
|
|
|
|
if (typeMap) {
|
|
|
|
nativeArray.push(typeMap);
|
|
|
|
}
|
2017-10-10 14:36:08 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
return nativeArray;
|
|
|
|
};
|
|
|
|
|
2018-02-14 13:00:19 +00:00
|
|
|
export const buildTypeMap = (value: any): NativeTypeMap | null => {
|
2017-10-10 14:36:08 +00:00
|
|
|
const type = typeOf(value);
|
2018-02-23 02:59:39 +00:00
|
|
|
if (value === null || value === undefined || Number.isNaN(value)) {
|
2017-11-17 11:07:52 +00:00
|
|
|
return {
|
|
|
|
type: 'null',
|
|
|
|
value: null,
|
|
|
|
};
|
2017-10-12 08:00:46 +00:00
|
|
|
} else if (value === DELETE_FIELD_VALUE) {
|
2017-11-17 11:07:52 +00:00
|
|
|
return {
|
|
|
|
type: 'fieldvalue',
|
|
|
|
value: 'delete',
|
|
|
|
};
|
2017-10-12 08:00:46 +00:00
|
|
|
} else if (value === SERVER_TIMESTAMP_FIELD_VALUE) {
|
2017-11-17 11:07:52 +00:00
|
|
|
return {
|
|
|
|
type: 'fieldvalue',
|
|
|
|
value: 'timestamp',
|
|
|
|
};
|
2018-01-11 18:28:14 +00:00
|
|
|
} else if (value === DOCUMENT_ID) {
|
|
|
|
return {
|
|
|
|
type: 'documentid',
|
2018-01-16 17:08:44 +00:00
|
|
|
value: null,
|
2018-01-11 18:28:14 +00:00
|
|
|
};
|
2017-10-10 14:36:08 +00:00
|
|
|
} else if (type === 'boolean' || type === 'number' || type === 'string') {
|
2017-11-17 11:07:52 +00:00
|
|
|
return {
|
|
|
|
type,
|
|
|
|
value,
|
|
|
|
};
|
2017-10-10 14:36:08 +00:00
|
|
|
} else if (type === 'array') {
|
2017-11-17 11:07:52 +00:00
|
|
|
return {
|
|
|
|
type,
|
|
|
|
value: buildNativeArray(value),
|
|
|
|
};
|
2017-10-10 14:36:08 +00:00
|
|
|
} else if (type === 'object') {
|
|
|
|
if (value instanceof DocumentReference) {
|
2017-11-17 11:07:52 +00:00
|
|
|
return {
|
|
|
|
type: 'reference',
|
|
|
|
value: value.path,
|
|
|
|
};
|
2017-10-10 14:36:08 +00:00
|
|
|
} else if (value instanceof GeoPoint) {
|
2017-11-17 11:07:52 +00:00
|
|
|
return {
|
|
|
|
type: 'geopoint',
|
|
|
|
value: {
|
|
|
|
latitude: value.latitude,
|
|
|
|
longitude: value.longitude,
|
|
|
|
},
|
2017-10-10 14:36:08 +00:00
|
|
|
};
|
|
|
|
} else if (value instanceof Date) {
|
2017-11-17 11:07:52 +00:00
|
|
|
return {
|
|
|
|
type: 'date',
|
|
|
|
value: value.getTime(),
|
|
|
|
};
|
2018-05-03 19:13:51 +00:00
|
|
|
} else if (value instanceof Blob) {
|
|
|
|
return {
|
|
|
|
type: 'blob',
|
|
|
|
value: value.toBase64(),
|
|
|
|
};
|
2017-10-10 14:36:08 +00:00
|
|
|
}
|
2017-11-17 11:07:52 +00:00
|
|
|
return {
|
|
|
|
type: 'object',
|
|
|
|
value: buildNativeMap(value),
|
|
|
|
};
|
2017-10-10 14:36:08 +00:00
|
|
|
}
|
2017-11-17 11:07:52 +00:00
|
|
|
console.warn(`Unknown data type received ${type}`);
|
|
|
|
return null;
|
2017-10-10 14:36:08 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Functions that parse the received from the native
|
|
|
|
* side and converts to the correct Firestore JS types
|
|
|
|
*/
|
|
|
|
|
2018-01-25 18:25:39 +00:00
|
|
|
export const parseNativeMap = (
|
|
|
|
firestore: Firestore,
|
2018-02-14 13:00:19 +00:00
|
|
|
nativeData: { [string]: NativeTypeMap }
|
2018-01-25 18:25:39 +00:00
|
|
|
): Object | void => {
|
2017-10-10 14:36:08 +00:00
|
|
|
let data;
|
|
|
|
if (nativeData) {
|
|
|
|
data = {};
|
2018-01-25 18:25:39 +00:00
|
|
|
Object.keys(nativeData).forEach(key => {
|
2017-10-10 14:36:08 +00:00
|
|
|
data[key] = parseTypeMap(firestore, nativeData[key]);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
return data;
|
|
|
|
};
|
|
|
|
|
2018-01-25 18:25:39 +00:00
|
|
|
const parseNativeArray = (
|
|
|
|
firestore: Firestore,
|
2018-02-14 13:00:19 +00:00
|
|
|
nativeArray: NativeTypeMap[]
|
2018-01-25 18:25:39 +00:00
|
|
|
): any[] => {
|
2017-10-10 14:36:08 +00:00
|
|
|
const array = [];
|
|
|
|
if (nativeArray) {
|
2018-01-25 18:25:39 +00:00
|
|
|
nativeArray.forEach(typeMap => {
|
2017-10-10 14:36:08 +00:00
|
|
|
array.push(parseTypeMap(firestore, typeMap));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
return array;
|
|
|
|
};
|
|
|
|
|
2018-02-14 13:00:19 +00:00
|
|
|
const parseTypeMap = (firestore: Firestore, typeMap: NativeTypeMap): any => {
|
2017-10-10 14:36:08 +00:00
|
|
|
const { type, value } = typeMap;
|
2017-10-12 08:00:46 +00:00
|
|
|
if (type === 'null') {
|
|
|
|
return null;
|
|
|
|
} else if (type === 'boolean' || type === 'number' || type === 'string') {
|
2017-10-10 14:36:08 +00:00
|
|
|
return value;
|
|
|
|
} else if (type === 'array') {
|
|
|
|
return parseNativeArray(firestore, value);
|
|
|
|
} else if (type === 'object') {
|
|
|
|
return parseNativeMap(firestore, value);
|
|
|
|
} else if (type === 'reference') {
|
|
|
|
return new DocumentReference(firestore, Path.fromName(value));
|
|
|
|
} else if (type === 'geopoint') {
|
|
|
|
return new GeoPoint(value.latitude, value.longitude);
|
|
|
|
} else if (type === 'date') {
|
|
|
|
return new Date(value);
|
2018-05-03 19:13:51 +00:00
|
|
|
} else if (type === 'blob') {
|
|
|
|
return Blob.fromBase64String(value);
|
2017-10-10 14:36:08 +00:00
|
|
|
}
|
|
|
|
console.warn(`Unknown data type received ${type}`);
|
|
|
|
return value;
|
|
|
|
};
|