Can I get createSagaMiddleware using require? - node.js

I'm trying to use run sagas in an a node app that will run from the command line: node app.js
I can't use import, so I'm trying to get createSagaMiddleware using require:
const sagaMiddleware = createSagaMiddleware()
I get this error:
"TypeError: createSagaMiddleware is not a function"
Can Saga be used like this?
const { createStore, combineReducers, applyMiddleware } = require("redux");
const createSagaMiddleware = require("redux-saga");
const { take } = require("redux-saga/effects");
const sagaMiddleware = createSagaMiddleware();
const reducer = state => state;
const store = createStore(
reducer,
applyMiddleware(sagaMiddleware)
);
function* watcherSaga() {
yield take("START");
yield //do stuff
}
sagaMiddleware.run(watcherSaga)
store.dispatch({type: 'START'})

Try this:
const createSagaMiddleware = require("redux-saga").default;

Related

jest.spy on a global function is ignored when the spy is called from another function

I'm working on a legacy JS web project that doesn't use import/require etc. So if I want to write tests, I need to somehow load all the code before the test is executed (I'm using a custom testEnvironment for that).
I've created a sample repo here.
Here are the main files:
// ./src/index.js
function spyOnMe() {
return "Hello World!";
}
function main() {
const text = spyOnMe();
return text;
}
// ./src/index.spec.js
it('should spyOn spyOnMe', () => {
const mockedValue = 'Thanks for helping!';
jest.spyOn(window, 'spyOnMe').mockReturnValue(mockedValue);
expect(spyOnMe()).toBe(mockedValue); // OK
const result = main();
expect(result).toBe(mockedValue); // KO
});
// ./jest.config.js
module.exports = {
clearMocks: true,
coverageProvider: "v8",
testEnvironment: "./jest.env.js",
};
// ./jest.env.js
const JSDOMEnvironment = require("jest-environment-jsdom");
const vm = require("vm");
const fs = require("fs");
class MyEnv extends JSDOMEnvironment.default {
constructor(config, context) {
super(config, context);
this.loadContext();
}
loadContext() {
const js = fs.readFileSync("./src/index.js", "utf8");
const context = vm.createContext();
context.document = this.global.document;
context.window = this.global.window;
vm.runInContext(js, context, {
filename: "./src/index.js",
displayErrors: true,
});
Object.assign(this.global, context);
}
}
module.exports = MyEnv;
The issue is in the index.spec.js:
The first expect returns Thanks for helping!
The second one returns "Hello world!"
Why is that?
I found a fix but I don't really understand why it works:
In jest.env.js, I should replace this line:
- const context = vm.createContext();
+ const context = vm.createContext(this.global);

What To Do Failed Compiling?

I am getting an error while running the command npm start. The file is created in PancakeSwap Frontend and I've been trying to fix this for a while, thanks for your help :)
Here is my App.js code:
import React, { useState, useEffect } from "react";
import SimpleStorageContract from "./contracts/SimpleStorage.json";
import getWeb3 from "./getWeb3";
import BlockchainContext from './BlockchainContext.js';
import "./App.css";
function App() {
const [storageValue, setStorageValue] = useState(undefined);
const [web3, setWeb3] = useState(undefined);
const [accounts, setAccounts] = useState([]);
const [contract, setContract] = useState([]);
useEffect(() => {
try {
// Get network provider and web3 instance.
const web3 = await getWeb3();
// // Use web3 to get the user's accounts.
const accounts = await web3.eth.getAccounts();
// // Get the contract instance.
const networkId = await web3.eth.net.getId();
const deployedNetwork = SimpleStorageContract.networks[networkId];
const contract = new web3.eth.Contract(
SimpleStorageContract.abi,
deployedNetwork && deployedNetwork.address,
);
// Set web3, accounts, and contract to the state, and then proceed with an // example of interacting with the contract's methods.
setWeb3(web3);
setAccounts(accounts);
setContract(contract);;
this.setState({ web3, accounts, contract: instance } catch (error) {
// Catch any errors for any of the above operations.
alert(
`Failed to load web3, accounts, or contract. Check console for details.`,
);
console.error(error);
const init = async() => {
}
init();
}, []);
useEffect(() => {
const load = async () => {
// Stores a given value, 5 by default.
await contract.methods.set(5).send({ from: accounts[0] });
// // Get the value from the contract to prove it worked.
const response = await contract.methods.get().call();
// // Update state with the result.
setStorageValue(response);
}
if(typeof web3 !== 'undefined'
&& typeof account !== 'undefined'
&& typeof contract !== 'undefined'{
load();
}
}, [web3, accounts, contract]);
if(typeof web3 === 'undefined') {
return <div>Loading Web3, account, and contract...</div>;
}
return (
<div className="App">
<BlockchainContext.Provider value={{web3, accounts, contract}}>
<h1>Good to Go!</h1>
<p>Your Truffle Box is installed and ready.</p>
<h2>Smart Contract Example</h2>
<p>
If your contracts compiled and migrated successfully, below will show
a stored value of 5 (by default).
</p>
<p>
Try changing the value stored on <strong>line 42</strong> of App.js.
</p>
<div>The stored value is: {storageValue}</div>
</BlockchainContext.Provider>
</div>
);
}
export default App;
And the error which I am getting is:
Failed to compile.
./src/App.js
Line 17:23: Parsing error: Can not use keyword 'await' outside an async function
15 | try {
16 | // Get network provider and web3 instance.
> 17 | const web3 = await getWeb3();
| ^
18 |
19 | // // Use web3 to get the user's accounts.
20 | const accounts = await web3.eth.getAccounts();
The code provided is pretty messy, but it looks like you are trying to use the await keyword in a synchronous function, specifically the function being passed as an argument into useEffect(). The await keyword can only be used inside asynchronous functions.
If you can, the easiest solution would be to make the function asynchronous by adding the async keyword (demonstrated below).
function App() {
const [storageValue, setStorageValue] = useState(undefined);
const [web3, setWeb3] = useState(undefined);
const [accounts, setAccounts] = useState([]);
const [contract, setContract] = useState([]);
useEffect(async () => {
If that won't work, you could use .then() instead (demonstrated below), however this will require more work.
function App() {
const [storageValue, setStorageValue] = useState(undefined);
const [web3, setWeb3] = useState(undefined);
const [accounts, setAccounts] = useState([]);
const [contract, setContract] = useState([]);
useEffect(() => {
try {
// Get network provider and web3 instance.
getWeb3().then(web3=>{
// code goes here
}).catch(err=>{
// error handling
});
I also recommend reading a little about async/await if you haven't already. This MDN article is a good place to start.

'Await' doesn't work with imported Async Function (email-deep-validator)

I'm trying to use the 'email-deep-validator' npm package ( https://www.npmjs.com/package/email-deep-validator ) following the examples:
const EmailValidator = require('email-deep-validator');
const emailValidator = new EmailValidator();
const { wellFormed, validDomain, validMailbox } = await emailValidator.verify('myEmail#myDomain.com');
But Node returns this error: SyntaxError: await is only valid in async function
I've checked in the code of this package that the verify function is defined like Async ( https://github.com/getconversio/email-deep-validator/blob/master/lib/index.js ) and I tried to execute the code with serveral versions of Node (9.2.0, 10.16.1, 12.7.0).
I'd appreciate an orientation. Thanks.
You can use await only in async function, the error message is pretty clear.
Example:
const EmailValidator = require('email-deep-validator');
const emailValidator = new EmailValidator();
async function main() {
const { wellFormed, validDomain, validMailbox } = await emailValidator.verify('myEmail#myDomain.com');
// ...rest of your code
}
main()
Thank at all for your help. This and other answers works properly:
#Rashomon:
You can use await only in async function, the error message is pretty clear.
Example:
const EmailValidator = require('email-deep-validator');
const emailValidator = new EmailValidator();
async function main() {
const { wellFormed, validDomain, validMailbox } = await emailValidator.verify('myEmail#myDomain.com');
// ...rest of your code
}
main()
You can only use await inside async functions.
const EmailValidator = require('email-deep-validator');
const emailValidator = new EmailValidator();
// top level async function
(async () => {
const { wellFormed, validDomain, validMailbox } = await emailValidator.verify('myEmail#myDomain.com');
})()

ObjectionJS - Group models in a data layer file

I have a NodeJS app running fastify with fastify-objectionjs.
For tidiness, I'd like to group all models in a single file called _main.js, where I export an array of the models inside the models folder.
Since the fastify-objectionjs registration requires an array of models, I thought I could just import the array from my _main.js and feed it as it is to the registration function.
But ObjectionJS is telling me that The supplied models are invalid.
/app.js (node entry point)
const fastify = require('fastify')({
logger: true
})
const knexConfig = require('./knexfile')
const dataLayer = require('./models/_main')
fastify.register(require('fastify-objectionjs'), {
knexConfig: knexConfig,
models: dataLayer
})
// Also tried:
// fastify.register(require('fastify-objectionjs'), {
// knexConfig: knexConfig,
// models: [dataLayer]
// })
/models/_main.js
const User = require('./user.model')
var dataLayer = [User]
module.exports = dataLayer
// Also tried without var:
// module.exports = {
// dataLayer: [
// User
// ]
// }
/models/user.model.js
const Knex = require('knex')
const connection = require('../knexfile')
const { Model } = require('objection')
const knexConnection = Knex(connection)
Model.knex(knexConnection)
class User extends Model {
static get tableName () {
return 'users'
}
}
module.exports = { User }
I can't seem to find a problem in the file flow, but if I create the models array on the fly, the app starts smoothly:
/app.js (node entry point)
const fastify = require('fastify')({
logger: true
})
const knexConfig = require('./knexfile')
const User = require('./models/user.model') // changed
fastify.register(require('fastify-objectionjs'), {
knexConfig: knexConfig,
models: [User] // changed
})
Any idea why this isn't working?
Thanks in advance for your time.
Found the gotcha, I just needed to use destructuring in the require of User, like this:
/models/_main.js
// BAD
// const User = require('./user.model')
// GOOD
const { User } = require('./user.model')
module.exports = [User]
Works like a charm.
Useful question that explains the difference:
Curly brackets (braces) in node require statement

Declare multiple module.exports in Node.js

What I'm trying to achieve is to create one module that contains multiple functions in it.
module.js:
module.exports = function(firstParam) { console.log("You did it"); },
module.exports = function(secondParam) { console.log("Yes you did it"); },
// This may contain more functions
main.js:
var foo = require('module.js')(firstParam);
var bar = require('module.js')(secondParam);
The problem I have is that the firstParam is an object type and the secondParam is a URL string, but when I have that it always complains that the type is wrong.
How can I declare multiple module.exports in this case?
You can do something like:
module.exports = {
method: function() {},
otherMethod: function() {},
};
Or just:
exports.method = function() {};
exports.otherMethod = function() {};
Then in the calling script:
const myModule = require('./myModule.js');
const method = myModule.method;
const otherMethod = myModule.otherMethod;
// OR:
const {method, otherMethod} = require('./myModule.js');
To export multiple functions you can just list them like this:
module.exports = {
function1,
function2,
function3
}
And then to access them in another file:
var myFunctions = require("./lib/file.js")
And then you can call each function by calling:
myFunctions.function1
myFunctions.function2
myFunctions.function3
in addition to #mash answer I recommend you to always do the following:
const method = () => {
// your method logic
}
const otherMethod = () => {
// your method logic
}
module.exports = {
method,
otherMethod,
// anotherMethod
};
Note here:
You can call method from otherMethod and you will need this a lot
You can quickly hide a method as private when you need
This is easier for most IDE's to understand and autocomplete your code ;)
You can also use the same technique for import:
const {otherMethod} = require('./myModule.js');
module.js:
const foo = function(<params>) { ... }
const bar = function(<params>) { ... }
//export modules
module.exports = {
foo,
bar
}
main.js:
// import modules
var { foo, bar } = require('module');
// pass your parameters
var f1 = foo(<params>);
var f2 = bar(<params>);
This is just for my reference as what I was trying to achieve can be accomplished by this.
In the module.js
We can do something like this
module.exports = function ( firstArg, secondArg ) {
function firstFunction ( ) { ... }
function secondFunction ( ) { ... }
function thirdFunction ( ) { ... }
return { firstFunction: firstFunction, secondFunction: secondFunction,
thirdFunction: thirdFunction };
}
In the main.js
var name = require('module')(firstArg, secondArg);
If the files are written using ES6 export, you can write:
module.exports = {
...require('./foo'),
...require('./bar'),
};
One way that you can do it is creating a new object in the module instead of replacing it.
for example:
var testone = function () {
console.log('test one');
};
var testTwo = function () {
console.log('test two');
};
module.exports.testOne = testOne;
module.exports.testTwo = testTwo;
and to call
var test = require('path_to_file').testOne:
testOne();
You can write a function that manually delegates between the other functions:
module.exports = function(arg) {
if(arg instanceof String) {
return doStringThing.apply(this, arguments);
}else{
return doObjectThing.apply(this, arguments);
}
};
There are multiple ways to do this, one way is mentioned below.
Just assume you have .js file like this.
let add = function (a, b) {
console.log(a + b);
};
let sub = function (a, b) {
console.log(a - b);
};
You can export these functions using the following code snippet,
module.exports.add = add;
module.exports.sub = sub;
And you can use the exported functions using this code snippet,
var add = require('./counter').add;
var sub = require('./counter').sub;
add(1,2);
sub(1,2);
I know this is a late reply, but hope this helps!
use this
(function()
{
var exports = module.exports = {};
exports.yourMethod = function (success)
{
}
exports.yourMethod2 = function (success)
{
}
})();
also you can export it like this
const func1 = function (){some code here}
const func2 = function (){some code here}
exports.func1 = func1;
exports.func2 = func2;
or
for anonymous functions like this
const func1 = ()=>{some code here}
const func2 = ()=>{some code here}
exports.func1 = func1;
exports.func2 = func2;
You can use like i did below... for both functions and arrow functions :
greet.js :
function greetFromGreet() {
console.log("hello from greet module...");
}
const greetVar = () => {
console.log("greet var as a arrow fn/...");
};
module.exports = { greetVar, greetFromGreet }; // ---- multiple module export...
// -----------------------------------------------
app.js :
const greetFromGreets = require("./greet");
greetFromGreets.greetFromGreet();
greetFromGreets.greetVar();
// -----------------------------------------------
Inside your node module you can export various functions such as:
module.exports.eat = eat;
function eat() {
.......
return *something*;
};
module.exports.sleep = sleep;
function sleep() {
.......
return *something*;
};
Note that you are not calling the functions while exporting them.
Then while requiring the modules you can require as:-
const task = require(__dirname + "/task.js");
//task is the name of the file
let eat = task.eat();
let sleep = task.sleep();
Two types module import and export.
type 1 (module.js):
// module like a webpack config
const development = {
// ...
};
const production = {
// ...
};
// export multi
module.exports = [development, production];
// export single
// module.exports = development;
type 1 (main.js):
// import module like a webpack config
const { development, production } = require("./path/to/module");
type 2 (module.js):
// module function no param
const module1 = () => {
// ...
};
// module function with param
const module2 = (param1, param2) => {
// ...
};
// export module
module.exports = {
module1,
module2
}
type 2 (main.js):
// import module function
const { module1, module2 } = require("./path/to/module");
How to use import module?
const importModule = {
...development,
// ...production,
// ...module1,
...module2("param1", "param2"),
};
module1.js:
var myFunctions = {
myfunc1:function(){
},
myfunc2:function(){
},
myfunc3:function(){
},
}
module.exports=myFunctions;
main.js
var myModule = require('./module1');
myModule.myfunc1(); //calling myfunc1 from module
myModule.myfunc2(); //calling myfunc2 from module
myModule.myfunc3(); //calling myfunc3 from module
Use the export keyword
module.js
export {method1, method2}
And import them in main.js
import {method1, method2) from "./module"
If you declare a class in module file instead of the simple object
File: UserModule.js
//User Module
class User {
constructor(){
//enter code here
}
create(params){
//enter code here
}
}
class UserInfo {
constructor(){
//enter code here
}
getUser(userId){
//enter code here
return user;
}
}
// export multi
module.exports = [User, UserInfo];
Main File: index.js
// import module like
const { User, UserInfo } = require("./path/to/UserModule");
User.create(params);
UserInfo.getUser(userId);
You can use this approach too
module.exports.func1 = ...
module.exports.func2 = ...
or
exports.func1 = ...
exports.func2 = ...
Adding here for someone to help:
this code block will help adding multiple plugins into cypress index.js
Plugins -> cypress-ntlm-auth and cypress env file selection
const ntlmAuth = require('cypress-ntlm-auth/dist/plugin');
const fs = require('fs-extra');
const path = require('path');
const getConfigurationByFile = async (config) => {
const file = config.env.configFile || 'dev';
const pathToConfigFile = path.resolve(
'../Cypress/cypress/',
'config',
`${file}.json`
);
console.log('pathToConfigFile' + pathToConfigFile);
return fs.readJson(pathToConfigFile);
};
module.exports = async (on, config) => {
config = await getConfigurationByFile(config);
await ntlmAuth.initNtlmAuth(config);
return config;
};
module.exports = (function () {
'use strict';
var foo = function () {
return {
public_method: function () {}
};
};
var bar = function () {
return {
public_method: function () {}
};
};
return {
module_a: foo,
module_b: bar
};
}());

Resources