I have a very basic app that takes a UK Postcode as a URL parameter and returns the longitude and latitude via the Mapbox API.
It seems I am receiving 2 responses: The first response is returned successfully and displayed on screen, then the second response is caught by my catch block with the following error Error: TypeError: Cannot read property 'geometry' of undefined I understand the error but don't understand that why the app executes successfully (returns lng and lat to user) then shows an error?
./server.js
require('dotenv').config()
const express = require('express');
const server = express();
const MapApi = require('./datasources/map')
const Map = new MapApi;
server.get('/:postcode', async (req,res) => {
const { postcode } = req.params
const [lng, lat] = await Map.getLngLat( postcode )
res.send(`Longitude: ${lng}, Latitude: ${lat}`)
})
const { PORT_NUMBER } = process.env
server.listen(PORT_NUMBER, () => console.log('Listening on port ', PORT_NUMBER))
./datasources/map.js
require('dotenv').config()
const axios = require('axios');
class MapApi {
constructor(){
this.baseURL = (search_term) => {
return `https://api.mapbox.com/geocoding/v5/mapbox.places/${search_term}.json?access_token=${process.env.MAPBOX_ACCESS_TOKEN}`
}
}
// Get Lng, Lat from Postocde
async getLngLat (search_term) {
return axios.get( this.baseURL(search_term) )
.then(response => {
return typeof response.data === "object"
? response.data.features[0].geometry.coordinates
: [0,0]
})
.catch(err => {
console.error('Error: ', err)
})
}
}
module.exports = MapApi
If i include the following line console.log(`Time ${Date.now()} - Type ${typeof response}`) in the then block of the axios request
I get the following console output >
Time 1575388974209 - Type object
Time 1575388975073 - Type object
Error: TypeError: Cannot read property 'geometry' of undefined
Related
I'm trying to retrieve value from firebase database which is RTDB
it doesnt send any error or output any error as i know of so im really confused as to why.
it worked fine a minute ago.
below is my code to retrieve value from table and send through telegram
import * as functions from "firebase-functions";
import * as express from "express";
import * as cors from "cors";
import * as admin from "firebase-admin";
admin.initializeApp();
const bot = express();
bot.use(cors({origin: true}));
bot.post("/", async function(req, res) {
if (
req.body &&
req.body.message &&
req.body.message.chat &&
req.body.message.chat.id &&
req.body.message.from &&
req.body.message.from.first_name
) {
const chatId = req.body.message.chat.id;
const firstName = req.body.message.from.first_name;
const receivedMessage = req.body.message.text;
// Check if the received message is the "/start" command
if (receivedMessage === "/start") {
// Define your RTDB Reference to point to the "Sensor MQ7" parent node
const rtdbReference = admin.database().ref("Sensor MQ7");
// Read the latest unknown child node of "Sensor MQ7"
const wildcardNodeSnapshot = await rtdbReference
.limitToLast(1)
.once("child_added");
// Read the known child nodes of the unknown child node
const coConcentrationSnapshot = wildcardNodeSnapshot.child("MQ7");
const latSnapshot = wildcardNodeSnapshot.child("latitude");
const longSnapshot = wildcardNodeSnapshot.child("longitude");
const timeSnapshot = wildcardNodeSnapshot.child("time");
// Get the values of the known child nodes
const coConcentration = coConcentrationSnapshot.val();
const time = timeSnapshot.val();
const latitude = latSnapshot.val();
const longtitude = longSnapshot.val();
// Check if the known child node value is above 100
if (coConcentration > 100) {
// Return the response with a button interface
return res.status(200).send({
method: "sendMessage",
chatId,
text: `${firstName} is in danger! Carbon Monoxide Concentration is too high: ${coConcentration}. Last known location is at (${latitude},${longtitude}) approximately ${time} o clock.`,
reply_markup: {
inline_keyboard: [
[
{
text: `Call ${firstName}`,
callback_data: "call_user",
},
],
],
},
});
}
}
} else {
// Return an error message if the request body is missing the required information
return res.status(400).send({
status: "An error occurred. The request body is missing the required information.",
});
}
// Return an empty response
return res.status(200).send({});
});
export const router = functions.https.onRequest(bot);
expected output should be like this: output
its strange because when i do /start it doesnt even send a blank reply
i was supposed to output the database value
When i checking my "img" entry on firebase with google cloud function and the request module i get an error but only when i deployed it on local emulator it works.
Error i get on my cloud logs:
removeExpiredDocuments
Exception from a finished function: TypeError: Cannot read properties of undefined (reading 'statusCode')
Example URL for 404:
https://ch.cat-ret.assets.lidl/catalog5media/ch/article/5104560/third/lg/5104560_01.jpg
const functions = require("firebase-functions");
const admin = require("firebase-admin");
const requesth = require('request');
admin.initializeApp();
exports.removeExpiredDocuments = functions.region('europe-west1').runWith({ memory: "256MB" }).pubsub.schedule("every 1 hours").onRun(async (context) => {
const db = admin.firestore();
const snaps = await db.collection("products").get();
let promises = [];
snaps.forEach((snap) => {
requesth(snap.data().img, function (error, response) {
functions.logger.info('[img] error: ' + error, { structuredData: true });
if ((response) && (response.statusCode) == 404) {
promises.push(snap.ref.delete());
functions.logger.info('[img] not found ' + snap.data().name, { structuredData: true });
}
});
});
return Promise.all(promises);
});
I wanna use google cloud function for checking if the "img" entry is statusCode 404 and if its statusCode 404 delete the document.
#edit new random error without changed anything
#2 Image of random change errors
I am trying to write a cloud function to export only the new documents getting added to my 'reviews' sub-collection. The trigger for this cloud function is: Cloud Firestore. However, my cloud function deployment fails through the console. Could someone please help me understand what's wrong with my cloud function?
Error message:
Deployment failure:
Build failed: /workspace/index.js:26
}
^
SyntaxError: missing ) after argument list
at new Script (vm.js:83:7)
at checkScriptSyntax (internal/bootstrap/node.js:620:5)
at startup (internal/bootstrap/node.js:280:11)
at bootstrapNodeJSCore (internal/bootstrap/node.js:623:3); Error ID: d984e68f
Cloud function code:
const firestore = require('#google-cloud/firestore');
const client = new firestore.v1.FirestoreAdminClient();
const bucket = 'gs://bucket_name'
exports.scheduledFirestoreBackup = (event, context) => {
const databaseName = client.databasePath(
// process.env.GCLOUD_PROJECT,
"fs124",
'(default)'
);
return client
.exportDocuments({
name: databaseName,
outputUriPrefix: bucket,
collectionIds: ['reviews'],
})
.onSnapshot()
.then(snap => {
snap.forEach(doc => {
const response = doc.data();
console.log(doc.data());
return response;
}
});
Console snippet:
The message you are getting, SyntaxError: missing ) after argument list is pretty clear. You are missing the closing curly bracket} and parenthesis) of then(). It should look something like this:
const firestore = require('#google-cloud/firestore');
const client = new firestore.v1.FirestoreAdminClient();
const bucket = 'gs://bucket_name'
exports.scheduledFirestoreBackup = (event, context) => {
const databaseName = client.databasePath(
// process.env.GCLOUD_PROJECT,
"fs124",
'(default)'
);
return client
.exportDocuments({
name: databaseName,
outputUriPrefix: bucket,
collectionIds: ['reviews'],
})
.onSnapshot()
.then(snap => {
snap.forEach(doc => {
const response = doc.data();
console.log(doc.data());
return response;
});
});
};
I am using the source code from a security rules tutorial to attempt to do integration testing with Jest for my Javascript async function async_create_post, used for my firebase HTTP function create_post The files involved has a directory structure of the following:
Testing file: root/tests/handlers/posts.test.js
File to be tested: root/functions/handlers/posts.js
Helper code from the tutorial: root/tests/rules/helpers.js
And here is the source code that is involved:
posts.test.js
const { setup, teardown} = require("../rules/helpers");
const {
async_get_all_undeleted_posts,
async_get_post,
async_delete_post,
async_create_post
} = require("../../functions/handlers/posts");
describe("Post Creation", () => {
afterEach(async () => {
await teardown();
});
test("should create a post", async () => {
const db = await setup();
const malloryUID = "non-existent uid";
const firstPost = {
body: "First post from Mallory",
author_id: malloryUID,
images: ["url1", "url2"]
}
const before_post_snapshot = await db.collection("posts").get();
expect(before_post_snapshot.docs.length).toBe(0);
await async_create_post(firstPost); //fails at this point, expected to create a new post, but instead threw an error
const after_post_snapshot = await db.collection("posts").get();
expect(after_post_snapshot.docs.length).toBe(1);
});
});
posts.js
const {admin, db } = require('../util/admin');
//admin.initializeApp(config); //my credentials
//const db = admin.firestore();
const { uuid } = require("uuidv4");
const {
success_response,
error_response
} = require("../util/validators");
exports.async_create_post = async (data, context) => {
try {
const images = [];
data.images.forEach((url) => {
images.push({
uid: uuid(),
url: url
});
})
const postRecord = {
body: data.body,
images: images,
last_updated: admin.firestore.FieldValue.serverTimestamp(),
like_count: 0,
comment_count: 0,
deleted: false,
author_id: data.author_id
};
const generatedToken = uuid();
await db
.collection("posts")
.doc(generatedToken)
.set(postRecord);
// return success_response();
return success_response(generatedToken);
} catch (error) {
console.log("Error in creation of post", error);
return error_response(error);
}
}
When I run the test in Webstorm IDE, with 1 terminal running Firebase emulators:start , I get the following error message.
console.log
Error in creation of post TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received an instance of Object
at validateString (internal/validators.js:120:11)
at Object.basename (path.js:1156:5)
at GrpcClient.loadProto (/Users/isaac/Desktop/project/functions/node_modules/google-gax/src/grpc.ts:166:23)
at new FirestoreClient (/Users/isaac/Desktop/project/functions/node_modules/#google-cloud/firestore/build/src/v1/firestore_client.js:118:38)
at ClientPool.clientFactory (/Users/isaac/Desktop/project/functions/node_modules/#google-cloud/firestore/build/src/index.js:330:26)
at ClientPool.acquire (/Users/isaac/Desktop/project/functions/node_modules/#google-cloud/firestore/build/src/pool.js:87:35)
at ClientPool.run (/Users/isaac/Desktop/project/functions/node_modules/#google-cloud/firestore/build/src/pool.js:164:29)
at Firestore.request (/Users/isaac/Desktop/project/functions/node_modules/#google-cloud/firestore/build/src/index.js:961:33)
at WriteBatch.commit_ (/Users/isaac/Desktop/project/functions/node_modules/#google-cloud/firestore/build/src/write-batch.js:485:48)
at exports.async_create_post (/Users/isaac/Desktop/project/functions/handlers/posts.js:36:5) {
code: 'ERR_INVALID_ARG_TYPE'
}
at exports.async_create_post (/Users/isaac/Desktop/project/functions/handlers/posts.js:44:13)
Error: expect(received).toBe(expected) // Object.is equality
Expected: 1
Received: 0
<Click to see difference>
at Object.<anonymous> (/Users/isaac/Desktop/project/tests/handlers/posts.test.js:59:45)
Error in creation of post comes from the console.log("Error in creation of post", error); in posts.js, so the error is shown in the title of this post.
I want to know why calling the async_create_post from posts.test.js will cause this error and does not populate my database with an additional record as expected behaviour. Do inform me if more information is required to solve the problem.
Here are some code snippets that may give more context.
helpers.js [Copied from the repository]
const firebase = require("#firebase/testing");
const fs = require("fs");
module.exports.setup = async (auth, data) => {
const projectId = `rules-spec-${Date.now()}`;
const app = firebase.initializeTestApp({
projectId,
auth
});
const db = app.firestore();
// Apply the test rules so we can write documents
await firebase.loadFirestoreRules({
projectId,
rules: fs.readFileSync("firestore-test.rules", "utf8")
});
// write mock documents if any
if (data) {
for (const key in data) {
const ref = db.doc(key); // This means the key should point directly to a document
await ref.set(data[key]);
}
}
// Apply the actual rules for the project
await firebase.loadFirestoreRules({
projectId,
rules: fs.readFileSync("firestore.rules", "utf8")
});
return db;
// return firebase;
};
module.exports.teardown = async () => {
// Delete all apps currently running in the firebase simulated environment
Promise.all(firebase.apps().map(app => app.delete()));
};
// Add extensions onto the expect method
expect.extend({
async toAllow(testPromise) {
let pass = false;
try {
await firebase.assertSucceeds(testPromise);
pass = true;
} catch (error) {
// log error to see which rules caused the test to fail
console.log(error);
}
return {
pass,
message: () =>
"Expected Firebase operation to be allowed, but it was denied"
};
}
});
expect.extend({
async toDeny(testPromise) {
let pass = false;
try {
await firebase.assertFails(testPromise);
pass = true;
} catch (error) {
// log error to see which rules caused the test to fail
console.log(error);
}
return {
pass,
message: () =>
"Expected Firebase operation to be denied, but it was allowed"
};
}
});
index.js
const functions = require('firebase-functions');
const {
async_get_all_undeleted_posts,
async_get_post,
async_delete_post,
async_create_post
} = require('./handlers/posts');
exports.create_post = functions.https.onCall(async_create_post);
The error message means that a method of the path module (like path.join) expects one of its arguments to be a string but got something else.
I found the offending line by binary search commenting the program until the error was gone.
Maybe one of your modules uses path and you supply the wrong arguments.
When trying to use axis to query an external Weather API, I get this error
ReferenceError: axios is not defined
at getTropicalCyclones (vm.js:16:9)
Here is my action for getTropicalCyclones {}
(of course I have to hide my client ID and secret)
const getTropicalCyclones = async () => {
const BASE_WEATHER_API = `https://api.aerisapi.com/tropicalcyclones/`
const CLIENT_ID_SECRET = `SECRET`
const BASIN = `currentbasin=wp`
const PLACE = `p=25,115,5,135` // rough coords for PH area of responsibility
const ACTION = `within` // within, closest, search, affects or ''
try {
let text = ''
let response = {}
await axios.get(
`${BASE_WEATHER_API}${ACTION}?${CLIENT_ID_SECRET}&${BASIN}&${PLACE}`
)
.then((resp) => {]
response = resp
text = 'Success retrieving weather!'
})
.catch((error) => {
console.log('!! error', error)
})
const payload = await bp.cms.renderElement(
'builtin_text',
{
text,
},
event.channel
)
await bp.events.replyToEvent(event, payload)
} catch (e) {
// Failed to fetch, this is where ReferenceError: axios is not defined comes from
console.log('!! Error while trying to fetch weather info', e)
const payload = await bp.cms.renderElement(
'builtin_text',
{
text: 'Error while trying to fetch weather info.',
},
event.channel
)
await bp.events.replyToEvent(event, payload)
}
}
return getTropicalCyclones()
So my question is, how do I import axios? I've tried
const axios = require('axios')
or
import axios from 'axios';
but this causes a different error:
Error processing "getTropicalCyclones {}"
Err: An error occurred while executing the action "getTropicalCyclones"
Looking at the package.json on GitHub, it looks like axios is already installed
https://github.com/botpress/botpress/blob/master/package.json
However, I cannot locate this package.json on my bot directory...
Secondly, based on an old version doc it looks like this example code just used axios straight
https://botpress.io/docs/10.31/recipes/apis/
How do I use axios on Botpress?
Any leads would be appreciated
Botpress: v11.0.0
Simply use ES6 import.
include this line at the top of your code.
import axios from 'axios';
Note: I'm expecting that the axios is already installed