How to export class instance in Node? - javascript

Let's say, i have a class instance
const User = require(./User);
const id = '123456',
secret = '8787';
const user = new User(id, secret)
module.exports = user;
The problem is that whenever i import user, it just returns an empty object.
Why is this occurring and what should i do in this case?
This is what i'm using for testing
index.js file
const OAuthClient = require('disco-oauth'); //class disco-oauth
const credential = require('./credential.json');
//class instance
const oauthclient = new OAuthClient(credential.id,credential.secret);
console.log(oauthclient); //Working fine in here
module.exports = oauthclient; //exporting instance
test.js file
const oauthclient = require('./index')
console.log(oauthclient) //prints {}

you should make file with name User.js and copy this code :
class user {
constructor(id, secret){
this.id= id,
this.secret=secret
}
}
module.exports = user;
and your file is ok for require User class (yourFile.js)
const User = require(./User);
const id = '123456',
secret = '8787';
const user = new User(id, secret)
module.exports = user;
and you can make test.js file for import this user (yourFile.js) :
const user = require('./yourFile.js')
console.log(user)

I think the problem is in how you export your class,
seems like you used module.export = User instead of module.exports= User

My node server is running in index.js file and i was trying to export the class instance from that file, that's why it didn't work.
Previous code
const http = require('http'),
bodyparser = require('body-parser'),
OAuthClient = require('disco-oauth');
const app = require('./Api/api');
const credential = require('./credential.json');
const oauthClient = new OAuthClient(credential.id, credential.secret);
oauthClient.setScopes(['identify', 'guilds', 'connections']);
oauthClient.setRedirect(credential.redirect);
app.use(bodyparser.urlencoded({extended: false}))
app.use(bodyparser.json())
const server = http.createServer(app),
PORT = 80;
server.listen(PORT,'0.0.0.0', () => {
console.log(`running on port ${PORT}`);
})
module.exports = {
oauthClient
}
I removed OAuthClient from index.js and moved it in separate file and it's working now.

Related

Problem with adding imported function into exported function

So basically I want this block:
const {someFunction} = require("/somePath");
exports.exportedFunction = (req, res) => { someFunction() }
to work like this block:
exports.exportedFunction = (req, res) => {
const {someFunction} = require("/somePath");
someFunction();
}
But without repeating the imports. How to prevent repeating imports into every single export? I want to have one import from which I can use the function into every export without importing exactly into exports. Is that even possible?
UPDATE: okay, there's small update. I have made a minimum requirement problem recreation and it looks like this:
//index.js
const express = require("express");
const app = express();
const router = require("./router");
exports.exportableStuff = () => {
return [1,2,3];
};
app.use("/", router);
app.listen(3000, () => {
console.log("i am listening");
});
//router.js
const express = require("express");
const router = express.Router();
const controller = require("./controller");
router.get("/", controller.testModule);
module.exports = router;
//controller.js
const {exportableStuff} = require("./index");
exports.testModule = (req, res) => {
console.log("it has been done");
exportableStuff();
res.send("<h1>hello, user</h1>");
}
UPDATE2: I actually managed to fix the closures myself. What I actually did to make this work is changing this:
const {exportableStuff} = require("./index");
Into:
const model = require("./index");
And call the function in my controller with model.exportableStuff().
Problem oficially solved, but if you have better idea, I'm all ears.
According to your comment, I think you might want to do following thing?
// index.js
module.exports = { someFunction }
// router.js
// case1
const { someFunction } = require("./index.js")
someFunction() // it will work
// case2
const index = require("./index.js")
index.someFunction() // it will work
But, if you want to export your someFunction to another exports
then use new function, you need to do like this.
// another.js
const { someFunction } = require("./index.js")
exports.exportedFunction = someFunction
// router.js
const { exportedFunction } = require("./another.js")
exportedFunction() // it will work

Change nodejs route with params at runtime

I need to change a route params at runtime in nodejs.
In my code I set a route using:
const troutes = require('./src/routes/testroutes')(page,sessionId)
app.use('/teste' + sessionId, troutes)
But, in runtime, sometimes the "page" object param is recreated and it becomes invalid. But the "sessionId" param is the same, no changes.
Then I create a new "page" and need remake the route, because the old route has a invalid page.
if I use:
let page={newpage};
const troutes = require('./src/routes/testroutes')(page,sessionId);
My urls donĀ“t work because the route use the old invalid "page" param object.
How could I delete or change the old route and use the new route with the new "page" object?
//server.js
const express = require('express')
const app = express()
const server = require('http').Server(app)
const port = 3001
const host = 'http://localhost'
const callbackUrl = `${host}:${port}`;
let page={page};
let sessionId='sessionId';
const troutes = require('./src/routes/testroutes')(page,sessionId)
app.use('/teste' + sessionId, troutes)
....
});
//routes.js
const express = require('express');
const router = express.Router();
module.exports = function (page,sessionId) {
router.get('/'+sessionId+'/getMyNumber', async (req, res) => {
const cc = await page.evaluate(() => {
return getMyNumber();
});
console.log(cc);
res.send({ "data": cc });
});
return router;
}
since you called require('./src/routes/testroutes')(page,sessionId) method only once in file, it loads only once. so passed parameters/initializations within function executed only once.
the router which is initialized and returned is used for further request processing.So new request will only trigger method of router.
if you want page to be dynamic, it would work if you move page inside router, instead of passing it from wrapper function as below.
const express = require('express');
const router = express.Router();
module.exports = function (sessionId) {
router.get('/'+sessionId+'/getMyNumber', async (req, res) => {
let page = {newPage}
const cc = await page.evaluate(() => {
return getMyNumber();
});
console.log(cc);
res.send({ "data": cc });
});
return router;
}

TypeError: Model is not a Constructor

Making a MongoDB call from a react component on Form Submit with Mongoose throws an error - TypeError: Group is not a constructor at below line
let group1 = new Group
I have a server file inside which I initialize the connection.
server.js
const mongoose = require('mongoose');
mongoose.connect('dbName',{ useNewUrlParser: true });
mongoose.connection.once('open',() =>{
console.log('connected to the database');
});
Then there is a model file called group.js
const mongoose = require('mongoose');
var groupSchema = new mongoose.Schema({
groupName: String
});
module.exports = mongoose.model('Group',groupSchema);
Component CreateNew
const Group = require('../models/group');
class CreateNew extends Component {
// code here
render()
// code here
<Form onSubmit = {e => {
let group1 = new Group({
groupName: 'My Group'
});
group1.save(function(err,group1){
if (err) return console.log(err);
console.log('mongo success');
});
}}>
When I put all the code in one place like this inside the server.js file then the code works and I can see the data in Mongo.
If I just shift the code from inside Form's onSubmit to before the 'class CreateNew extends Component' line just for testing then it throws following error
Cannot overwrite Group model once compiled.
at this line
module.exports = mongoose.model('Group',groupSchema);
I'll show you a short overview of the project, which includes frontend and backend.
BACKEND
1.1 server.js
const express = require('express');
const app = express();
const port = process.env.PORT || 80;
const http = require('http').Server(app);
const mongoose = require('mongoose');
const routes = require(path_to_api.js)(router);
app.use('/myApi', routes)
//***Here you should implement more details about your project such as routes, body parsers and other middlewares*****//
mongoose.connect('mongodb://localhost:27017/your-app-name', err => err?console.log(err):console.log('Successfully connected to MongoDB'));
http.listen(port, ()=> console.log(`Server running on ${port}`))
1.2 Model, group.js
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
let groupSchema = new Schema({
groupName: {
type: String
}
});
module.exports = mongoose.model('Group',groupSchema);
1.3 api.js (Still backend!!!)
const Group = require(path_to_group.js);
module.exports = router => {
router.post('/group', (req, res)=> {
let group = new Group();
group.groupName = req.body.groupName;
//Save in database
group.save(function(err){
...
})
}
return router
}
FRONTEND
2.1 Ajax calls (service.js)
function group(data){
return fetch('/api/authenticate',{
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-type': 'application/json'
},
body: JSON.stringify(data)
}).then(response => response.json()).then(data => {
return data //Server response
})
}
export {group}
2.2 React Component
import {group} from //service.js path
class CreateNew extends Component {
constructor(props, context){
this.sendGroupName = this.sendGroupName.bind(this);
}
this.sendGroupName(){
let data = //data received from form after submit
//It is the most important part from the frontend - sending data to the server
group(data).then(res => {
//do somenthing with servers response
}
}
render(){
<Form onSubmit={this.sendGroupName}>
//Form content such as inputs, labels...
<Form/>
}
That is my quickly explanation concerning MEAN projects. I hpe it will be useful for you.

Ways to export module

Imagine this code:
var authenticate = (req, res, next) => {
...
};
Can I export the above code like these?
module.exports = {authenticate}; or module.exports = authenticate;
Can I import above code like these?
var {authenticate} = require('./middleware/authenticate'); or var authenticate = require('./middleware/authenticate');
This should solve all your troubles: https://flaviocopes.com/commonjs/
exporting value:
autheticate.js
module.exports = authenticate;
other-file.js
const authenticate = require('./autheticate.js')
or exporting object
autheticate.js
module.exports = {authenticate};
other-file.js
const {authenticate} = require('./autheticate.js')

Variable does not return desired object

I am building an Express app. I currently have an error in the following file, factoryRepository.js
let appReference = null;
module.exports.init = (app) => {
appReference = app;
};
module.exports.getRepositoryFactory = () => {
let repositoryFactory = {
getUserRepository: () => {
return require("./UserRepository").init(appReference.get('models').User);
}
};
return repositoryFactory;
};
appReference.get throws a TypeError because appReference is still null even after I have called module.exports.init somewhere else.
I have tried to make a function that returns appReference so I can see in what state it is. I have been able to get app rather than null, it is only in the context of getUserRepository that it stays null.
The faulty line is only called when I ping a certain route.
EDIT:
This is app.js, the context from which module.exports.init is being called
import express from 'express';
import passport from 'passport';
import config from './config/config';
let app = express();
// Setup models
app.set('models', require('./app/models'));
require('./app/repo/repositoryFactory').init(app);
// Setup config
require('./config/init')(app);
// Setup routes
require('./app/routes')(app, passport);
// Setup passport
require('./app/auth')(passport, config);
// Route to ends
require('./config/endpoints')(app);
export default app;
public.js is the logic given to my router, and it is here where I call the faulty code with repositoryFactory.getUserRepository()
let repositoryFactory = require('../repo/RepositoryFactory').getRepositoryFactory();
module.exports.doLogin = (req, res) => {
let success = () => {
res.redirect('/');
};
let error = (message) => {
res.status(500).json(message);
};
let userRepository = repositoryFactory.getUserRepository();
userRepository.findOrCreate({
facebookId: req.user.id,
displayName: req.user.displayName
}, success, error);
};
module.exports.doLogout = (req, res) => {
req.logout();
res.json({
success: true,
message: 'You\'ve succesfully logged out.'
});
};
This looks like a scope issue. Let's say we simplify your three files as follows, and also put them all in the same directory (for simplicity here):
app.js:
'use strict';
const express = require('express');
let app = express();
require('./repositoryFactory').init(app);
const myPublic = require('./public');
repositoryFactory.js:
'use strict';
let appReference = null;
module.exports.init = (app) => {
appReference = app;
};
module.exports.getRepositoryFactory = () => {
return appReference ? 'I have an app reference!' : 'No app reference!';
};
public.js:
'use strict';
let repositoryFactory = require('./RepositoryFactory').getRepositoryFactory();
console.log(repositoryFactory);
This is going to log No app reference! because the repositoryFactory is not a singleton. The repositoryFactory instance in app.js is a different instance than the repositoryFactory instance in public.js.
One solution would be to pass a parameter for the repositoryFactory instance. repositoryFactory.js would be unchanged, but app.js might look like this:
'use strict';
const express = require('express');
let app = express();
const repositoryFactory = require('./repositoryFactory')
repositoryFactory.init(app);
const myPublic = require('./public');
myPublic.init(repositoryFactory);
myPublic.log();
And the corresponding public.js might look like this:
'use strict';
let repositoryFactory = null;
module.exports.init = (myRepositoryFactory) => {
repositoryFactory = myRepositoryFactory.getRepositoryFactory();
}
module.exports.log = () => {
console.log(repositoryFactory);
}

Categories