Persistent object in node.js - javascript

I am fairly new to node and backend work in general. We are using express at work for a pretty large monolith application that houses all of our endpoints and services. My task is to grab a property that comes in on the request object (i.e. request.someObject), and use it in several services. In a DOM environment I would use something like localStorage or sessionStorage to store that data, and then reuse it where needed across the application. Im going to try and explain a little further with code:
Endpoint
router.route('/:cartId/generatePaymentLink')
.post(jsonParser, urlParser, function(request, response, next) {
var theObject = request.someObject;
// need to pass theObject to several services
});
Services are stored within separate files, here is an example of one
var paypalInfo = new Paypal({
userId: theObject.user_id,
password: theObject.password
});
I can pass it through parameters to the services that use data, but its used in several different places and would have to be defined in those individual services. Is there a way to create a persistent object/config file that I can just import and have that data, or something like sessionStorage in the DOM?
EDIT: Not a database, looking for another solution. For performance reasons we are avoiding this

Related

How to share a single instance of an object among multiple actions?

I have a React/Redux application that talks alot to an API and deals with a lot of rarely changing data from a DB. In order to reduce traffic and improve UE, I now want to create a caching mechanism that stores data on the client by automatically using the best technology that is available (descending from IndexedDB to LocalStorage etc.).
I created a cache object that does an initial check which determines the storage mechanism (which gets saved to an engine property, so the check just needs to run once). It also has some basic methods save(key, value) and load(key), which then call the appropriate functions for the initially determined mechanism.
The cache object and its methods do work, but I wonder how to create the cache in my main index.js only once when the application loads, and then use this very object in my actions without recreating another cache object every time?
BTW: It feels wrong to make the cache part of my application state as it does not really contain substantial data to run the application (if there is no caching available, it falls back to just calling the API).
Do I need to inject the cache into my actions somehow? Or do I need to create a global/static cache object in the main window object?
Thanks for clarification and thoughts on this issue.
redux-thunk middleware offers a custom argument injection feature you could use.
When creating the store
const cache = createCache()
const store = createStore(
reducer,
applyMiddleware(thunk.withExtraArgument(cache))
)
Then in your action creator
function getValue(id) {
return (dispatch, getState, cache) => {
// use cache
}
}

Torii provider name from adapter?

I have a Torii adapter that is posting my e.g. Facebook and Twitter authorization tokens back to my API to establish sessions. In the open() method of my adapter, I'd like to know the name of the provider to write some logic around how to handle the different types of providers. For example:
// app/torii-adapters/application.js
export default Ember.Object.extend({
open(authorization) {
if (this.provider.name === 'facebook-connect') {
var provider = 'facebook';
// Facebook specific logic
var data = { ... };
}
else if (this.provider.name === 'twitter-oauth2') {
var provider = 'twitter';
// Twitter specific logic
var data = { ... };
}
else {
throw new Error(`Unable to handle unknown provider: ${this.provider.name}`);
}
return POST(`/api/auth/${provider}`, data);
}
}
But, of course, this.provider.name is not correct. Is there a way to get the name of the provider used from inside an adapter method? Thanks in advance.
UPDATE: I think there are a couple ways to do it. The first way would be to set the provider name in localStorage (or sessionStorage) before calling open(), and then use that value in the above logic. For example:
localStorage.setItem('providerName', 'facebook-connect');
this.get('session').open('facebook-connect');
// later ...
const providerName = localStorage.getItem('providerName');
if (providerName === 'facebook-connect') {
// ...
}
Another way is to create separate adapters for the different providers. There is code in Torii to look for e.g. app-name/torii-adapters/facebook-connect.js before falling back on app-name/torii-adapters/application.js. I'll put my provider-specific logic in separate files and that will do the trick. However, I have common logic for storing, fetching, and closing the session, so I'm not sure where to put that now.
UPDATE 2: Torii has trouble finding the different adapters under torii-adapters (e.g. facebook-connect.js, twitter-oauth2.js). I was attempting to create a parent class for all my adapters that would contain the common functionality. Back to the drawing board...
UPDATE 3: As #Brou points out, and as I learned talking to the Torii team, fetching and closing the session can be done—regardless of the provider—in a common application adapter (app-name/torii-adapters/application.js) file. If you need provider-specific session-opening logic, you can have multiple additional adapters (e.g. app-name/torii-adapters/facebook-oauth2.js) that may subclass the application adapter (or not).
Regarding the session lifecycle in Torii: https://github.com/Vestorly/torii/issues/219
Regarding the multiple adapters pattern: https://github.com/Vestorly/torii/issues/221
Regarding the new authenticatedRoute() DSL and auto-sesssion-fetching in Torii 0.6.0: https://github.com/Vestorly/torii/issues/222
UPDATE 4: I've written up my findings and solution on my personal web site. It encapsulates some of the ideas from my original post, from #brou, and other sources. Please let me know in the comments if you have any questions. Thank you.
I'm not an expert, but I've studied simple-auth and torii twice in the last weeks. First, I realized that I needed to level up on too many things at the same time, and ended up delaying my login feature. Today, I'm back on this work for a week.
My question is: What is your specific logic about?
I am also implementing provider-agnostic processing AND later common processing.
This is the process I start implementing:
User authentication.
Basically, calling torii default providers to get that OAuth2 token.
User info retrieval.
Getting canonical information from FB/GG/LI APIs, in order to create as few sessions as possible for a single user across different providers. This is thus API-agnotic.
➜ I'd then do: custom sub-providers calling this._super(), then doing this retrieval.
User session fetching or session updates via my API.
Using the previous canonical user info. This should then be the same for any provider.
➜ I'd then do: a single (application.js) torii adapter.
User session persistence against page refresh.
Theoretically, using simple-auth's session implementation is enough.
Maybe the only difference between our works is that I don't need any authorizer for the moment as my back-end is not yet secured (I still run local).
We can keep in touch about our respective progress: this is my week task, so don't hesitate!
I'm working with ember 1.13.
Hope it helped,
Enjoy coding! 8-)

How should I manage in-memory data in Node?

I have a simple app built using Node, Express, and Socket.io on the server side. My page queries my API when it needs to retrieve data that will not change, and uses WebSockets for getting live updates from the server for dynamic data. The app allows a single person, the "Supervisor", to send questions to any number of "Users" (unauthenticated) and view their answers as they trickle in. The Users send their data to the server using a POST request, and it is streamed to the Supervisor over a WebSocket. The server stores user data in a simple array, and uses an ES6 map of the items in the array (users) to objects containing each their questions and answers, like this:
class User {}
let users = [], qa = new Map();
io.on('connection', socket => {
let user = new User(socket.id);
users.push(user);
qa.set(user, {});
socket.on('question-answered', ({id, answer}) => {
let questionData = qa.get(user);
questionData[id] = answer;
qa.set(user, questionData);
});
});
This is obviously a very primitive way of handling data, but I don't see the need for additional complexity. The data doesn't need to persist across server crashes or restarts (the user's questions and answers are also stored in localStorage), and MongoDB and even Redis just seem like overkill for this kind of data.
So my question is, am I going about this the right way? Are there any points I'm missing? I just want a simple way to store data in memory and be able to access it through client-side GET requests and socket.io. Thank you for any help.
If an array and a map provide you the type of access you need to the data and you don't need crash persistence and you have an appropriate amount of memory to hold the amount of data, then you're done.
There is no need for more than that unless your needs (query, persistence, performance, multi-user, crash recovery, backup, etc...) require something more complicated. A simple cliche applies here: If it ain't broke, it don't need fixing.

Singe Page Application External Configurations (Not On NodeJS)

I'm looking for either a reference or an answer to what I think is a very common problem that people who are current implementing JavaScript MVC frameworks (such as Angular, Ember or Backbone) would come across.
I am looking for a way or common pattern to externalize application properties that are accessible in the JS realm. Something that would allow the javascript to load server side properties such as endpoints, salts, etc. that are external to the application root. The issue that I'm coming across is that browsers do not typically have access to the file systems because it is a security concerns.
Therefore, what is the recommended approach for loading properties that are configurable outside of a deployable artifact if such a thing exists?
If not, what is currently being used or is in practice that is considered the recommended approach for this types of problem?
I am looking for a cross compatible answer (Google Chrome is awesome, I agree).
Data Driven Local Storage Pattern
Just came up with that!!
The idea is to load the configuration properties based on a naming over convention configuration where all properties are derived from the targeted hostname. That is, the hostname will derive a trusted endpoint and that endpoint will load the corresponding properties to the application. These application properties will contain information that is relative at runtime. The runtime information will be supplied to the integration parts which then communicate via property iteration on the bootstrapping start up.
To keep it simple, we'll just use two properties here:
This implementation is Ember JS specific but the general idea should be portable
I am currently narrowing the scope of this question to a specific technological perspective, that is Ember JS with the following remedy that is working properly for me and hope it will help any of you out there dealing with the same issue.
Ember.Application.initializer implementation in start up
initialize: function (container, application) {
var origin = window.location.origin;
var host = window.location.hostname;
var port = window.location.port;
var configurationEndPoint = '';
//local mode
if(host === 'localhost'){
//standalone using api stub on NODEJS
if(port === '8000'){
configurationEndPoint = '/api/local';
}//standalone UI app integrating with back end application on same machine, different port
else{
configurationEndPoint = '/services/env';
}
origin += configurationEndPoint;
}else{
throw Error('Unsupported Environment!!');
}
//load the configuration from a trusted resource and store it in local storage on start up
$.get(origin,
function( data ) {
//load all configurations as key value pairs and store in localStorage for access.
configuration = data.configuration;
for(var config in configuration){
debugger;
var objectProperty = localStorage + '.' + config.toString()
objectProperty = configuration[config];
}
}
);
}
Configurable Adapter
export default DS.RESTAdapter.extend({
host: localStorage.host,
namespace: localStorage.namespace
});
No later than yesterday morning i was tackling the same issue.
Basically, you have two options:
Use localStorage/indexedDB or any other client-side persistent storage. (But you have to put config there somehow).
Render your main template (the one that gets rendered always) with a hidden where you put config JSON.
Then in your app init code you get this config and use it. Plain and simple in theory, but lets get down to nasty practice (for second option).
First, client should get config before application loads. It is not easy sometimes. e.g. user should be logged in to see config. In my case i check if i can provide config on the first request, and if not redirect user to login page. This leads us to second limitation. Once you are ready to provide config, you have to reboot app completely so that configuration code run again (at least in Angular it is necessary, as you cannot access providers after the app bootstraps).
Another constraint, the second option is useless if you use static html and cannot change it somehow on server before sending to the client.
May be a better option would be to combine both variants. This should solve some problems for returning users, but first interaction will not be very pleasant anyway. I have not tried this yet.

processing data for templates in express/node

I'm developing extension to an existing app using expressjs. By requirements I need to do server side rendering. Our API server is running on JAVA.
In my express app, I'm going to have to render page while making serverside calls to JAVA server. For example, I'm going to call getCategories, getVendors, getReviews etc APIs in order get data that I need to pass to rendering template.
What is a good way to accomplish this? I mean pack all of that into a single object and pass to res.render() method. Could you please provide me with some basic examples? I imagine that I would need to create a module that does all of this and returns some nice object...
All of the examples on the internet show something like res.render('index', { data: 'someData'}), however in this case data is bootstrapped. I would need a data to be compiled with several API calls and then passed to the rendering method.
Thanks!
It really depends on whether you want to call your Java API server side or client side.
If server side, your express route containing res.render() will need to collect all the information it needs from Java before rendering the page. If your API is slow, the page load will be slow. If possible, use something like async.parallel to avoid blocking.
Your code sample is correct. res.render('index', { foo: 'bar'})
This would add the foo variable to the root scope of your view. How you build up the data structure is entirely up to you. I would recommend using async.parallel and/or async.series to collate all of the data. If they are all completely independent, run them in parallel.
// an example of how to run each in parallel and then render the view.
var getCategories = function(done) {
// get something
done();
};
var data = {};
async.parallel([
getCategories, // <-- adds to the data structure
getVendors,
getReviews
], function(err) {
res.render('index', { data: data });
});
Your other option is using express to render the base page and using something like jQuery to hit the Java API and update the relevant page fragments.

Categories

Resources