Why does this NPM package say it is not a constructor? - node.js

I am working on a Sails.js project that requires me to use this NPM package. I created a new Sails.js service to invoke this package after npm install-ing it like this:
// Require and initialize the rules engine
var jsonRulesEngine = require('json-rules-engine'),
rulesEngine = new jsonRulesEngine();
When I run this script, I get the following error:
/Users/Nag/Code/learn-nodejs/server/node_modules/bluebird/js/release/async.js:61
fn = function () { throw arg; };
^
TypeError: jsonRulesEngine is not a constructor
at Object.verify (/Users/Nag/Code/learn-nodejs/server/api/services/RulesService.js:21:27)
at Object.wrapper [as verify] (/Users/Nag/Code/learn-nodejs/server/node_modules/#sailshq/lodash/lib/index.js:3250:19)
at /Users/Nag/Code/learn-nodejs/server/api/controllers/UtilsController.js:113:43
at /Users/Nag/Code/learn-nodejs/server/api/services/RedisService.js:55:13
at tryCatcher (/Users/Nag/Code/learn-nodejs/server/node_modules/bluebird/js/release/util.js:16:23)
at Promise.successAdapter [as _fulfillmentHandler0] (/Users/Nag/Code/learn-nodejs/server/node_modules/bluebird/js/release/nodeify.js:23:30)
at Promise._settlePromise (/Users/Nag/Code/learn-nodejs/server/node_modules/bluebird/js/release/promise.js:566:21)
at Promise._settlePromise0 (/Users/Nag/Code/learn-nodejs/server/node_modules/bluebird/js/release/promise.js:614:10)
at Promise._settlePromises (/Users/Nag/Code/learn-nodejs/server/node_modules/bluebird/js/release/promise.js:693:18)
at Async._drainQueue (/Users/Nag/Code/learn-nodejs/server/node_modules/bluebird/js/release/async.js:133:16)
at Async._drainQueues (/Users/Nag/Code/learn-nodejs/server/node_modules/bluebird/js/release/async.js:143:10)
at Immediate.Async.drainQueues (/Users/Nag/Code/learn-nodejs/server/node_modules/bluebird/js/release/async.js:17:14)
at Immediate.<anonymous> (/Users/Nag/Code/learn-nodejs/server/node_modules/async-listener/glue.js:188:31)
at runCallback (timers.js:666:20)
at tryOnImmediate (timers.js:639:5)
at processImmediate [as _immediateCallback] (timers.js:611:5)
[nodemon] app crashed - waiting for file changes before starting...
Any clue why I might get that error? In the examples section of the package, the owner of the package imports the package using ES6 format whereas I am requiring it. Does that make a difference?

When you require an NPM package, depending on your module system1, the default export will not automatically be imported when you do this:
var jsonRulesEngine = require('json-rules-engine');
So when you require like you did, it will return the module object, not necessarily the default export as expected. In the package json-rules-package the Engine is exported by default but your require doesn't require the default. If you log the returned module object it will look like this:
{
Engine: function(...) { ... },
Fact: function(...) { ... },
Operator: function(...) { ... },
Rule: function(...) { ... },
default: function(...) { ... }
}
The engine is under the property default and Engine. You could do:
var jsonRulesEngine = require('json-rules-engine').default();
Or:
var jsonRulesEngine = require('json-rules-engine').Engine;
The first will explicitly import the default export. Then you can create an instance of the class like so:
var rulesEngine = new jsonRulesEngine();
1 Yes, using ES2015 import will affect the outcome. If you were to use import syntax from ES2015, this problem would not be encountered. To know why see this answer. In short, Babel transpiles ES2015 code so that default is explicitly accessed when requiring thus importing the default export.

Related

Await in NodeJS in script vs runkit [duplicate]

I have node 14.13.0, and even with --harmony-top-level-await, top-level await is not working.
$ cat i.js
const l = await Promise.new(r => r("foo"))
console.log(l)
$ node -v
v14.13.0
$ node --harmony-top-level-await i.js
/Users/karel/i.js:1
const l = await Promise.new(r => r("foo"))
^^^^^
SyntaxError: await is only valid in async function
at wrapSafe (internal/modules/cjs/loader.js:1001:16)
at Module._compile (internal/modules/cjs/loader.js:1049:27)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1114:10)
at Module.load (internal/modules/cjs/loader.js:950:32)
at Function.Module._load (internal/modules/cjs/loader.js:791:14)
at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:72:12)
at internal/main/run_main_module.js:17:47
What am I doing wrong?
Top-level await only works with ESM modules (JavaScript's own module format), not with Node.js's default CommonJS modules. From your stack trace, you're using CommonJS modules.
You need to put "type": "module" in package.json or use .mjs as the file extension (I recommend using the setting).
For instance, with this package.json:
{
"type": "module"
}
and this main.js:
const x = await Promise.resolve(42);
console.log(x);
node main.js shows 42.
Side note: You don't need --harmony-top-level-await with v14.13.0. Top-level await is enabled by default in that version (it was enabled in v14.8.0).
T.J. Crowder answer is right, but I recommend changing all the .js to .mjs
For example, if you are working with NextJS like me, you will see a problem that files in the .next directory use CommonJS (.next is generated using npx next build) and their extensions are js so it raises an error when the .next files use require()

gulp serve showing error when trying to create sharepoint clent development

gulp serve showing error like below
fs.js:27
const { Math, Object } = primordials;
^
Reference: primordials is not defined
at fs.js:27:26
at req_ (E:\Sharepoint\react-app\node_modules\natives\index.js:143:24)
at Object.req [as require] (E:\Sharepoint\react-app\node_modules\natives\index.js:55:10)
at Object. (E:\Sharepoint\react-app\node_modules\vinyl-fs\node_modules\graceful-fs\fs.js:1:37)

Reference a global JS function in another file, in NodeJS

What I'm actually doing is writing a VS Code Extension, but since I'm new to Node I'm struggling with referencing one JS file from another.
//main.js (compiled from TypeScript)
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
require("./Test.js");
console.log("hello");
t1();
and
//Test.js
function t1() {
console.log("t1");
}
They're both in the same folder. If I run it from VS Code, or from node directly, it doesn't work
PS E:\VSCodeTest> node src/main.js
hello
E:\VSCodeTest\src\main.js:5
t1();
^
ReferenceError: t1 is not defined
at Object.<anonymous> (E:\VSCodeTest\src\main.js:5:1)
at Module._compile (module.js:635:30)
at Object.Module._extensions..js (module.js:646:10)
at Module.load (module.js:554:32)
at tryModuleLoad (module.js:497:12)
at Function.Module._load (module.js:489:3)
at Function.Module.runMain (module.js:676:10)
at startup (bootstrap_node.js:187:16)
at bootstrap_node.js:608:3
The VS Code project is actually TypeScript but I've distilled it down to the crux of the problem in the JS files.
I believe it should work based on
https://www.typescriptlang.org/docs/handbook/modules.html
Import a module for side-effects only Though not recommended practice,
some modules set up some global state that can be used by other
modules. These modules may not have any exports, or the consumer is
not interested in any of their exports. To import these modules, use:
import "./my-module.js";
How have I misunderstood that?
Change Test.js to this:
//Test.js
function t1() {
console.log("t1");
}
module.exports = t1;
And then do something more like this in main.js:
const t1 = require("./Test.js");
t1(); // prints "t1"
There's a lot of information about how modules work in the docs: https://nodejs.org/api/modules.html
Alternatively, if you want t1 to be a global, then assign it to global.t1 in Test.js:
//Test.js
global.t1 = function t1() {
console.log("t1");
};
I wouldn't recommend that if you can avoid it, though, for all the reasons people recommend avoiding globals when possible
Require doesn't work quite like that, but you're close -- if you want to use a function you've created to in another file, just add it to that file's exports.
/// test.js
exports.t1 = function() ...
// or
module.exports = {
t1: function() ...
}
Then you need to specifically save that off to use it
/// main.js
var t1 = require('./test.js').t1;
t1();
Global scoping doesn't work like it does in the browser, check out node's docs on it, or try a blog explaining it (I didn't write this and can't fully vouch)

Meteor ReferenceError Buffer is not defined

I'm running Meteor 1.4.2.3 and after adding some code that deals with files I get a reference error saying "Buffer" is not defined.
The error is in util.js
exports.isPrimitive = isPrimitive; exports.isBuffer = Buffer.isBuffer;
Uncaught ReferenceError: Buffer is not defined
at util.js (modules.js:29525)
at fileEvaluate (modules-runtime.js:343)
at require (modules-runtime.js:238)
at meteorInstall.node_modules.meteor-node-stubs.node_modules.readable-stream.lib._stream_readable.js (modules.js:25209)
at fileEvaluate (modules-runtime.js:343)
at require (modules-runtime.js:238)
at meteorInstall.node_modules.meteor-node-stubs.node_modules.readable-stream.readable.js (modules.js:25144)
at fileEvaluate (modules-runtime.js:343)
at require (modules-runtime.js:238)
at meteorInstall.node_modules.meteor-node-stubs.node_modules.stream-browserify.index.js (modules.js:24653)
at fileEvaluate (modules-runtime.js:343)
at require (modules-runtime.js:238)
at meteorInstall.node_modules.gm.index.js (modules.js:21644)
at fileEvaluate (modules-runtime.js:343)
at require (modules-runtime.js:238)
at meteorInstall.both.collections.files.collection.js (app.js:2317)
at fileEvaluate (modules-runtime.js:343)
at require (modules-runtime.js:238)
at app.js:2583
What is the dependency for Buffer ? am I missing a package?
Buffer is a builtin class in Node.js and doesn't exist in browsers. If there is a separate browser compatible version of the dependency try using that one instead. If not, there is a package in NPM called buffer that can be used as a polyfill in browsers, React Native and other non-Node.js environments.
import Buffer from 'buffer';
if (typeof this.Buffer === 'undefined') {
this.Buffer = Buffer.Buffer;
}
Adding this code on Startup worked for me
global.Buffer = function() {}
global.Buffer.isBuffer = () => false
Complete Code looks like this
Meteor.startup(()=> {
global.Buffer = function() {}
global.Buffer.isBuffer = () => false
ReactDOM.render(<App />, document.getElementById('container'));
});

How do I get jest to ignore the fairly common `debug` node package?

I've got a node js module that looks like this
"use strict";
var debug = require('debug')('foo');
var Foo = function() {
this.x = 123;
debug("init");
};
module.exports = Foo;
And my test looks like this
jest.dontMock('../lib/foo');
jest.dontMock('debug');
describe('footest', function() {
it('checks the foo', function() {
var Foo = require('../lib/foo');
var foo = new Foo();
expect(foo.x).toBe(123);
});
});
But when I run jest with
node node_modules/jest-cli/bin/jest.js
I get
Found 1 matching tests...
FAIL __tests__/foo-test.js (0.02s)
? footest › it checks the foo
- TypeError: /Users/gregg/src/jest-test/lib/foo.js: /Users/gregg/src/jest-test/node_modules/debug/node.js: Cannot read property 'buffer' of undefined
at Socket.self [as bytesWritten] (net.js:688:8)
at _getMetadata (/Users/gregg/src/jest-test/node_modules/jest-cli/src/lib/moduleMocker.js:279:49)
at _getMetadata (/Users/gregg/src/jest-test/node_modules/jest-cli/src/lib/moduleMocker.js:286:23)
at _getMetadata (/Users/gregg/src/jest-test/node_modules/jest-cli/src/lib/moduleMocker.js:279:27)
at _getMetadata (/Users/gregg/src/jest-test/node_modules/jest-cli/src/lib/moduleMocker.js:279:27)
at Object.module.exports.getMetadata (/Users/gregg/src/jest-test/node_modules/jest-cli/src/lib/moduleMocker.js:388:20)
at Loader._generateMock (/Users/gregg/src/jest-test/node_modules/jest-cli/src/HasteModuleLoader/HasteModuleLoader.js:280:56)
at Loader.requireMock (/Users/gregg/src/jest-test/node_modules/jest-cli/src/HasteModuleLoader/HasteModuleLoader.js:782:43)
at Loader.requireModuleOrMock (/Users/gregg/src/jest-test/node_modules/jest-cli/src/HasteModuleLoader/HasteModuleLoader.js:897:17)
at /Users/gregg/src/jest-test/node_modules/debug/node.js:6:11
at Object.runContentWithLocalBindings (/Users/gregg/src/jest-test/node_modules/jest-cli/src/lib/utils.js:309:17)
at Loader._execModule (/Users/gregg/src/jest-test/node_modules/jest-cli/src/HasteModuleLoader/HasteModuleLoader.js:243:9)
at Loader.requireModule (/Users/gregg/src/jest-test/node_modules/jest-cli/src/HasteModuleLoader/HasteModuleLoader.js:879:10)
at Loader.requireModuleOrMock (/Users/gregg/src/jest-test/node_modules/jest-cli/src/HasteModuleLoader/HasteModuleLoader.js:899:17)
at /Users/gregg/src/jest-test/lib/foo.js:3:13
at Object.runContentWithLocalBindings (/Users/gregg/src/jest-test/node_modules/jest-cli/src/lib/utils.js:309:17)
at Loader._execModule (/Users/gregg/src/jest-test/node_modules/jest-cli/src/HasteModuleLoader/HasteModuleLoader.js:243:9)
at Loader.requireModule (/Users/gregg/src/jest-test/node_modules/jest-cli/src/HasteModuleLoader/HasteModuleLoader.js:879:10)
at Loader.requireModuleOrMock (/Users/gregg/src/jest-test/node_modules/jest-cli/src/HasteModuleLoader/HasteModuleLoader.js:899:17)
at Spec.<anonymous> (/Users/gregg/src/jest-test/__tests__/foo-test.js:7:14)
at Timer.listOnTimeout [as ontimeout] (timers.js:110:15)
How do I get jest to ignore the debug package and why does it appear to be making a mock when I told it not to?
Right now there is a bug in jest 0.1.18 (being fixed here, documented here) where core node modules cannot be ignored from being mocked.
Once the pull request is accepted by facebook, this problem should go away.
Until then, you can point your package.json to the repo of the fix:
"jest-cli": "git://github.com/adaschevici/jest.git#cf4c6ff97d7009ff8627dd7d3a59cfeff1f3c8b8"
which should resolve that issue.
The reason this happens is because jest.dontMock('debug'); will only prevent mocking the root file of the debug module, while all other internals will still be mocked.
One possible solution could be to prevent mocking debug library using unmockedModulePathPatterns configuration option:
In package.json:
{
"name": "...",
"version": "0.0.0",
...
"jest": {
"unmockedModulePathPatterns": ["/node_modules/debug"]
},
}
At the top of your test file, try this:
jest.autoMockOff();
Then manually mock files with jest.mock(..)
Update: There's a fix that doesn't require you turn off auto mocking. tldr; add debug, tty, and net to jest.unmockedModulePathPatterns in package.json

Resources