├── .babelrc ├── .editorconfig ├── .eslintignore ├── .eslintrc ├── .gitignore ├── .prettierrc ├── LICENSE ├── README.md ├── index.js ├── package.json └── test └── test.js /.babelrc: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/invertase/firebase-firestore-fields/d92496594caab9de2ab27622a3857dc6980b5810/.eslintignore -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "extends": ["airbnb-base", "prettier"], 4 | "parser": "babel-eslint", 5 | "plugins": ["prettier"], 6 | "env": { 7 | "es6": true, 8 | "node": true, 9 | "shelljs": true, 10 | "jest": true 11 | }, 12 | "rules": { 13 | "no-extend-native": 0, 14 | "import/no-dynamic-require": 0, 15 | "global-require": "off", 16 | "class-methods-use-this": 0, 17 | "no-console": 1, 18 | "no-plusplus": 0, 19 | "no-undef": 0, 20 | "no-underscore-dangle": "off", 21 | "no-use-before-define": 0, 22 | "import/no-cycle": 1 23 | }, 24 | "overrides": [ 25 | { 26 | "files": ["test/**/*.js"], 27 | "env": { 28 | "jest": true 29 | } 30 | } 31 | ] 32 | } 33 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .nyc_output 3 | .idea 4 | .DS_Store 5 | yarn.lock 6 | package-lock.json 7 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "arrowParens": "avoid", 3 | "trailingComma": "all", 4 | "useTabs": false, 5 | "semi": true, 6 | "singleQuote": true, 7 | "bracketSpacing": true, 8 | "jsxBracketSameLine": false, 9 | "tabWidth": 2, 10 | "printWidth": 100, 11 | "overrides": [{ 12 | "files": [ 13 | "src/**/*.js", 14 | "test/**/*.js" 15 | ], 16 | "parser": "babylon", 17 | "options": { 18 | "trailingComma": "all" 19 | } 20 | }] 21 | } 22 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache-2.0 License 2 | ------------------ 3 | 4 | Copyright (c) 2016-present Invertase Limited & Contributors 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this library except in compliance with the License. 8 | 9 | You may obtain a copy of the Apache-2.0 License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | 19 | 20 | Creative Commons Attribution 3.0 License 21 | ---------------------------------------- 22 | 23 | Copyright (c) 2016-present Invertase Limited & Contributors 24 | 25 | Documentation and other instructional materials provided for this project 26 | (including on a separate documentation repository or it's documentation website) are 27 | licensed under the Creative Commons Attribution 3.0 License. Code samples/blocks 28 | contained therein are licensed under the Apache License, Version 2.0 (the "License"), as above. 29 | 30 | You may obtain a copy of the Creative Commons Attribution 3.0 License at 31 | 32 | https://creativecommons.org/licenses/by/3.0/ 33 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |
4 |
5 |

Firebase Firestore Fields

6 |

7 | 8 |

9 | NPM downloads 10 | NPM version 11 | License 12 | Chat 13 | Follow on Twitter 14 |

15 | 16 | 17 | Converts [Cloud Firestore REST field values](https://firebase.google.com/docs/firestore/reference/rest/v1beta1/Value) into a usable format. Handles nested objects and arrays. 18 | 19 | ## Usage 20 | 21 | ``` 22 | npm install --save firebase-firestore-fields 23 | ``` 24 | 25 | ```js 26 | const convert = require('firebase-firestore-fields'); 27 | 28 | // typical response from a Cloud Firestore REST endpoint 29 | const response = { 30 | name: 'projects/testproject/databases/(default)/documents/config/2L3sczWg8vZhIZDVgLh5', 31 | fields: { 32 | title: { 33 | stringValue: 'Super cool app!', 34 | }, 35 | theme: { 36 | mapValue: { 37 | fields: { 38 | backgroundColor: { 39 | stringValue: '#000000', 40 | }, 41 | }, 42 | }, 43 | }, 44 | appEnabled: { 45 | booleanValue: true, 46 | }, 47 | }, 48 | createTime: '2017-11-24T10:00:12.419673Z', 49 | updateTime: '2017-11-24T10:58:15.600296Z', 50 | }; 51 | 52 | // convert the response fields into a usable format 53 | const converted = convert(response.fields); 54 | 55 | console.dir(converted); 56 | // OUTPUT: 57 | // { 58 | // title: "Super cool app!", 59 | // theme: { 60 | // backgroundColor: "#000000" 61 | // }, 62 | // appEnabled: true, 63 | // } 64 | ``` 65 | 66 | ### Differences 67 | 68 | #### integerValue 69 | 70 | Returns a type `Number` (Cloud Firestore returns it as a `string`). 71 | 72 | #### geoPointValue 73 | 74 | Returns the latitude & longitude points as an array pair: `[latitude, longitude]`. 75 | 76 | ## License 77 | 78 | - See [LICENSE](/LICENSE) 79 | 80 | --- 81 | 82 | Built and maintained with 💛 by [Invertase](https://invertase.io). 83 | 84 | - [💼 Hire Us](https://invertase.io/hire-us) 85 | - [☕️ Sponsor Us](https://opencollective.com/react-native-firebase) 86 | - [👩‍💻 Work With Us](https://invertase.io/jobs) 87 | 88 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | function parseValue(value) { 2 | const type = Object.keys(value)[0]; 3 | 4 | switch (type) { 5 | case 'geoPointValue': 6 | return [value.geoPointValue.latitude, value.geoPointValue.longitude]; 7 | case 'arrayValue': 8 | return typeof value.arrayValue.values !== 'undefined' 9 | ? value.arrayValue.values.map(parseValue) 10 | : []; 11 | case 'mapValue': 12 | return parseFields(value.mapValue.fields); 13 | case 'integerValue': 14 | case 'doubleValue': 15 | return Number(value[type]); 16 | default: 17 | return value[type]; 18 | } 19 | } 20 | 21 | function parseFields(fields) { 22 | const res = {}; 23 | const keys = Object.keys(fields); 24 | for (let i = 0, len = keys.length; i < len; i++) { 25 | const key = keys[i]; 26 | res[key] = parseValue(fields[key]); 27 | } 28 | return res; 29 | } 30 | 31 | module.exports = parseFields; 32 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "firebase-firestore-fields", 3 | "version": "1.0.2", 4 | "description": "Convert Firebase Cloud Firestore API fields into a usable JavaScript format.", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "nyc mocha" 8 | }, 9 | "files": [ 10 | "index.js" 11 | ], 12 | "author": "Invertase (http://invertase.io)", 13 | "license": "APACHE-2.0", 14 | "devDependencies": { 15 | "babel-eslint": "^10.0.1", 16 | "eslint": "^5.12.1", 17 | "eslint-config-airbnb-base": "^13.1.0", 18 | "eslint-config-prettier": "^3.6.0", 19 | "eslint-plugin-import": "^2.15.0", 20 | "eslint-plugin-prettier": "^3.0.1", 21 | "prettier": "^1.16.1", 22 | "mocha": "^5.2.0", 23 | "nyc": "^13.1.0" 24 | }, 25 | "repository": { 26 | "type": "git", 27 | "url": "https://github.com/invertase/firebase-firestore-fields.git" 28 | }, 29 | "keywords": [ 30 | "javascript", 31 | "firebase", 32 | "cloud firestore", 33 | "api", 34 | "web api", 35 | "firestore", 36 | "firebase firestore", 37 | "firestore field converter", 38 | "nullValue", 39 | "booleanValue", 40 | "integerValue", 41 | "doubleValue", 42 | "timestampValue", 43 | "stringValue", 44 | "bytesValue", 45 | "referenceValue", 46 | "geoPointValue", 47 | "arrayValue", 48 | "mapValue" 49 | ] 50 | } 51 | -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const pkg = require('../index'); 3 | 4 | describe('firebase-firestore-fields', function() { 5 | describe('timestampValue', function() { 6 | it('should return a string value', function() { 7 | const fields = { foo: { timestampValue: '2017-11-22T00:00:00Z' } }; 8 | const res = pkg(fields); 9 | assert.deepEqual(res, { 10 | foo: '2017-11-22T00:00:00Z', 11 | }); 12 | }); 13 | }); 14 | 15 | describe('booleanValue', function() { 16 | it('should return a boolean value', function() { 17 | const fields = { foo: { booleanValue: false } }; 18 | const res = pkg(fields); 19 | assert.deepEqual(res, { 20 | foo: false, 21 | }); 22 | }); 23 | }); 24 | 25 | describe('geoPointValue', function() { 26 | it('should return a array value', function() { 27 | const fields = { 28 | foo: { 29 | geoPointValue: { 30 | latitude: 1, 31 | longitude: -1.2, 32 | }, 33 | }, 34 | }; 35 | const res = pkg(fields); 36 | assert.deepEqual(res, { 37 | foo: [1, -1.2], 38 | }); 39 | }); 40 | }); 41 | 42 | describe('stringValue', function() { 43 | it('should return a string value', function() { 44 | const fields = { foo: { stringValue: 'bar' } }; 45 | const res = pkg(fields); 46 | assert.deepEqual(res, { 47 | foo: 'bar', 48 | }); 49 | }); 50 | }); 51 | 52 | describe('referenceValue', function() { 53 | it('should return a string value', function() { 54 | const ref = 'projects/foobar/databases/(default)/documents'; 55 | const fields = { foo: { referenceValue: ref } }; 56 | const res = pkg(fields); 57 | assert.deepEqual(res, { 58 | foo: ref, 59 | }); 60 | }); 61 | }); 62 | 63 | describe('arrayValue', function() { 64 | it('should return a array of correct values', function() { 65 | const fields = { 66 | foo: { 67 | arrayValue: { 68 | values: [ 69 | { 70 | stringValue: '234', 71 | }, 72 | { 73 | geoPointValue: { 74 | latitude: 1.111, 75 | longitude: 1.112, 76 | }, 77 | }, 78 | ], 79 | }, 80 | }, 81 | }; 82 | const res = pkg(fields); 83 | assert.deepEqual(res, { 84 | foo: ['234', [1.111, 1.112]], 85 | }); 86 | }); 87 | 88 | it('should return an empty array when array values[] is undefined', function() { 89 | const fields = { 90 | foo: { 91 | arrayValue: {}, 92 | }, 93 | }; 94 | const res = pkg(fields); 95 | assert.deepEqual(res, { 96 | foo: [], 97 | }); 98 | }); 99 | }); 100 | 101 | describe('nullValue', function() { 102 | it('should return a null value', function() { 103 | const fields = { foo: { nullValue: null } }; 104 | const res = pkg(fields); 105 | assert.deepEqual(res, { 106 | foo: null, 107 | }); 108 | }); 109 | }); 110 | 111 | describe('integerValue', function() { 112 | it('should return a number value', function() { 113 | const fields = { foo: { integerValue: '123' } }; 114 | const res = pkg(fields); 115 | assert.deepEqual(res, { 116 | foo: 123, 117 | }); 118 | }); 119 | }); 120 | 121 | describe('doubleValue', function() { 122 | it('should return a number value', function() { 123 | const fields = { foo: { doubleValue: 13.37 } }; 124 | const res = pkg(fields); 125 | assert.deepEqual(res, { 126 | foo: 13.37, 127 | }); 128 | }); 129 | }); 130 | 131 | describe('mapValue', function() { 132 | it('should return a object value', function() { 133 | const fields = { 134 | foo: { 135 | mapValue: { 136 | fields: { 137 | string: { 138 | stringValue: 'foobar', 139 | }, 140 | nested: { 141 | mapValue: { 142 | fields: { 143 | number: { 144 | integerValue: '234', 145 | }, 146 | }, 147 | }, 148 | }, 149 | }, 150 | }, 151 | }, 152 | }; 153 | const res = pkg(fields); 154 | assert.deepEqual(res, { 155 | foo: { 156 | string: 'foobar', 157 | nested: { 158 | number: 234, 159 | }, 160 | }, 161 | }); 162 | }); 163 | }); 164 | }); 165 | --------------------------------------------------------------------------------