Как использовать Geofirex внутри облачных функций Google - PullRequest
0 голосов
/ 30 апреля 2019

У меня есть сценарий использования, когда мне нужно использовать библиотеку geofirex внутри облачных функций Google.Функция init библиотеки ожидает экземпляр FirebaseApp.Можно ли инициализировать его внутри облачных функций для запроса базы данных firestore с помощью firebase-admin?

Что я пытался ..

functions> src> index.ts

import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';
admin.initializeApp();
admin.firestore().settings({timestampsInSnapshots: true});


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

exports.geofenceUserNotifications = functions.https.onRequest((req, res) => {
  if(!req || !req.body || !req.body.length || !req.body[0].latitude || !req.body[0].longitude || !req.body[0].uid || !req.body[0].userFcmToken){
    // end function with 401 status
    res.status(401).send('Authentication required.');
  }

  const uid = req.body[0].uid;
  const userFcmToken = req.body[0].userFcmToken;
  const latitude = req.body[0].latitude;
  const longitude = req.body[0].longitude;
  const field = 'position';

  geoFire.collection('users').setPoint(uid, field, latitude, longitude).then(result => {
    res.end('User geoPoint updated!');
  }).catch( err => {
      console.log(err);
      res.end('error when update user geo point!');
  });

});

functions> package.json

{
  "name": "functions",
  "scripts": {
    "lint": "tslint --project tsconfig.json",
    "build": "tsc",
    "serve": "npm run build && firebase serve --only functions",
    "shell": "npm run build && firebase functions:shell",
    "start": "npm run shell",
    "deploy": "firebase deploy --only functions",
    "logs": "firebase functions:log"
  },
  "main": "lib/index.js",
  "dependencies": {
    "firebase-admin": "~6.0.0",
    "firebase-functions": "^2.1.0",
    "moment": "^2.23.0",
    "firebase": "^5.10.1",
    "geofirex": "0.0.6",
    "rxjs": "^6.3.3",
    "rxjs-compat": "^6.5.1"
  },
  "devDependencies": {
    "tslint": "~5.8.0",
    "typescript": "~2.8.3"
  },
  "private": true
}

Нет ошибки при развертывании, но при вызове функции geofenceUserNotifications я получаю эту ошибку:

TypeError: app.firestore is not a function
    at new GeoFireCollectionRef (/user_code/node_modules/geofirex/dist/index.cjs.js:1465:24)
    at GeoFireClient.collection (/user_code/node_modules/geofirex/dist/index.cjs.js:1639:16)
    at exports.geofenceUserNotifications.functions.https.onRequest (/user_code/lib/index.js:2197:13)
    at cloudFunction (/user_code/node_modules/firebase-functions/lib/providers/https.js:57:9)
    at /var/tmp/worker/worker.js:783:7
    at /var/tmp/worker/worker.js:766:11
    at _combinedTickCallback (internal/process/next_tick.js:73:7)
    at process._tickDomainCallback (internal/process/next_tick.js:128:9)

Заранее спасибо.

Ответы [ 2 ]

1 голос
/ 01 мая 2019

При второй проверке кажется, что Firebase Admin SDK для Node.js действительно имеет концепцию FirebaseApp . Возможно, вы захотите попробовать передать admin.app() в GeofireX для его инициализации.

В облачных функциях вы используете Firebase Admin SDK для Node.js , который не имеет понятия FirebaseApp.

При быстром сканировании похоже, что GeofireX был создан только для использования с клиентским JavaScript SDK от Firebase. Возможно, вы захотите подать запрос на добавление в репозиторий или, что еще лучше, PR. :)

0 голосов
/ 02 мая 2019

проблема решена следующим образом:

const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
admin.firestore().settings({timestampsInSnapshots: true});

// Init GeoFireX
const geofirex = require('geofirex');// <-- Use require Instead of import geofirex
import { get } from 'geofirex';
const geoFire = geofirex.init(admin); // <-- admin not admin.app()

Тогда

exports.geofenceUserNotifications = functions.https.onRequest(async (req, res) => {

  //setPoint (id, field, lat, lng)
  geoFire.collection('users').setPoint(uid, field, latitude, longitude).then(result => {
    res.end('User geo point is updated!');
  }).catch( err => {
      res.end('error when update user geo point');
      return;
  });
});

И geoFireX работает отлично.

но теперь я столкнулся с другой проблемой с запросом geoFireX.Я пытался получить предметы поблизости, но geoFireX возвращает Observable<object[]>, и это не работает в облачных функциях.

Я пытался использовать get () от geoFireX:

const query = geoFire.collection('places', queryRef).within(center, radius, field);
const nearbyPlaces = await get(query); // await query.pipe(operators.first()).toPromise();

но, к сожалению, это не работает.и я получаю следующую ошибку:

Ошибка: Аргумент "onNext" не является допустимой функцией.в Validator. (анонимная функция) .values ​​[as isFunction] (/srv/node_modules/@google-cloud/firestore/build/src/validate.js:99:27) в Query.onSnapshot (/ srv / node_modules / @ google-cloud / firestore / build / src / reference.js: 1524: 25) в Observable._subscribe (/srv/node_modules/geofirex/dist/index.cjs.js:1597:33) в Observable._trySubscribe (/ srv / node_modules)/rxjs/internal/Observable.js:44:25) в Observable.subscribe (/srv/node_modules/rxjs/internal/Observable.js:30:22) в MapOperator.call (/ srv / node_modules / rxjs / internal / operator/map.js:32:23) в Observable.subscribe (/srv/node_modules/rxjs/internal/Observable.js:25:31) в Object.subscribeToResult (/srv/node_modules/rxjs/internal/util/subscribeToResult.js): 12: 23) в CombineLatestSubscriber._complete (/srv/node_modules/rxjs/internal/observable/combineLatest.js:76:46) в CombineLatestSubscriber.Subscriber.complete (/srv/node_modules/rxjs/internal/Subscriber.js:78: 18)

...