New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

geofirex

Package Overview
Dependencies
Maintainers
1
Versions
7
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

geofirex

Realtime Firestore GeoQueries with RxJS

  • 0.0.6
  • Source
  • npm
  • Socket score

Version published
Weekly downloads
399
increased by88.21%
Maintainers
1
Weekly downloads
 
Created
Source

GeoFireX

Realtime Geolocation with Firestore & RxJS

:point_right: Live Demo :tv: Video Tutorial

:checkered_flag: QuickStart

npm install geofirex

# peer dependencies
npm install rxjs firebase

Initialize

The library is a lightweight client for the Firebase Web SDK that provides tools for wrangling geolocation data in Firestore. You need a Firebase project to get started.

// Init Firebase
import * as firebase from 'firebase/app';
firebase.initializeApp(yourConfig);

// Init GeoFireX
import * as geofirex from 'geofirex';
const geo = geofirex.init(firebase);

Write Geo Data

Next, add some geolocation data in your database. A collection creates a reference to Firestore (just like the SDK), but with some extra geolocation tools. The point method returns a class that helps you create geolocation data.

const cities = geo.collection('cities');

const point = geo.point(40, -119);

cities.add({ name: 'Phoenix', position: point.data });

Calling point.data returns an object that contains a geohash string and a Firestore GeoPoint. It should look like this in your database. You can name the object whatever you want and even save multiple points on a single document.

Query Geo Data

Now let's query Firestore for cities.position within 100km radius of a centerpoint.

const center = geo.point(40.1, -119.1);
const radius = 100;
const field = 'position';

const query = cities.within(center, radius, field);

The query returns a realtime Observable of the document data, plus some useful metadata like distance and bearing from the query centerpoint.

query.subscribe(console.log);
// [{ ...documentData, queryMetadata: { distance: 1.23232, bearing: 230.23 }  }]

You now have a realtime stream of data to visualize on a map.

:notebook: API

collection(path: string, query? QueryFn)

Creates reference to a Firestore collection that can be used to make geo-queries and perform writes If you pass an optional Firestore query function, all subsequent geo-queries will be limited to this subset of documents

Example:

const collection = geo.collection('cities');
Performing Geo-Queries

collection.within(center: GeoFirePoint, radius: number, field: string)

Query the parent Firestore collection by geographic distance. It will return documents that exist within X kilometers of the centerpoint.

Each doc also contains returns distance and bearing calculated on the query on the queryMetadata property.

Returns: Observable<object[]>

Write Data

Write data just like you would in Firestore

collection.add(data)

Or use one of the client's conveniece methods

  • collection.setDoc(id, data) - Set a document in the collection with an ID.
  • collection.setPoint(id, field, lat, lng)- Add a geohash to an existing doc
Read Data

In addition to Geo-Queries, you can also read the collection like you would normally in Firestore, but as an Observable

  • collection.data()- Observable of document data
  • collection.snapshot()- Observable of Firestore QuerySnapshot

point(latitude: number, longitude: number)

Returns a GeoFirePoint allowing you to create geohashes, format data, and calculate relative distance/bearing.

Example: const point = geo.point(38, -119)

Getters
  • point.hash Returns a geohash string at precision 9
  • point.geoPoint Returns a Firestore GeoPoint
  • point.geoJSON Returns data as a GeoJSON Feature<Point>
  • point.coords Returns coordinates as [latitude, longitude]
  • point.data Returns data object suitable for saving to the Firestore database
Geo Calculations
  • point.distance(latitude, longitude) Haversine distance to a point
  • point.bearing(latitude, longitude) Haversine bearing to a point

:pizza: Additional Features

The goal of this package is to facilitate rapid feature development with tools like MapBox, Google Maps, and D3.js. If you have an idea for a useful feature, open an issue.

toGeoJSON Operator

A custom RxJS operator that transforms a collection into a GeoJSON FeatureCollection. Very useful for tools like MapBox that can use GeoJSON to update a realtime data source.

const query = geo.collection('cars').within(...)

query.pipe( toGeoJSON() )

// Emits a single object typed as a FeatureCollection<Geometry>
{
  "type": "FeatureCollection",
  "features": [...]
}
Promises with get

Don't need a realtime stream? Convert any query observable to a promise by wrapping it with get.

import { get } from 'geofirex';

async function getCars {
    const query = geo.collection('cars').within(...)
    const cars = await get(query)
}

:zap: Tips

Scale to Massive Collections

It's possibe to build Firestore collections with billions of documents. One of the main motivations of this project was to make geoqueries possible on a queried subset of data. You can make a regular Firestore query on collection by passing a callback as the second argument, then all geoqueries will scoped these contstraints.

Note: This query requires a composite index, which you will be prompted to create with an error from Firestore on the first request.

Example:

const users = geo.collection('users', ref =>
  ref.where('status', '==', 'online')
);

const nearbyOnlineUsers = users.within(center, radius, field);

Usage with RxJS < 6.2, or Ionic v3

This package requires RxJS 6.2, but you can still use it with older versions without blowing up you app by installing rxjs-compat.

Example:

npm i rxjs@latest rxjs-compat

Seeing this error: DocumentReference.set() called with invalid data

Firestore writes cannot use custom classes, so make sure to call the data getter on the point.

const point = geo.point(40, -50);
// This is an ERROR
ref.add({ location: point });

// This is GOOD
ref.add({ location: point.data });

Make Dynamic Queries the RxJS Way

const radius = new BehaviorSubject(1);
const cities = geo.collection('cities');

const points = this.radius.pipe(
  switchMap(rad => {
    return cities.within(center, rad, 'point');
  })
);

// Now update your query
radius.next(23);

Always Order by [Latitude, Longitude]

The GeoJSON spec formats coords as [Longitude, Latitude] to represent an X/Y plane. However, the Firebase GeoPoint uses [Latitude, Longitude]. For consistency, this libary will always require you to use the latter format.

Keywords

FAQs

Package last updated on 13 Jul 2018

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc