Reduxtoolkit Query :: access all request - firebase

I have a react-native project that uses RTK Query.
I want to integrate Firebase/perf library.
s there a way to hook into all fetch request at one place. So I can mesure each fetch?
Firebase/perf integration in a function ::
// Define the network metric
const metric = await perf().newHttpMetric(url, 'GET');
// Define meta details
metric.putAttribute('user', 'abcd');
// Start the metric
await metric.start();
// Perform a HTTP request and provide response information
const response = await fetch(url);
metric.setHttpResponseCode(response.status);
metric.setResponseContentType(response.headers.get('Content-Type'));
metric.setResponsePayloadSize(response.headers.get('Content-Length'));
// Stop the metric
await metric.stop();
I would like to replace the fetch in this snippet with the RTK Query main fetch function.
Anyone ever done this integration ?
Thanks for your help.

Related

How to make Next-Auth-session-token-dependent server queries with React Query in Next JS?

I am trying to make an API GET request, using React Query's useInfiniteQuery hook, that uses data from a Next Auth session token in the query string.
I have a callback in /api/auth/[...nextauth.ts] to send extra userData to my session token.
There are two relevant pages on the client side. Let's call them /pages/index.tsx and /hooks/useApiData.ts. This is what they look like, for all intents and purposes:
// pages/index.tsx
export default function Page() {
const {data, fetchNextPage, isLoading, isError} = useCourseData()
if (isLoading) return <main />
return <main>
<InfiniteScroller fetchMore={fetchNextPage}>
{data?.pages?.map(page => page?.results?.map(item: string => item))}
</InfiniteScroller>
</main>
}
// hooks/useApiData.ts
async function fetchPage(pageParam: string) {
const response = await fetch(pageParam)
return await response.json()
}
export default function useApiData() {
const {data: session} = useSession()
const init = `/api?userData=${session?.user?.userData}`
return useInfiniteQuery('query',
({pageParam = init}) => fetchPage(pageParam),
{getNextPageParam: prevPage => prevPage.next ?? undefined}
)
}
My initial request gets sent to the API as /api?userData=undefined. The extra data is definitely making its way into the token.
I can place the data from my session in the DOM via the render function of /pages/index.tsx, so I figure the problem is something to do with custom hooks running before the session context is ready, or something like that... I don't understand the mechanics of hooks well enough to figure that out.
I've been looking for answers for a long time, and I'm surprised not to have found a single person with the same issue. These are not unpopular packages and I guess a lot of people are using them in conjunction to achieve what I'm attempting here, so I figure I must be doing something especially dumb. But what?!
How can I get the data from my Next Auth session into my React Query request? And for bonus points, why is the session data not available when the request is sent in my custom hook?

Strapi: How to include/populate relations with fetch call?

I'm trying to make a "related articles" for a "blog-article" single based off the relation "blog-categories", but I can't seem to get the relations to appear in the api call.
What's the API url with the correct parameters to get relations with Strapi?
To populate all of the articles in descending order by date with images, I'm doing:
const res =
await fetch (
https://localhost:3000/api/blog-articles?populate=*&sort[0]=publishDate%3Adesc
)
Collection's Content Fields
Edit: Fetch result
Edit 2: Schema
I think you can achieve this by passing the related field name in the populate http query string.
HTTP Request URL
GET http://localhost:3000/api/blog-articles?populate=blog_categories&sort[0]=publishedAt%3Adesc
JS Implementation
const resp = await fetch('http://localhost:3000/api/blog-articles?populate=blog_categories&sort[0]=publishedAt%3Adesc');
const data = await resp.json();
console.log(data);

How to check if client's contacts are using my app?

I'm currently developing an app using Firebase.
My Firestore Database looks like below:
Once the user passes the Firebase authentication procedure, I'm creating a user document with a field "Phone:" which contains his phone number. Basically, everyone who is gonna using the app will be listed in the database.
And here is my challenge:
I'm using the plugin easy_contact_picker to store all the contacts of the users device to a List.
How can I find out whether the users contacts are using the app or whether they are listed in the database?
My goal is create a contact List Widget which shows me all my contacts. But those contacts which are using the app or which are listed in the database, should be highlighted or marked particularly.
Which is the best way to realize that if we consider that millions of users (to minimize computing power)are listed in the database?
Anyone has an idea?
Thanks a lot
First of all try to awoid giving everyone access to read all users. That is something most ppl do when handling such a problem. The do it because the query over all users won't work if you don't give the rights to read all of them.
Because of security reasons I would move the logic for checking if a user exists into callable function (not a http function!). That way you can call it inside of your app and check for a single user or multiple of them in an array. That would depend how your frontend would handle it.
Very importand would be to store all phone numbers in the absolute same format. That way you could query for them. Regardless of the number of users you could always find a specific one like here:
var citiesRef = db.collection("users");
var query = citiesRef.where("Phone", "==", "+4912345679");
The numbers need to be absolutely the same without any emtpy spaces - chars and the +49 or 0049 also needs to be the same.
You could create two callable funcitons. One to check if a single user exists in your app and another where you send an array of phone numbers and you get an array back. The cloud function can use Promise.all to performe such queries in parallel so you get your responce quite fast.
I'm using a similar approach to add users in my app as admins to specific groups where you just enter the email of the user and if he is in the app he will be added. I not he get's an invitation on the email to join the App.
With the help of Tarik's answer, Ayrix and I came up with the following solution.
Important: Read Tarik's answer for more information.
Client: callable_compare_contacts.dart
import 'package:cloud_functions/cloud_functions.dart';
Future<List<Object>> getMembersByPhoneNumber(List<String> allPhoneNumbers) async {
HttpsCallable callable = FirebaseFunctions.instance.httpsCallable('membersByPhoneNumber');
final results = await callable.call(<String, dynamic>{'allPhoneNumbers': allPhoneNumbers});
return results.data;
}
Server: index.js
const functions = require("firebase-functions");
const admin = require("firebase-admin");
if (admin.apps.length === 0) {
admin.initializeApp({
credential: admin.credential.applicationDefault(),
});
}
exports.membersByPhoneNumber = functions.https.onCall((data, context) => {
return new Promise((resolve, reject) => {
if (!data || !data.allPhoneNumbers.length) return resolve([]);
const phoneNumbers = data.allPhoneNumbers;
// TODO: different scope? move vars for future use
const db = admin.firestore();
const collectionRef = db.collection("User");
let batches = [];
// because of wrong eslint parsing (dirty)
batches = [];
while (phoneNumbers.length) {
// firestore limits batches to 10
const batch = phoneNumbers.splice(0, 10);
// add the batch request to to a queue
batches.push(
new Promise((response) => {
collectionRef.where("Phone", "in", [...batch]).get()
.then((results) =>
response(results.docs.map(function(result) {
return result.data().Phone;
} )));
})
);
}
// response / return to client
Promise.all(batches).then(function(content) {
// console.log("content.flat()");
// console.log(content.flat());
return resolve(content.flat());
});
});
});
Note: This is our first callable/cloud function .. so Suggestions for changes are welcome.

Dynamic callback endpoints with cloud functions

When a user triggers a function there’s a POST request going away to a partner. Within the body I need to include a unique endpoint callbackURL with an Id so they can send me status updates linked with a specific user. How can I accomplish that? I know how to setup static endpoints, but not create new ones for every request.
As Doug said in his comment above, you don't need a new URL (i.e. a new endpoint) for each different id. You can deploy only one HTTP Cloud Function (which exposes one endpoint) and, in the Cloud Function, you extract the value of id from the Request object with its originalUrl property, as follows:
exports.myWebhook = functions.https.onRequest((req, res) => {
const urlArray = req.originalUrl.split('/');
console.log(urlArray);
console.log(urlArray[1]);
const id = urlArray[1];
//Do whatever you need with id
//.....
//If you want to test that it works with a browser, you can send it back as a response to the browser
res.send(urlArray[1]);
});
You then call this Cloud Function with the following URI:
https://us-central1-yourprojectname.cloudfunctions.net/myWebhook/id/callback
Note that it is also possible to extract values from the Request body, see https://firebase.google.com/docs/functions/http-events?authuser=0#read_values_from_the_request.

Dialogflow: How do I pass a parameter through in a Firebase query?

I have a Realtime DB in Firebase and have setup an agent in Google Cloud's Dialogflow. This agent agent is fetching data about bus route names. The end user is asked for a bus number and the agent should get relevant info based on that route number. I can call the database but only for a set bus number.
So for example below I can pull in bus info for 100 based on having the snapshot.child set to 100. But I want the snapshot.child to change based on the askBus parameter from Dialogflow. Any suggestions?
function handleBus(agent) {
const bus = agent.parameters.bus;
agent.add(`Thank you...`);
return admin.database().ref('Routes').once("value").then((snapshot) => {
var routeInfo = snapshot.child('100/route_desc').val();
var routeName = snapshot.child('100/route_long_name').val();
agent.add(`Bus info is ` + routeInfo + ' and is called ' + routeName);
In general, the best way to handle this is to reference the node of the bus number as part of setting up the path to the query. Getting it once you have the result is certainly possible, but means you're pulling in a lot more data than you need to for each query.
But there are a few ways to do this.
The one most similar to how you're doing it now is to generate a string that includes the route number. This example shows how to do it using a back-quote, which is available in the most recent JavaScript, or you can just do string concatenation:
function handleBus(agent) {
const bus = agent.parameters.bus;
agent.add(`Thank you...`);
return admin.database().ref('Routes').once("value").then((snapshot) => {
var routeInfo = snapshot.child(`${bus}/route_desc`).val();
var routeName = snapshot.child(`${bus}/route_long_name`).val();
agent.add(`Bus info is ` + routeInfo + ' and is called ' + routeName);
But if you're just looking for the information from that route, you can setup the reference to the database to include the route, get the entire result and its value, and then treat this as a JavaScript object.
function handleBus(agent) {
const bus = agent.parameters.bus;
agent.add(`Thank you...`);
return admin.database().ref('Routes').child(bus).once("value").then((snapshot) => {
var route = snapshot.val();
var routeInfo = route['route_desc'];
var routeName = route['route_long_name'];
agent.add(`Bus info is ` + routeInfo + ' and is called ' + routeName);
As an aside, I want to point out that you're using Promises perfectly. That is a trap many people fall into, and you've done a good job querying the value through a Promise, handling it as part of Promise fulfillment, and returning a Promise in your handler.
In the webhook use async call to firebase to fetch the bus information.
Fetch the parameter value.
Access Firebase DB.
Fetch information based on parameter using async call.
Use promise to reply back with the correct response. See this for responding via promise.
Promise would be used inside your Firebase function when it fetches the DB information.

Resources