Re Initialization express Application - node.js

I have node.js application, which was built on express.js framework.
const app = express();
require('./config')(app);
require('./services')(app);
./config/config.js we instantiate config:
module.exports = function (app) {
const conf = {APIKey: 1234567890, url: '<someurl>'};
app.set('config', conf);
};
./services/APIService.js we create service instance(singleton)
module.exports = (app) => {
app.set('apiService', new APIService(app));
};
function APIService(app) {
const config = app.get('config');
this.key = config.APIKey;
};
APIService.prototype.sendRequest = () => {
const config = app.get('config');
this._send(config.url, 'some text');
};
Or, service2
module.exports = function(app) {
const config = app.get('config');
const myMod = require('myMod')(config.APIKey);
}
Cool, all works correct. But sometime administrator will change some config data. So, we create new config, set him to
newConf = {APIKey: 1234000000, url: '<some_new_url>'};
app.set('config', newConf);
APIService.sendRequest, will send request to CHANGED url, but APIService.key still unchanged. And myMod already instantiated with old config data.
We need write some setter methods, like this
//for APIService
APIService.prototype.setConfig = () => {
const config = app.get('config');
this.key = config.APIKey;
};
//for service 2
/* change const myMod to let myMod and create method for overriding */
or bang! kill and restart node.js server process. Bad idea. Maybe exist some method for this goal, something like app.restart() for safely reinitializing application(or, maybe, his parts)?

Did you try to call app.set('apiService', new APIService(app)); again ? or just have getter and setter on the prototype for your params.
Better way should be to have a new APIService object at each new request with a middleware, somehting like :
app.use(function (req, res, next){
req.api = new APIService(app);
next();
});
And use req.api.

Related

pass variable to nodesjs to localhost

I want to pass the variable "valor_dollar" into the server localhost or an file html. Actually I can not to look the variable the browser.
const express = require ('express');
const cheerio = require ('cheerio')
const request = require ('request-promise')
const axios = require('axios')
const app = express();
app.get('/',(req,res) => {
res.end(prova());
});
app.listen(3000);
function prova(){
axios.get('https://www.morningstar.es/es/funds/snapshot/snapshot.aspx?id=F0GBR04ASX').then((response) => {
// Load the web page source code into a cheerio instance
const $ = cheerio.load(response.data)
// The pre.highlight.shell CSS selector matches all `pre` elements
// that have both the `highlight` and `shell` class
const urlElems = $('td.line.text')[0]
const urlText = $(urlElems).text()
let valor_dollar = Number(urlText.substring(4,7))
console.log(valor_dollar)
})
}
You are calling res.end method directly without setting the body, the prova function returns undefined.
Instead you can modify your method like this to have a callback that runs after the HTTP call.
function prova(callback){
axios.get('https://www.morningstar.es/es/funds/snapshot/snapshot.aspx?id=F0GBR04ASX').then((response) => {
// Load the web page source code into a cheerio instance
const $ = cheerio.load(response.data)
// The pre.highlight.shell CSS selector matches all `pre` elements
// that have both the `highlight` and `shell` class
const urlElems = $('td.line.text')[0]
const urlText = $(urlElems).text()
let valor_dollar = Number(urlText.substring(4,7))
callback(valor_dollar);
});
}
and the route should be like this:
app.get('/',(req,res) => {
prova(function(value) {
res.body = { dollar_value: value };
res.end();
});
});

Loopback app.models.ModelName is undefined

Below code is accessing one model from another model, which returns undefined
var app = require('../../server/server');
module.exports = function(Regions) {
const Media = app.models.Media;
console.log( Media) // Returns Undefined
}
And I have tried below also, but same error
module.exports = function(Regions) {
console.log( Regions.app.models.Media) // Returns Undefined
}
Have you tried accessing your model like so:
require('loopback').getModel('Regions')
This is the way:
module.exports = function (Region) {
let app
Region.beforeRemote('find', function (ctx, unused, next) {
// Do something
next()
})
Region.on('attached', function (a) {
app = a
})
}
You can also create a boot script if you want to perform actions across models at boot time:
Is your sample code correctly located in common/models/regions.js?
Here is some other snippet for you:
'use strict';
var app = require('../../server/server');
var models = app.models;
var Media;
app.on('started', function () {
Media = models.Media;
});
module.exports = function (Regions) {
...
}

Custom service in feathersjs

I try to write a custom service, but it doesn't work at all. I try to post a request and make two update queries in the collections, but i will not work at all
this is my code
// Initializes the `bedrijven` service on path `/bedrijven`
const createService = require('feathers-mongoose');
const createModel = require('../../models/bedrijven.model');
const hooks = require('./bedrijven.hooks');
const filters = require('./bedrijven.filters');
module.exports = function() {
const app = this;
const Model = createModel(app);
const paginate = app.get('paginate');
const options = {
name: 'bedrijven',
Model,
paginate
};
// Initialize our service with any options it requires
app.post('/bedrijven/setfavo', function(req, res) {
Promise.all([
app.service('bedrijven').update({
owner: req.body.userid
}, {
favo: false
}),
app.service('bedrijven').update(req.body._id, {
favo: true
})
]);
});
app.use('/bedrijven', createService(options));
// Get our initialized service so that we can register hooks and filters
const service = app.service('bedrijven');
service.hooks(hooks);
if (service.filter) {
service.filter(filters);
}
};
Make sure this file is included in your main app.js file.
Something like:
const bedrijven = require('./bedrijven/bedrijven.service.js');
app.configure(bedrijven);
Is there a reason you don't want to use feathers generate service? It would take care of these questions for you.

NodeJS- ReferenceError: wagner is not defined

I don't have experience at all with nodejs and I am learning. I have a code, which I am testing and giving me the following errors, and I don't understand why:
1) Part 3 Assessment Tests "before all" hook:
ReferenceError: wagner is not defined
at Object. (fx.js:2:31)
at Object. (dependencies.js:3:10)
at Context. (test.js:29:20)
2) Part 3 Assessment Tests "after all" hook:
TypeError: Cannot read property 'close' of undefined
at Context. (test.js:65:11)
These are the programs involved in the issue:
test.js --------------
var assert = require('assert');
var express = require('express');
var fs = require('fs');
var status = require('http-status');
var superagent = require('superagent');
var wagner = require('wagner-core');
var URL_ROOT = 'http://localhost:3000';
var PRODUCT_ID = '000000000000000000000001';
describe('Part 3 Assessment Tests', function() {
var server;
var app;
var succeeded = 0;
var finalCharge;
var Category;
var Config;
var fx;
var Product;
var Stripe;
var User;
before(function() {
app = express();
// Bootstrap server
models = require('./models')(wagner);
dependencies = require('./dependencies')(wagner);
// Make models available in tests
var deps = wagner.invoke(function(Category, fx, Product, Stripe, User, Config) {
return {
Category: Category,
fx: fx,
Product: Product,
Stripe: Stripe,
User: User,
Config: Config
};
});
...
dependencies.js -------------
var wagner = require('wagner-core');
var fs = require('fs');
var fx = require('./fx')(wagner);
var Stripe = require('stripe');
module.exports = function(wagner) {
var stripe =
// TODO: Make Stripe depend on the Config service and use its `stripeKey`
// property to get the Stripe API key.
wagner.factory('Stripe', function() {
return Stripe(Config.stripeKey);
});
wagner.factory('fx', fx);
wagner.factory('Config', function() {
return JSON.parse(fs.readFileSync('./config.json').toString());
});
var Config = wagner.invoke(function(Config) {
return Config;
});
};
fx.js --------------------------
var superagent = require('superagent');
var _ = require('underscore')(wagner);
module.exports = function(Config) {
...
};
I think I shouldn't have any problem because wagner is defined on test.js and passed as parameter to dependencies.js, and it is passing it on to fx.js.
1- Could you tell me what is wrong in the code ?
2- The second error, I have not cue why is it happening.
Please, help
In your dependencies.js, in the fx definition, you dont need to pass wagner as parameter, because that variable doesnt exist there:
var fx = require('./fx');
As i see, you already defined the Config factory, and you dont need to assign it to a variable for use it, because wagner will autoinject your "Config" factory, allowing you access to it:
wagner.factory('Stripe', function(Config) {
return Stripe(Config.stripeKey);
});
...
wagner.factory('Config', function() {
return JSON.parse(fs.readFileSync('./config.json').toString());
});
Then in your fx.js, when you wanna use the Config parameter you just pass it:
module.exports = function(Config) {
var url = 'http://openexchangerates.org/api/latest.json?app_id=' +
Config.openExchangeRatesKey;
...
}
Exactly the same you should do if you wanna use the "Config" factory in any other file:
[auth.js]
function setupAuth(User, Config, app) {
...
}
You're trying to use wagner in fx.js before you execute the exported function and outside of the scope that wagner is passed to. Also, Config seems a bit misleading if you're passing wagner to that function instead.
If you can defer loading underscore, you could do something like:
var superagent = require('superagent');
var _;
module.exports = function(Config) {
if (!_)
_ = require('underscore')(Config);
// ...
};

Routing in Express.js - dynamic number of parameters

I've a concept for create routing with multiple parameters when numbers of it are dynamic, for example:
/v2/ModuleName/Method/Method2/
In Express I want parse it as: Modules.v2.ModuleName.Method.Method2(). When will be just one method, this should be of course Modules.v2.ModuleName.Method(). It's possible to do that?
You can split pathname then lookup the method from your Modules object like this:
// fields = ['v2', 'ModuleName', 'Method', 'Method2']
var method = Modules;
fields.forEach(function (field) {
method = method[field];
})
// call method
console.log(method());
Full code:
var express = require('express'), url = require('url');
var app = express();
Modules = {
method: function () { return 'I am root'},
v2: {
method: function () { return 'I am v2';}
}
};
app.get('/callmethod/*', function (req, res) {
var path = url.parse(req.url).pathname;
// split and remove empty element;
path = path.split('/').filter(function (e) {
return e.length > 0;
});
// remove the first component 'callmethod'
path = path.slice(1);
// lookup method in Modules:
var method = Modules;
path.forEach(function (field) {
method = method[field];
})
console.log(method());
res.send(method());
});
app.listen(3000);
Test on browser:
http://example.com:3000/callmethod/method
"I am root"
http://example.com:3000/callmethod/v2/method
"I am v2"
PS: you can improve this app to support pass params to a method via url:
http://example.com:3000/callmethod/v2/method?param1=hello&param2=word

Resources