UNPKG

10.5 kBJavaScriptView Raw
1import React, { Component } from 'react';
2import PropTypes from 'prop-types';
3import _inheritsLoose from '@babel/runtime/helpers/esm/inheritsLoose';
4import _extends from '@babel/runtime/helpers/esm/extends';
5import _objectWithoutPropertiesLoose from '@babel/runtime/helpers/esm/objectWithoutPropertiesLoose';
6import hoistStatics from 'hoist-non-react-statics';
7
8var FirestoreCache = function () {};
9
10var FirestoreContext = React.createContext(null);
11
12var FirestoreProvider =
13/*#__PURE__*/
14function (_Component) {
15 _inheritsLoose(FirestoreProvider, _Component);
16
17 function FirestoreProvider(props) {
18 var _this = _Component.call(this, props) || this;
19
20 var firebase = props.firebase,
21 useTimestampsInSnapshots = props.useTimestampsInSnapshots;
22 var firestore = firebase.firestore();
23
24 if (typeof useTimestampsInSnapshots !== 'undefined') {
25 firestore.settings({
26 timestampsInSnapshots: useTimestampsInSnapshots
27 });
28 }
29
30 _this.state = {
31 firestoreDatabase: firestore,
32 firestoreCache: new FirestoreCache()
33 };
34 return _this;
35 }
36
37 var _proto = FirestoreProvider.prototype;
38
39 _proto.render = function render() {
40 return React.createElement(FirestoreContext.Provider, {
41 value: this.state
42 }, this.props.children);
43 };
44
45 return FirestoreProvider;
46}(Component);
47
48FirestoreProvider.defaultProps = {};
49process.env.NODE_ENV !== "production" ? FirestoreProvider.propTypes = {
50 firebase: PropTypes.object.isRequired,
51 children: PropTypes.node.isRequired,
52 useTimestampsInSnapshots: PropTypes.bool
53} : void 0;
54
55var Firestore = function (_ref) {
56 var render = _ref.render;
57 return React.createElement(FirestoreContext.Consumer, null, function (_ref2) {
58 var firestoreDatabase = _ref2.firestoreDatabase;
59 return render({
60 firestore: firestoreDatabase
61 });
62 });
63};
64
65process.env.NODE_ENV !== "production" ? Firestore.propTypes = {
66 render: PropTypes.func.isRequired
67} : void 0;
68
69var withFirestore = function (Component) {
70 var C = function (_ref) {
71 var wrappedComponentRef = _ref.wrappedComponentRef,
72 remainingProps = _objectWithoutPropertiesLoose(_ref, ["wrappedComponentRef"]);
73
74 return React.createElement(FirestoreContext.Consumer, null, function (value) {
75 if (!value) {
76 throw new Error('FirestoreProvider is missing');
77 }
78
79 var firestoreDatabase = value.firestoreDatabase;
80 return React.createElement(Component, _extends({}, remainingProps, {
81 firestore: firestoreDatabase,
82 ref: wrappedComponentRef
83 }));
84 });
85 };
86
87 C.displayName = "withFirestore(" + (Component.displayName || Component.name) + ")";
88 C.WrappedComponent = Component;
89 process.env.NODE_ENV !== "production" ? C.propTypes = {
90 wrappedComponentRef: PropTypes.func
91 } : void 0;
92 return hoistStatics(C, Component);
93};
94
95/**
96 * Deep equality comparison for Arrays
97 * @param {Array} a The array to compare against
98 * @param {Array} b The array to compare with
99 * @returns {boolean} If the two arrays are equal
100 */
101function deepEqual(a, b) {
102 if (Array.isArray(a) && Array.isArray(b)) {
103 if (a.length !== b.length) {
104 return false;
105 }
106
107 for (var i = 0; i < a.length; i++) {
108 if (!deepEqual(a[i], b[i])) {
109 return false;
110 }
111 }
112
113 return true;
114 } else {
115 return a === b;
116 }
117}
118
119var FirestoreCollection =
120/*#__PURE__*/
121function (_Component) {
122 _inheritsLoose(FirestoreCollection, _Component);
123
124 function FirestoreCollection() {
125 var _this;
126
127 for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
128 args[_key] = arguments[_key];
129 }
130
131 _this = _Component.call.apply(_Component, [this].concat(args)) || this;
132 _this.state = {
133 isLoading: true,
134 data: [],
135 error: null,
136 snapshot: null
137 };
138
139 _this.setupFirestoreListener = function () {
140 var _this$props = _this.props,
141 firestore = _this$props.firestore,
142 path = _this$props.path,
143 queryProps = _objectWithoutPropertiesLoose(_this$props, ["firestore", "path"]);
144
145 var collectionRef = firestore.collection(path);
146
147 var query = _this.buildQuery(collectionRef, queryProps);
148
149 _this.unsubscribe = query.onSnapshot(_this.handleOnSnapshotSuccess, _this.handleOnSnapshotError);
150 };
151
152 _this.handleOnSnapshotSuccess = function (snapshot) {
153 if (snapshot) {
154 _this.setState({
155 isLoading: false,
156 data: snapshot.docs.map(function (doc) {
157 return _extends({
158 id: doc.id
159 }, doc.data());
160 }),
161 error: null,
162 snapshot: snapshot
163 });
164 }
165 };
166
167 _this.handleOnSnapshotError = function (error) {
168 _this.setState({
169 isLoading: false,
170 data: [],
171 error: error,
172 snapshot: null
173 });
174 };
175
176 _this.buildQuery = function (collectionRef, queryProps) {
177 var sort = queryProps.sort,
178 limit = queryProps.limit,
179 filter = queryProps.filter;
180 var query = collectionRef;
181
182 if (sort) {
183 sort.split(',').forEach(function (sortItem) {
184 var _sortItem$split = sortItem.split(':'),
185 field = _sortItem$split[0],
186 order = _sortItem$split[1];
187
188 query = query.orderBy(field, order);
189 });
190 }
191
192 if (limit) {
193 query = query.limit(limit);
194 }
195
196 if (filter) {
197 //if filter is array of array, build the compound query
198 if (Array.isArray(filter[0])) {
199 filter.forEach(function (clause) {
200 var _query;
201
202 query = (_query = query).where.apply(_query, clause);
203 });
204 } else {
205 var _query2;
206
207 //build the simple query
208 query = (_query2 = query).where.apply(_query2, filter);
209 }
210 }
211
212 return query;
213 };
214
215 return _this;
216 }
217
218 var _proto = FirestoreCollection.prototype;
219
220 _proto.componentDidMount = function componentDidMount() {
221 this.setupFirestoreListener();
222 };
223
224 _proto.componentWillUnmount = function componentWillUnmount() {
225 this.handleUnsubscribe();
226 };
227
228 _proto.componentWillReceiveProps = function componentWillReceiveProps(nextProps) {
229 var _this2 = this;
230
231 if (nextProps.path !== this.props.path || nextProps.sort !== this.props.sort || nextProps.limit !== this.props.limit || !deepEqual(nextProps.filter, this.props.filter)) {
232 this.handleUnsubscribe();
233 this.setState({
234 isLoading: true
235 }, function () {
236 return _this2.setupFirestoreListener();
237 });
238 }
239 };
240
241 _proto.handleUnsubscribe = function handleUnsubscribe() {
242 if (this.unsubscribe) {
243 this.unsubscribe();
244 }
245 };
246
247 _proto.render = function () {
248 var _this$props2 = this.props,
249 children = _this$props2.children,
250 render = _this$props2.render;
251 if (render) return render(this.state);
252 if (typeof children === 'function') return children(this.state);
253 return null;
254 };
255
256 return FirestoreCollection;
257}(Component);
258
259process.env.NODE_ENV !== "production" ? FirestoreCollection.propTypes = {
260 path: PropTypes.string.isRequired,
261 sort: PropTypes.string,
262 limit: PropTypes.number,
263 filter: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.object])), PropTypes.arrayOf(PropTypes.array)]),
264 children: PropTypes.func,
265 render: PropTypes.func,
266 firestore: PropTypes.object.isRequired
267} : void 0;
268var FirestoreCollection$1 = withFirestore(FirestoreCollection);
269
270var FirestoreDocument =
271/*#__PURE__*/
272function (_Component) {
273 _inheritsLoose(FirestoreDocument, _Component);
274
275 function FirestoreDocument() {
276 var _this;
277
278 for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
279 args[_key] = arguments[_key];
280 }
281
282 _this = _Component.call.apply(_Component, [this].concat(args)) || this;
283 _this.state = {
284 isLoading: true,
285 data: null,
286 error: null,
287 snapshot: null
288 };
289
290 _this.setupFirestoreListener = function () {
291 var _this$props = _this.props,
292 firestore = _this$props.firestore,
293 path = _this$props.path;
294 var documentRef = firestore.doc(path);
295 _this.unsubscribe = documentRef.onSnapshot(_this.handleOnSnapshotSuccess, _this.handleOnSnapshotError);
296 };
297
298 _this.handleOnSnapshotError = function (error) {
299 _this.setState({
300 isLoading: false,
301 error: error,
302 data: null,
303 snapshot: null
304 });
305 };
306
307 _this.handleOnSnapshotSuccess = function (snapshot) {
308 if (snapshot) {
309 var newState = {
310 isLoading: false,
311 error: null,
312 snapshot: snapshot
313 };
314
315 try {
316 var documentData = snapshot.data();
317 newState.data = _extends({
318 id: snapshot.id
319 }, documentData);
320 } catch (error) {
321 newState.error = error;
322 }
323
324 _this.setState(newState);
325 }
326 };
327
328 return _this;
329 }
330
331 var _proto = FirestoreDocument.prototype;
332
333 _proto.componentDidMount = function componentDidMount() {
334 this.setupFirestoreListener();
335 };
336
337 _proto.componentWillUnmount = function componentWillUnmount() {
338 this.handleUnsubscribe();
339 };
340
341 _proto.componentWillReceiveProps = function componentWillReceiveProps(nextProps) {
342 var _this2 = this;
343
344 if (nextProps.path !== this.props.path) {
345 this.handleUnsubscribe();
346 this.setState({
347 isLoading: true
348 }, function () {
349 return _this2.setupFirestoreListener();
350 });
351 }
352 };
353
354 _proto.handleUnsubscribe = function handleUnsubscribe() {
355 if (this.unsubscribe) {
356 this.unsubscribe();
357 }
358 };
359
360 _proto.render = function () {
361 var _this$props2 = this.props,
362 children = _this$props2.children,
363 render = _this$props2.render;
364 if (render) return render(this.state);
365 if (typeof children === 'function') return children(this.state);
366 return null;
367 };
368
369 return FirestoreDocument;
370}(Component);
371
372process.env.NODE_ENV !== "production" ? FirestoreDocument.propTypes = {
373 path: PropTypes.string.isRequired,
374 children: PropTypes.func,
375 render: PropTypes.func,
376 firestore: PropTypes.object.isRequired
377} : void 0;
378var FirestoreDocument$1 = withFirestore(FirestoreDocument);
379
380export { Firestore, FirestoreProvider, FirestoreCollection$1 as FirestoreCollection, FirestoreDocument$1 as FirestoreDocument, withFirestore };