Why is the database snapshot undefined Firebase Admin Node Js? - node.js

The following code comes straight Firebase Functions getting started tutorial:
const functions = require('firebase-functions');
// The Firebase Admin SDK to access the Firebase Realtime Database.
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.addMessage = functions.https.onRequest((req, res) => {
let userid = 'afewfaewf';
let dummyJson = {key: 'value'};
let dbPath = '/' + userid;
admin.database().ref(dbPath).update({dummy: dummyJson}).then(snapshot => {
console.log('finished writing to Firebase database ');
console.log(snapshot === undefined);
res.redirect(303, snapshot.ref);
});
});
Here is the full output running it locally:
❯ firebase serve --only functions
=== Serving from '/Users/eric/AndroidStudioProjects/XXX/firebase-functions'...
i functions: Preparing to emulate HTTPS functions. Support for other event types coming soon.
Warning: You're using Node.js v7.7.1 but Google Cloud Functions only supports v6.9.1.
Server#addProtoService is deprecated. Use addService instead
✔ functions: addMessage: http://localhost:5002/xxx/us-central1/addMessage
info: User function triggered, starting execution
info: finished writing to Firebase database
info: true
error: (node:11005) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): TypeError: Cannot read property 'ref' of undefined
(node:11005) DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
And on the cloud:
11:44:06.290 PM
warning
addMessage
TypeError: Cannot read property 'ref' of undefined at admin.database.ref.update.then.snapshot (/user_code/index.js:32:31) at process._tickDomainCallback (internal/process/next_tick.js:129:7)
TypeError: Cannot read property 'ref' of undefined
at admin.database.ref.update.then.snapshot (/user_code/index.js:32:31)
at process._tickDomainCallback (internal/process/next_tick.js:129:7)
11:44:06.289 PM
warning
addMessage
Unhandled rejection
11:44:06.288 PM
info
addMessage
true
11:44:06.283 PM
info
addMessage
finished writing to Firebase database
11:44:05.322 PM
outlined_flag
addMessage
Function execution started

Thanks #cartan for pointing me to the right direction
The original example "reads" from Firebase database so there is a snapshop value returned
My code on the other try to "writes" to Firebase database, there is no value returned but a call back instead.
I've changed my code to the following and everything works perfectly as expected:
admin.database().ref(dbPath).update({dummy: dummyJson}, function (err) {
console.log("done with error " + err);
res.status(200).send("success");
});

Related

What format should data sent to a Google Cloud Functions onCall request be in?

I have the most simple Google onCall cloud function:
// [START]
exports.echo = functions.https.onCall(async (data, context) => {
return {
value: "echo"
};
});
// [END]
I submit the following in the Google cloud console test:
{"data":"somedata"}
I am getting the following error:
{"error":{"message":"INTERNAL","status":"INTERNAL"}}
It seems there is an issue with the object that I am passing. Can anyone tell me what the correct format is? What am I missing here?
P.s: I am ultimately trying to connect an onCall function with a client application via Firebase/fire, but that is also giving the same error.
Here's the trace:
/workspace/node_modules/firebase-functions/lib/common/providers/https.js:349:16 at fixedLen (/workspace/node_modules/firebase-functions/lib/providers/https.js:66:41) at /workspace/node_modules/firebase-functions/lib/common/providers/https.js:385:32 at processTicksAndRejections (internal/process/task_queues.js:95:5)
Unhandled error TypeError: res.on is not a function at /workspace/node_modules/firebase-functions/lib/common/providers/https.js:350:17 at new Promise () at /workspace/node_modules/firebase-functions/lib/common/providers/https.js:349:16 at fixedLen (/workspace/node_modules/firebase-functions/lib/providers/https.js:66:41) at /workspace/node_modules/firebase-functions/lib/common/providers/https.js:385:32 at processTicksAndRejections (internal/process/task_queues.js:95:5)
Here's the index.ts:
import * as functions from "firebase-functions";
// The Firebase Admin SDK to access Cloud Firestore.
import admin = require("firebase-admin");
// Triggers
import { echo } from "./triggers/echo"
admin.initializeApp();
// Exports
module.exports = {
// OnCall
echo: functions.https.onCall(echo)
};
A few things:
The arrow function signature was incorrect.
async is not required for this synchronous response.
The correct type of the context parameter is CallableContext:
import * as functions from 'firebase-functions';
export const echo = functions.https.onCall((data:any, context:functions.https.CallableContext) => ({
value: "echo"
}))

Nestjs Repository test fails with error "Received promise resolved instead of rejected"

I am writing unit tests for my backend application, I am struggling to test for a item in the database not being found, this is the code for my repository to be tested:
#EntityRepository(Collectible)
export class CollectibleRepository extends Repository<Collectible> {
async getCollectible(id: number) {
const collectible = await this.findOne(id);
if (!collectible) {
throw new NotFoundException();
}
return collectible;
}
}
And this is the code for testing, I will only show this test case.
const mockCollectible = new Collectible(
faker.lorem.sentence(),
faker.lorem.sentences(3),
faker.datatype.float(),
faker.datatype.float(),
faker.datatype.number(),
);
describe('Collectible Repository', () => {
let collectibleRepository: CollectibleRepository;
beforeEach(async () => {
const module = await Test.createTestingModule({
providers: [CollectibleRepository],
}).compile();
collectibleRepository = module.get<CollectibleRepository>(
CollectibleRepository,
);
});
describe('View Collectibles', () => {
it('throws and error as the collectible is not found', async (done) => {
collectibleRepository.findOne = jest.fn().mockResolvedValue(undefined);
await expect(collectibleRepository.getCollectible(1)).rejects.toThrow(
NotFoundException,
);
done();
});
});
});
This causes the following error output:
Expected message: not "Not Found"
8 | const collectible = await this.findOne(id, { relations: ['business'] });
9 | if (!collectible) {
> 10 | throw new NotFoundException();
| ^
11 | }
12 | return collectible;
13 | }
at CollectibleRepository.getCollectibleBusiness (src/collectible/collectible.repository.ts:10:13)
(Use `node --trace-warnings ...` to show where the warning was created)
(node:95012) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 3)
(node:95012) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
FAIL src/collectible/collectible.repository.spec.ts (8.525 s)
● Collectible Repository › View Collectibles › throws and error as the collectible is not found
expect(received).rejects.not.toThrow()
Received promise resolved instead of rejected
Resolved to value: undefined
39 | it('throws and error as the collectible is not found', async (done) => {
40 | collectibleRepository.findOne = jest.fn().mockResolvedValue(undefined);
> 41 | await expect(collectibleRepository.getCollectible(1)).rejects.not.toThrow(
| ^
42 | NotFoundException,
43 | );
44 | done();
at expect (../node_modules/expect/build/index.js:134:15)
at Object.<anonymous> (collectible/collectible.repository.spec.ts:41:13)
I tried using this repository (which was mentioned in another SO thread) with a set of examples for testing Nest.js applications, but it seems like a repository is not being directly tested.
Update: I updated my code since I was missing a await in my code (as noted by Micael Levi ), I was also calling the wrong function (lol). I am receiving the following warning:
(node:98378) UnhandledPromiseRejectionWarning: Error: expect(received).rejects.not.toThrow(expected)
Though probably I will ignore it unless it affects my CI pipeline (which I need to configure lmao)
Update 2: Warning was caused by another test (I may rest for now).
you missed the await in const collectible = this.findOne(id);
So
const collectible = await this.findOne(id);

Parse Sever with custom Express app Master Key Permission Denied

We have a custom express app that loads in the node.js parse server sdk. When we try to use a function call that requires the master key we keep getting errors for permission denied.
at /Users/gateway/Documents/lm/Website/lm-node/node_modules/parse/lib/node/RESTController.js:324:19
at processTicksAndRejections (internal/process/task_queues.js:86:5)
(node:61092) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 4)
(node:61092) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
we initiate our parse server like this..
Parse.initialize(process.env.PARSE_STAGING_APP_ID, null, process.env.PARSE_STAGING_MASTER_KEY);
//Parse.Cloud.useMasterKey();
Parse.serverURL = process.env.PARSE_STAGING_SERVER_URL;
Parse.User.enableUnsafeCurrentUser();
module.exports = Parse
async function channelStatus(orgId) {
const Status = Parse.Object.extend("Status");
const query = new Parse.Query(Status);
query.equalTo("orgID", orgId);
try {
const results = await query.first({useMasterKey: true});
if(results) {
// do some stuff
results.save();
} else {
const StatusNew = Parse.Object.extend("Status");
const statusNew = new StatusNew();
// do some stuff
statusNew.save()
}
} catch (error) {
throw error;
}
}
if we enable Parse.Cloud.useMasterKey(); it works but this can be bad because it works for every function.. we want to make sure we are using masterKey on certain functions..
thoughts?
full error in visual studio.
(node:35145) UnhandledPromiseRejectionWarning: Error: Permission denied for action get on class Status.
at /Users/gateway/Documents/lmx/WebSite/lmx/node_modules/parse/lib/node/RESTController.js:324:19
at process._tickCallback (internal/process/next_tick.js:68:7)
(node:35145) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 4)
(node:35145) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
GET /test - - ms - -
Logs
Jul 29 13:08:29 lmx-stage app/web.1: error: Error generating response. ParseError {
Jul 29 13:08:29 lmx-stage app/web.1: code: 119,
Jul 29 13:08:29 lmx-stage app/web.1: message: 'Permission denied for action get on class Status.' } code=119, message=Permission denied for action get on class Status.
Jul 29 13:08:29 lmx-stage app/web.1: error: Permission denied for action get on class Status. code=119, message=Permission denied for action get on class Status.

NodeJs Require module returns an empty object

I'm using NodeJS 8 LTS.
I have 3 js scripts where:
// main.js
const dom = require ('./Domains/Domains');
const factory = require ('./Domains/Factory');
(async () => {
const Domain = await factory.foo(); // <=== Error
})();
// Domains.js
class Domains {
constructor (options = {}) {
....
}
}
module.exports = Domains;
// Factory.js
const Domains = require('./Domains');
module.exports = {
foo: async () =>{
.... async stuff ...
return new Domains();
}
};
when I run main.js I get
(node:1816) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): TypeError: Domains is not a constructor
warning.js:18
(node:1816) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
Debugging, I found that in Factory.js when it requires Domanis.js const Domains = require('./Domains'); it returns an empty object.
Looking around on internet I found that it happens when there are a circular dependencies between modules (Require returns an empty object) but It doesn't seem the case here.
Any idea?
Finally, I got the the issue's origin. The empty object was due to a circular dependency derived by another require that was inside Domains.js
// Domains.js
const another_module= require("circular_dep_creator");
class Domains {
constructor (options = {}) {
....
}
}
module.exports = Domains;
// circular_dep_creator.js
const factory = require ('./Domains/Factory');
...
another stuff
So, this causes a circular dependency that creates an empty object
The setImmediate call will delay the loading of the required module until the browser has finished doing what it needs to do. This may cause some issues where you try to use this module before it is loaded, but you could add checks for that.
// produces an empty object
const module = require('./someModule');
// produces the required object
let module;
setImmediate(() => {
module = required('./someModule');
});

Module.exports not finding function

So I am creating a basic user login system (this is one of my first nodejs projects) and I am wanting to redirect the user to the 'dashboard' page with a successful login.
First of all I am not sure this is the best way to do the redirecting so I am open to suggestions.
The problem I am having is after calling the function and the user logs in I want to call this function:
var loginResponse = () =>{
io.emit('loginResponse');
}
This is in the server.js file (the main server file) and I am exporting it like so
module.exports = {
loginResponse : loginResponse
};
I am then after all the validation, calling db etc. is done wanting to call it in the login.js file as shown:
var createUserSession = (userSessionObj) =>{
session.user = userSessionObj;
serverMain.loginResponse();
};
I am requiring the file server file like so:
const serverMain = require('../server');
However, I am getting the following error on execute:
(node:35012) UnhandledPromiseRejectionWarning: TypeError: serverMain.loginResponse is not a function
at createUserSession (/Users/chrisholder/Documents/Programming/RandomPrograms/registerlogin/server/registrationlogin/login.js:83:14)
at hashing.comparePassword.then (/Users/chrisholder/Documents/Programming/RandomPrograms/registerlogin/server/registrationlogin/login.js:73:7)
at <anonymous>
(node:35012) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:35012) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
I have tried using the 'path' module as another way to requiring the server.js file however, it has not worked.
Thanks for your help!

Resources