Using firebase emulator with react-fire package - javascript

I am, following this answer, setting up the firebase emulator using react-fire with the following code
const preloadSDKs = (firebaseApp: firebase.app.App) => {
return Promise.all([
preloadFirestore({
firebaseApp,
setup: firestore => {
return firestore().useEmulator('localhost', 8080);
}
}),
]);
};
interface IAppProps {
}
const App: React.FunctionComponent<IAppProps> = (props) => {
const firebaseApp = useFirebaseApp();
preloadSDKs(firebaseApp).then(() => Promise.resolve());
However, I am a bit confused as to how I can add some condidtional code that makes sure I use the emulator in development, and use my cloud firestore in production build.
Can anyone help me configure this?

Related

Got the error code "TypeError: Cannot read properties of null (reading 'sendTransaction')" while trying to deploy to the goerli test network

Here is my hardhat.config.js code
// hardhat.config.js
require("#nomiclabs/hardhat-ethers");
require("#nomiclabs/hardhat-waffle");
require("dotenv").config()
// You need to export an object to set up your config
// Go to https://hardhat.org/config/ to learn more
const GOERLI_URL = process.env.GOERLI_URL;
const PRIVATE_KEY = process.env.PRIVATE_KEY;
/**
* #type import('hardhat/config').HardhatUserConfig
*/
module.exports = {
solidity: "0.8.4",
networks: {
goerli: {
url: process.env.GOERLI_URL || "https://eth-goerli.alchemyapi.io/v2/PT8BEXCUKwsfvcBz8y3g7A2V7LdhUKQA",
accounts: process.env.PRIVATE_KEY
}
}
};
And my deploy.js script:
// scripts/deploy.js
const hre = require("hardhat");
async function main() {
// We get the contract to deploy.
const BuyMeACoffee = await hre.ethers.getContractFactory("BuyMeACoffee");
const buyMeACoffee = await BuyMeACoffee.deploy();
await buyMeACoffee.deployed();
console.log("BuyMeACoffee deployed to:", buyMeACoffee.address);
}
// We recommend this pattern to be able to use async/await everywhere
// and properly handle errors.
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});
I really do not know how to get it sorted and it pretty much has left me in a loop.
Please help. Thank You
I am pretty much new to using hardhat and npm. My current node v16.13.1 (npm v8.1.2)
There was an error in the hardhat.config file instead of accounts:process.env.PRIVATE_KEY, it should have been accounts:[process.env.PRIVATE_KEY]

NextJS - TypeError: res.unstable_revalidate is not a function

I try to use a brand new feature released in NextJS v.12.1 https://deepinder.me/nextjs-on-demand-isr. The API itself works fine. I can reach it. But in exchange it returns 500 error that says res.unstable_revalidate is not a function. It does not work either over dev (next server && next dev) run or production one (next build && next start).
This is the api endpoint:
// ./api/misc/revalidate
const revalidateCache = async (_, res) => {
console.log(res.unstable_revalidate, 'TEST REVALIDATE'); // res.unstable_revalidate is undefined here :(
try {
await res.unstable_revalidate('/');
return res.json({ revalidated: true });
} catch (err) {
return res.status(500).send(`Error revalidating: ${err}`);
}
};
export default revalidateCache;
This is the invoke:
// ./apps/client/services/server
const getRevalidate = async () => {
await fetch('/api/misc/revalidate');
};
export default getRevalidate;
View layer that I call from:
// .src/pages/index.js
// ...some code here
const HomePage = ({ page, legacy }) => {
const handleClick = () => {
getRevalidate();
};
return (
<div className={styles.homeRoot}>
<button onClick={handleClick}>REVALIDATE</button>
</div>
);
};
UPD:
I use express to handle API abstration.
import express from 'express';
import revalidateCacheApi from './api/misc/revalidate';
export default app => {
// ...some code here
app.use('/api/misc/revalidate', revalidateCacheApi);
};
NVM. It was an issue with my local server. I use advanced set up with two independent instances (:3000 and :4000) spinning in the memory.
The way I designed API above suppose to call it over :4000 server. Which is in fact Express server (obviously does not has NextJS internal API to purge the cache).
So I moved the call to the pages/api/revalidate and up to :3000 server.
Works fine:
// ./src/pages/server/revalidate.js
const getRevalidate = async () => {
await fetch('/api/revalidate');
};
export default getRevalidate;

Passing Firestore (v9) instance across packages

I'm trying to write some Firestore operations into a separate package so that it could be imported and reused in different web apps. I'm building a monorepo with different packages and I'm trying to use Firebase v9 for the following example:
From packageA I'm defining and exporting a getPosts(db) function that takes in a Firestore object and returns some posts form the given database
// in 'packageA'
import { collection, getDocs, Firestore } from 'firebase/firestore';
export const getPosts = async (db: Firestore) => {
console.log('Passed in db: ', db); // This correctly prints the passed in Firestore object
try {
const postsCollection = collection(db, 'posts'); // This function will throw
const querySnapshot = await getDocs(postsCollection);
return querySnapshot.docs.map((doc) => doc.data());
} catch (e) {
console.error('Error reading posts: ', e);
}
}
In a web app I'm initialising the Firebase app and exporting the Firestore instance
// firebase.js in 'web-app-1'
import { initializeApp } from 'firebase/app';
import { getFirestore } from 'firebase/firestore';
const firebaseConfig = { /* my Firebase config */ };
export const app = initializeApp(firebaseConfig);
export const db = getFirestore(app);
Then I'm trying to use the getPosts function from the package in a component...
// App.js in 'web-app-1'
import { db } from './firebase.js';
import { getPosts } from 'packageA';
let posts;
async function loadPosts() {
try {
posts = await getPosts(db);
} catch (e) {
console.error(e);
}
}
loadPosts(); // throws an error
but I get the following error from the collection(db, 'posts') call
Error reading posts: Expected first argument to collection() to be a CollectionReference, a DocumentReference or FirebaseFirestore
even though the passed in database is correctly printed in the console (form the getPosts function)
Note: If I copy the whole getPosts function and use it directly in the web app (i.e. without importing it from another package) then it works and correctly fetches the posts.
It looks like a bug with version 9, and the method is trying to use a Firebase Realtime Database instead of Firestore, so the method is sending an error for the collections.
It seems to override the fact that it's Firestore when using the function, so I would send this to the Firebase support directly because the way that the package is being formed seems to be the main issue.
I've been looking around a bit more and found this answer to a similar question to solve my problem too.
Basically what I had to do is to specify Firebase as a peerDependency in packageA and not include it in the final bundle. The web apps that consume packageA will include Firebase as a regular dependency.
So the package.json files look as follows
In the utility package
{
"name": "packageA",
"peerDependencies": {
"firebase": "^9.6.3"
}
}
and then in the web apps
{
"name": "web-app-1",
"dependencies": {
"firebase": "^9.6.3",
}
}
This approach also makes sense to my use case as the web app – and only the web app – that initialises the Firebase app will include it in its bundle. I can imagine however that in some other use cases this is not a possible solution.
Nevertheless I have submitted my issue to the Firebase support as suggested and here is their answer:
We have received some similar cases and we are already working to solve this. However, it can take a while due the workload of the engineering team, please, be patient.
I am currently experience the same problem. The workaround is importing the files direct via the bundler.
Keep in mind this is not optimal because I have to install the packages in the native project again, so it requires some manual maintenance
Project structure
apps
native
web
packages
utils
This ensures that my app uses the firebase instance and package that is inside native/node_modules/
Metro.config.js
`
const { getDefaultConfig } = require("#expo/metro-config");
const path = require("path");
const projectRoot = __dirname;
const workspaceRoot = path.resolve(__dirname, "../..");
const config = getDefaultConfig(__dirname);
const extraNodeModules = {
'#aim/utils': path.resolve(__dirname + '/../../packages/utils'),
};
const watchFolders = [
path.resolve(__dirname + '/../../packages/utils')
];
config.watchFolders = [workspaceRoot];
config.resolver.nodeModulesPath = [
path.resolve(projectRoot, "node_modules"),
path.resolve(workspaceRoot, "node_modules"),
];
module.exports = {
transformer: {
getTransformOptions: async () => ({
transform: {
experimentalImportSupport: false,
inlineRequires: false,
},
}),
},
resolver: {
extraNodeModules: new Proxy(extraNodeModules, {
get: (target, name) =>
//redirects dependencies referenced from common/ to local node_modules
name in target ? target[name] : path.join(process.cwd(), `node_modules/${name}`),
}),
},
watchFolders,
};
// module.exports = config;
`
getting types to work (native)
tsconfig.json
`
{
"compilerOptions": {
"allowSyntheticDefaultImports": true,
"jsx": "react-native",
"lib": ["dom", "esnext"],
"moduleResolution": "node",
"noEmit": true,
"skipLibCheck": true,
"resolveJsonModule": true,
"strict": true,
"baseUrl": ".",
"paths": {
"#aim/utils/*": ["../../packages/utils/*"]
}
},
}
`

Firebase Login Fails on Localhost but works in Production

Code relevant to the issue
<SimpleButton
onClick={this.onClickLogin}
disabled={!this.isEmailPasswordValid()}
style={{ width: '50%' }}
id="gi-auth-modal-log-in-button">
Log In
</SimpleButton>
async onClickLogin() {
const that = this;
this.props
.loginWithPassword(that.state.email, that.state.password)
.then(() => {
that.props.closeModal();
})
.catch(e => console.log(e))
}
export const loginWithPassword = (email, password) => async (dispatch) => {
return await firebase
.auth()
.signInWithEmailAndPassword(email, password)
.then(async (userData) => {
await dispatch(login(userData));
})
.catch(handleFirebaseError);
};
When I run this project on localhost and try to login (with valid credentials), onClickLogin catches the following error:
{
"code": "auth/invalid-api-key",
"message": "Your API key is invalid, please check you have copied it correctly."
}
The error message seems simple enough but here is the kicker: the same code works in production. My assumption is that since this code works in production but not on localhost it is some kind of environment configuration issue.
Please help me understand what it can be and should there be any differences in login behavior between dev and production (assuming the same DB is used for both).
Firebase code for reference:
import * as firebaseAdmin from 'firebase-admin';
const firebaseConfig = {
apiKey: process.env.FIREBASE_KEY,
projectId: process.env.FIREBASE_PROJECT_ID
};
firebaseAdmin.initializeApp(firebaseConfig);
late answer but I had the same problem.
Do you have any Allow CORS extension installed? Try to toggle it to off and try again.
Make sure you added localhost in the authorized domains list in your firebase project

node Mqtt.js structuring code / best practices

So I've been searching for a long time on mqtt.js examples for structuring and best practices and haven't found anything worthwhile. thus [main] how do you structure your mqtt.js code in your node/express application?
[1] So the libraries mqttjs/async-MQTT provides some example on connecting and on-message but on a real app with lots of subscription and publishes how to structure code so that it initiliazes on the app.js and uses the same client (return from the mqtt.connect) for all the sub/pub in different files.
[2] and from the question[1] should my app only use 1 client for all the works or can use multiple clients as needed on multiple files (let's say I have 3 files mqttInit, subscriber, publisher. so if I use the init on subscriber and get a client should I export it or just make a new instance of a client on the publisher file)
[3] so the mqttjs API provides only an onMessage function so all subscribed topics message gets here thus I put a switch or a if else to manage this so if we have a lot of topics how do you manage this
[4] so my current setup is kind of messed up
this is the initializer file lets say'
mqttService.js
const mqtt = require("mqtt");
const { readFileSync } = require("fs");
module.exports = class mqttService {
constructor() {
this.client = mqtt.connect("mqtt://xxxxxxxxxxx", {
cert: readFileSync(process.cwd() + "/certificates/client.crt"),
key: readFileSync(process.cwd() + "/certificates/client.key"),
rejectUnauthorized: false,
});
this.client.on("error", (err) => {
console.log(err);
});
this.client.once("connect", () => {
console.log("connected to MQTT server");
});
}
};
subscriber.js
this is the function(subscribe()) that I call in app.js to init the mqtt thing
const { sendDeviceStatus, sendSensorStatus } = require("../socketApi");
const { client } = new (require("./mqttService"))();
function subscribe() {
let state = {
timer: false,
};
...
let topics = {
....
},
client.subscribe([...]);
client.on("message", async (topic, buffer) => {
if (topic) {
...
}
});
}
module.exports = {
subscribe,
client,
};
publish.js
const { AsyncClient } = require("async-mqtt");
const _client = require("./subscribe").client;
const client = new AsyncClient(_client);
async function sendSensorList(daqId) {
let returnVal = await client.publish(
`${daqId}-GSL-DFC`,
JSON.stringify(publishObject),
{ qos: 1 }
);
console.log(returnVal);
return publishObject;
}
.....
module.exports = {
sendSensorList,
.......
};
so as you can see from the above code everything is kind of linked with one another and messed up thus I need some expo on how you structure code
thanks for reading, please feel free to provide any info and any info is much appreciated

Categories