├── .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 |
10 |
11 |
12 |
13 |
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 |
--------------------------------------------------------------------------------