NodeJs Require module returns an empty object - node.js

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');
});

Related

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);

fs.readFileSync(filePath, function read(err, data) {} does not work even tho the targeted file is in the correct location

Here's my relevant code:
1)
let pickenFile = randomItemFormatted.source_filenametxt;
let filePath = `textFiles/${pickenFile}`;
This happens after an axios.get() that returns the name of the file.
The problem does not come from the name of the file itself.
2)
fs.readFileSync(filePath, function read(err, data) {
if(err){
console.log(err);
runTheBot();
}else{
// I should be able to access the data here :(
console.log(data);
tokenizer = new natural.SentenceTokenizer();
let textToTokenize = tokenizer.tokenize(data.toString('utf8').replace(/\0/g, ''));
dataObj.randomItemFormatted = randomItemFormatted;
dataObj.stringsArray = textToTokenize;
return returnSpecificString(dataObj);
}
});
})}
When I pass the filePath to the fs.readFileSync(), the code does not pass the error block. I'm adding the full error response here:
(node:9500) UnhandledPromiseRejectionWarning: Error: ENOENT: no such file or directory, open 'textFiles/1884_Ford__Bradstreet.txt'
at Object.openSync (fs.js:447:3)
at Object.readFileSync (fs.js:349:35)
at /Users/cyrus/Documents/Code/01. Code/franklin-ford-bot/server_side/server.js:74:9
at processTicksAndRejections (internal/process/task_queues.js:85:5)
(node:9500) 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:9500) [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.
Here's also my project's architecture where the targeted .txt files are hosted.I start the server with the node server_side/server.js.
It was working previously and nothing changed in the code since when it was working.
fs.readFileSync() does not take a callback. Your code is trying to use the fs.readFile() interface with fs.readFileSync(). See the doc.
Errors from fs.readFileSync() will be thrown as exceptions so you need try/catch around it to catch errors.
The general structure for using fs.readFileSync() in the code you show would look like this:
try {
let data = fs.readFileSync(filePath);
// I should be able to access the data here :(
console.log(data);
tokenizer = new natural.SentenceTokenizer();
let textToTokenize = tokenizer.tokenize(data.toString('utf8').replace(/\0/g, ''));
dataObj.randomItemFormatted = randomItemFormatted;
dataObj.stringsArray = textToTokenize;
return returnSpecificString(dataObj);
} catch(e) {
console.log(e);
runTheBot();
return something;
}
Now, as for the ENOENT error, that is a separate problem to fix. What I would suggest is that you do this:
const path = require('path');
let filePath = `textFiles/${pickenFile}`
console.log(path.resolve(filePath));
This will show you the full path for the file you were attempting to use. It seems likely that either the full path is not exactly what you expected it to be or there is a file permission issue preventing you from accessing it.
If the textFiles subdirectory you are trying to access is below the module directory where this code is running from, then you may want to use __dirname to reference it like this:
const path = require('path');
let filePath = path.join(__dirname, "textFiles", pickenFile);

TypeError: invNum.next is not a function

I have tried this code :
const invNum = require('invoice-number');
router.post('/checkout', async (req, res, next) => {
if (!req.session.cart) {
return res.redirect('/pos/');
}
var saleList = Sale.find().sort({ _id: -1 }).limit(1); // removed (err, data)=>{} to simply view it is working tested already
var settings = await Setting.find({}); // removed try and catch to simply view it is working tested already
var ticketNumber;
ticketNumber = !saleList ? invNum.next('0000000') : invNum.next(saleList.ticket_number);
var sale = new Sale({
ticket_number:ticketNumber,
cart: req.session.cart,
created_at: new Date()
});
sale.save((err, product) => {
createReceipt(settings, req.session.cart, "receipts/"+ticketNumber+".pdf");
req.session.cart = null;
res.redirect('/pos/');
});
});
I got this error:
TypeError: invNum.next is not a function
The problem is with invNum.next().
invNum.next() is a Node.js module to generate invoice number sequentially installed from npm.
Example:
invNum.next('2017/08/ABC001')
// => 2017/08/ABC002
I have tried already suggestions from previous stackoverflow posts by trying Promises or await async function in order to get this code to work. Hopefully, you can help or suggest something. Thank you.
There is a problem in version of invoice-number module. In the npm it is showing as 1.0.6 but in the GitHub repository it has 1.0.5 in the package.json file.
https://github.com/amindia/invoice-number.
I have tested this module by taking from Github repository and it's working fine.
Please take the source of this module from the given link it will works fine.
Seems to be some error in the module. I tried the below code snippet on RunKit
https://runkit.com/embed/ws2lv1y38mt4
var invNum = require('invoice-number')
try{
invNum.next('sdfsd1')
} catch(e){
console.log(e)
}
Getting the same error
I got this error:
TypeError: invNum.next is not a function 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()
What is the output when you use the console.log on invNum?
Also use try catch and inside call invNum.next with await. Maybe something inside this function is throwing an error.
Edit: as jfriend00 says, if an plain text (like your "0000...") is working, probably the saleList is returning some error and you are not catching or treating the error.
Edit2: The last update on this NPM code is from 1 year ago and fewer people used this lib, probably is broken.
There is some part of the code from the index.js of the lib:
function _next (invoiceNumber) {
if (!invoiceNumber)
throw new Error('invoiceNumber cannot be empty')
var array = invoiceNumber.split(/[_/:\-;\\]+/)
var lastSegment = array.pop()
var priorSegment = invoiceNumber.substr(0, invoiceNumber.indexOf(lastSegment))
var nextNumber = alphaNumericIncrementer(lastSegment)
return priorSegment + nextNumber}
var api = { next: _next}
module.exports = api

Replacing bluebird with node.js native promises breaks Promise.reject

The following code works perfectly fine when I use bluebird promises:
import * as Promise from 'bluebird';
getAccount(id) {
var account = find(accounts, ['id', id]);
return account ?
Promise.resolve(account) :
Promise.reject(new NotFoundError());
}
NotFoundError is defined as follows:
export function NotFoundError(message = 'Not Found') {
this.name = 'NotFoundError';
this.message = message;
this.stack = (new Error()).stack;
}
NotFoundError.prototype = Object.create(Error.prototype);
NotFoundError.prototype.constructor = NotFoundError;
However, if I remove the import of bluebird in getAccount() and let node.js take over promises, the code fails inside the NotFoundError() constructor because this is not defined. Specifically, the constructor is called twice, once correctly from the getAccount() code shown above and a second time by node.js's _tickCallback() function with this as undefined:
NotFoundError (errors.js:13)
runMicrotasksCallback (internal/proces…ext_tick.js:58)
_combinedTickCallback (internal/proces…ext_tick.js:67)
_tickCallback (internal/proces…ext_tick.js:98)
Why is node.js calling the NotFoundError() constructor a second time and that too incorrectly!!!
Please help.
The issue is caused by this line:
.catch(NotFoundError, function() { ... })
Native promises don't have an option to pass a specific error class to a catch method, so what happens is that when an error occurs, NotFoundError is called (without a new in front of it) because it's presumed to be the catch handler.

Bluebird warning "A promise was created in a handler but was not returned from it"

I get the warning about not returning a created promise from Bluebird and I do not understand why and how I should rewrite my code.
(I have tried reading about the warning at Bluebird API page and the anti-pattern page as I suspect this is what I'm doing)
In my view.js file:
var express = require('express'),
router = express.Router(),
settings = myReq('config/settings'),
Sets = myReq('lib/Sets'),
log = myReq('lib/utils').getLogger('View');
router.get('/:setId/', function(req, res, next) {
var
setId = req.params.setId,
user = req.user,
set = new Sets(setId, user);
log.info('Got a request for set: ' + setId);
// The below line gives the warning mentioned
set.getSet().then(function(output) {
res.send(output);
}).error(function(e){
log.error(e.message, e.data);
res.send('An error occurred while handling set:' + e.message);
});
});
module.exports = router;
In my Sets.js file I have:
var
Promise = require('bluebird'),
OE = Promise.OperationalError,
settings = myReq('config/settings'),
UserData = myReq('lib/userData'),
log = myReq('lib/utils').getLogger('sets'),
errorToSend = false;
module.exports = function(setId, user) {
var
sets = myReq('lib/utils').getDb('sets');
return {
getSet : function() {
log.debug('Getting set')
return sets.findOneAsync({
setId:setId
}).then(function(set){
if ( set ) {
log.debug('got set from DB');
} else {
set = getStaticSet(setId);
if ( ! set ) {
throw new OE('Failed getting db records or static template for set: ' + setId );
}
log.debug('got static set');
}
log.debug('I am handling set')
if ( ! checkSet(set) ) {
var e = new OE('Failed checking set');
e.data = set;
throw e;
}
return {
view : getView(set),
logic : set.logic,
canEdit : true,
error : errorToSend
};
});
}
};
};
So the line in my view.js file with "set.getSet()" gives the warning about not returning the created promise. It seems like this script still does what I expect it to do, but I do not understand why I get the warning.
Stacktrace:
Warning: a promise was created in a handler but was not returned from it
at Object.getSet (C:\dev\infoscrn\lib\Sets.js:36:25)
at C:\dev\infoscrn\routes\view.js:39:20
at Layer.handle [as handle_request] (C:\dev\infoscrn\node_modules\express\lib\router\layer.js:82:5)
at next (C:\dev\infoscrn\node_modules\express\lib\router\route.js:110:13)
at Route.dispatch (C:\dev\infoscrn\node_modules\express\lib\router\route.js:91:3)
at Layer.handle [as handle_request] (C:\dev\infoscrn\node_modules\express\lib\router\layer.js:82:5)
at C:\dev\infoscrn\node_modules\express\lib\router\index.js:267:22
at param (C:\dev\infoscrn\node_modules\express\lib\router\index.js:340:14)
at param (C:\dev\infoscrn\node_modules\express\lib\router\index.js:356:14)
at Function.proto.process_params (C:\dev\infoscrn\node_modules\express\lib\router\index.js:400:3)
at next (C:\dev\infoscrn\node_modules\express\lib\router\index.js:261:10)
at Function.proto.handle (C:\dev\infoscrn\node_modules\express\lib\router\index.js:166:3)
at router (C:\dev\infoscrn\node_modules\express\lib\router\index.js:35:12)
at Layer.handle [as handle_request] (C:\dev\infoscrn\node_modules\express\lib\router\layer.js:82:5)
at trim_prefix (C:\dev\infoscrn\node_modules\express\lib\router\index.js:302:13)
at C:\dev\infoscrn\node_modules\express\lib\router\index.js:270:7
at Function.proto.process_params (C:\dev\infoscrn\node_modules\express\lib\router\index.js:321:12)
at next (C:\dev\infoscrn\node_modules\express\lib\router\index.js:261:10)
at C:\dev\infoscrn\node_modules\express\lib\router\index.js:603:15
at next (C:\dev\infoscrn\node_modules\express\lib\router\index.js:246:14)
First, try and update all your dependencies. There's been a recent version of Bluebird, which fixed an issue involving this warning.
Next, make sure you return from all your handlers.
Then, if you still get the warning (like I do) you can disable this specific warning. I chose to do so by setting BLUEBIRD_W_FORGOTTEN_RETURN=0 in my environment.
Don't disable warnings. They're there for a reason.
The typical pattern is that if your onfulfill or onreject handler causes a Promise to be constructed, it will return that Promise (or some chain derived from it) from the handler, so that the chain adopts the state of that Promise.
So Bluebird is keeping track of when it is running one of your handler functions, and also keeping track of when it's Promise constructor is called. If it determines that a Promise was created at any point while your handler is running (that includes anywhere down in the callstack), but that Promise was not returned from your handler, it issues this warning because it thinks you probably forgot to write the return statement.
So if you legitimately don't care about the Promise that was created inside the handler, all you have to do is explicitly return something from your handler. If you don't care about what is returned from your handler (i.e., if you don't care what value the Promise fulfills with), then simply return null. Whatever you return, the explicit return (specifically, a return value other than undefined) tells Bluebird that you think you know what you're doing, and it won't issue this warning.
Make sure that every place you have return statement which is the solution works for me.

Resources