Get all defined variables in scope in node.js - node.js

I am trying to get all the variables that have been defined, i tried using the global object
but it seems to be missing the ones defined as var token='44'; and only includes the ones defined as token='44';. What i am looking for idealy is something like the get_defined_vars() function of php. I need to access the variables because i need to stop the node process and then restart at the same point without having to recalculate all the variables, so i want to dump them somewhere and access them later.

It's impossible within the language itself.
However:
1. If you have an access to the entire source code, you can use some library to get a list of global variables like this:
var ast = require('uglify-js').parse(source)
ast.figure_out_scope()
console.log(ast.globals).map(function (node, name) {
return name
})
2. If you can connect to node.js/v8 debugger, you can get a list of local variables as well, see _debugger.js source code in node.js project.

As you stated
I want to dump them somewhere and access them later.
It seems like you should work towards a database (as Jonathan mentioned in the comments), but if this is a one off thing you can use JSON files to store values. You can then require the JSON file back into your script and Node will handle the rest.
I wouldn't recommend this, but basically create a variable that will hold all the data / variables that you define. Some might call this a God Object. Just make sure that before you exit the script, export the values to a JSON file. If you're worried about your application crashing, perform backups to that file more frequently.
Here is a demo you can play around with:
var fs = require('fs');
var globalData = loadData();
function loadData() {
try { return require('./globals.json'); } catch(e) {}
return {};
}
function dumpGlobalData(callback) {
fs.writeFile(
__dirname + '/globals.json', JSON.stringify(globalData), callback);
}
function randomToken() {
globalData.token = parseInt(Math.random() * 1000, 10);
}
console.log('token was', globalData.token)
randomToken();
console.log('token is now', globalData.token)
dumpGlobalData(function(error) {
process.exit(error ? 1 : 0);
});

Related

Is it possible to get all variables in scope through typescript?

I know there is an old post about this functionality in javascript: Getting All Variables In Scope
But I am desperately looking and thought I'd just ask in case there might be transpile magic in typescript (or a way we can extend it) that may acheve this..(e.g.)
.ts
() => {
const a = 123;
console.log(scope)
}
.js transpile
var scope = {};
() => {
scope.a = 123;
console.log(scope);
}
The reason I'm asking is that I'm looking for a node backend solution to be able to log a function's scope state and save it in a debug database for review. (So any time an error occurs the state is never lost but recorded instead)
#k0pernikus
Getting specific on my issue, I'm trying to get more context on what went wrong with my handler for a firebase event. functions.firestore.document('users/{uid}').onUpdate
// ====== Pretend code I wish would work =====
const logScopeSomewhere = (anonymousScope) => (err) => {
console.log(anonymousScope) // { pie: 'pie', apple: 'apple' }
// or write error to database..
// Main goal is that all variables in the function that errored are logged with the Type Error..
}
const handleUpdate = (change: Change<QueryDocumentSnapshot>, context: EventContext) => {
let anonymousScope;
return (async () => {
anonymousScope = scope; // special reserved - // Possible JS transpile manipulation can have a closure on top..
const pie = 'pie'; // anonymousScope.pie
const apple = 'apple'; // anonymousScope.apple
// apple.core.seed - // TypeError (will go to catch..)
})().catch(logScopeSomewhere(anonymousScope))
}
functions.firestore.document('users/{uid}').onUpdate(handleUpdate)
Trying to be more clear, I want to have an object that has a snapshot of the state of the executing function when the error occurred. I plan to catch it and will use it as logging information.
I don't think V8 exposes scope information in any other way than through DevTools.
You can parse your own source code, which lets you do any analysis you want. See this answer to the old question you linked for an example.
The TypeScript compiler must be doing the same analysis already internally, so I'm pretty sure it could be extended to dump that information. For example, it should be possible to extend the TypeScript language with a scope keyword (or whatever) that gets compiled to a JS object containing all in-scope variables and their values. That said, I have no idea whether something like that already exists, or how one would go about adding it.

Require a file once and use it everywhere

I've read up on module.exports and how it works but I'm not sure if I can accomplish what I want with it - or at least I'm not sure how to. I have some helper functions in a file, one of which is used in a majority of files in my project. I'm wondering if it is possible to just "require" the file one time and then just use it across the entirety of the project when needed.
My file looks something like this:
discord-utils.js
const { MessageEmbed, Permissions } = require('discord.js')
module.exports = {
embedResponse (message, embedOptions, textChannel = null) {
const embed = new MessageEmbed()
if (embedOptions.color) embed.setColor(embedOptions.color)
if (embedOptions.title) embed.setTitle(embedOptions.title)
if (embedOptions.description) embed.setDescription(embedOptions.description)
if (embedOptions.url) embed.setURL(embedOptions.url)
if (embedOptions.author) embed.setAuthor(embedOptions.author)
if (embedOptions.footer) embed.setFooter(embedOptions.footer)
if (embedOptions.fields) {
for (const field of embedOptions.fields) {
embed.addFields({
name: field.name,
value: field.value,
inline: field.inline ? field.inline : false
})
}
}
if (textChannel) {
textChannel.send(embed)
return
}
message.embed(embed)
},
inVoiceChannel (voiceState, message, response = null) {
if (!voiceState.channel) {
this.embedResponse(message, {
color: 'RED',
description: response === null ? 'You need to be in a voice channel to use this command.' : response
})
console.warn(`${message.author.tag} attempted to run a music command without being in a voice channel.`)
return false
}
return true
},
isAdminOrHasPerms (user, permissionRole) {
return user.hasPermisssion(Permissions.FLAGS.ADMINISTRATOR) || user.hasPermission(permissionRole)
}
}
In pretty much every other file, I use the embedResponse function. So in the project I have to do require('discord-utils) and then do things like: discordUtils.embedResponse(blahblah...) and while that's fine, it seems really redundant since I know I'm going to be using it just about everywhere. I'm wondering if there's a way I can just use one require statement and pull the functions I need at any time?
You may define a globally accessible variable using the global object in NodeJS. However, this neither a common nor a recommended pattern in NodeJS.
global.foo = 1 // make the foo variable globally accessible
https://nodejs.org/api/globals.html#globals_global
Node.js actually has a neat little caching system that can be taken advantage of to achieve a singleton effect. The first time you require a file, it runs and sets module.exports. Every time you require that same file afterwards, it will return a reference to the same object that was returned the fist time, instead of actually re-executing.
There are some caveats though. It's not always a guarantee that the file won't execute a second time. For example sometimes if you require the file from a very different location far from the first one, it might re-execute the file. Like if you first required the file as require('./my-file') and later require it with require('../../../../my-file'), it could sometimes re-execute it and clear the cached reference.

Is it considered bad practice to manipulate a queried database document before sending to the client in Mongoose?

So I spent too long trying to figure out how to manipulate a returned database document (using mongoose) using transform and virtuals, but for my purposes, those aren't options. The behaviour I desire is very similar to that of a transform (in which I delete a property), but I only want to delete the property from the returned document IFF it satisfies a requirement calculated using the req.session.user/req.user object (I'm using PassportJS, but any equivalent session user suffices). Obviously, there is no access to the request object in a virtual or transform, and so I can't do the calculation.
Then it dawned on me that I could just query normally and manipulate the returned object in the callback before I send it to the client. And I could put it in a middleware function that looks nice, but something tells me this is a hacky thing to do. I'm presenting an api to the client that does not reflect the data stored/retrieved directly from the database. It may also clutter up my route configuration if I have middleware like this all over making it harder to maintain code. Below is an example of what the manipulation looks like:
app.route('/api/items/:id').get(manipulateItem, sendItem);
app.param('id', findUniqueItem);
function findUniqueItem(req, res, next, id) {
Item.findUniqueById(id, function(err, item) {
if (!err) { req.itemFound = item; }
next();
}
}
function manipulateItem(req, res, next) {
if (req.itemFound.people.indexOf(req.user) === -1) {
req.itemFound.userIsInPeopleArray = false;
} else {
req.itemFound.userIsInPeopleArray = true;
}
delete req.itemFound.people;
}
function sendItem(req, res, next) {
res.json(req.itemFound);
}
I feel like this is a workaround to a problem with a simpler solution, but I'm not sure what that solution is.
There's nothing hacky about the act of modifying it.
It's all a matter of when you modify it.
For toy servers, and learning projects, the answer is whenever you want.
In production environments, you want to do your transform on your way out of your system, and into the next system (the next system might be the end user; it might be another server; it might be another big block of functionality in your own server, that shouldn't have access to more information that it needs to do its job).
getItemsFromSomewhere()
.then(transformToTypeICanUse)
.then(filterBasedOnMyExpectations)
.then(doOperations)
.then(transformToTypeIPromisedYou)
.then(outputToNextSystem);
That example might not be super-helpful in terms of an actual how, but that's sort of the point.
As you can see, you could link that system of events up to another system of events (that does its own transform to its own data-structure, does its own filtering/mapping, transforms that data into whatever its API promises, and passes it along to the next system, and eventually out to the end user).
I think part of the sense of "hacking" comes from bolting the result of the async process onto req, where req gets injected from step to step, through the middleware.
That said:
function eq (a) {
return function (b) { return a === b; };
}
function makeOutputObject (inputObject, personWasFound) {
// return whatever you want
}
var personFound = req.itemFound.people.some(eq(req.user));
var outputObject = makeOutputObject(req.itemFound, personFound);
Now you aren't using the actual delete keyword, or modifying the call-to-call state of that itemFound object.
You're separating your view-based logic from your app-based logic, but without the formal barriers (can always be added later, if they're needed).

what should nodeJS/commonJS module.exports return

I know that I can set module.exports to either an object or a function
(and in some cases a function that will return an object).
I am also aware of the differences and ways to use exports vs. module.exports so no need to comment on that.
I also understand that whatever is returned is cached and will be returned on any consecutive call to require. So that if I choose to return a function and not an object then possibly this implies that on every require It is necessary to actually run this function.
I was wondering is there any defacto standard on which of those two should be used. Or if there is no such standard - what considerations would apply when deciding if my module should return an object, a function or anything more complicated...
The module I intend to write is expected to be used as part of an express application if it matters (maybe there is a "local defacto standard" for express/connect modules).
If the require'd code is standalone, and does not need access to any objects from the parent code, I export an object.
edit - the above is my preferred way to do it. I do the below only when I need to pass stuff into the module, like configuration data, or my database object. I haven't found a more elegant way to give the module access to variables that are in the parents' scope.
So to pass an object from parent into module I use a function:
//parent.js
var config = { DBname:'bar' };
var child = require('./child.js')(config);
//child.js
module.exports = function(cfg){
var innerchild = {};
innerchild.blah = function(){
console.log(cfg.DBname); // this is out of scope unless you pass it in
}
return innerchild;
};
"so that if I choose to return a function and not an object then
possibly this implies that on every require It is necessary to
actually run this function."
It does not matter whether you return an individual function or an object. In neither cases a function (or functions) are ran. unless you explicitly do so.
For instance, consider the a module hello.js:
exports = function () { return 'Hello'; };
You can use require to get that function:
var hello = require('hello');
If you want to run that function, you need to invoke it explicitly as follows:
var hello = require('hello')();
You wrote you want to make sure your function is executed exactly once. Intuitively this could lead you to writing your hello.js as follows:
var hello = function () { return 'Hello'; };
exports = hello();
In which case you could just store result from hello via require:
var hello = require('hello');
However: if you do that the export system may cache your module. In such cases, you do not get fresh result from hello, but instead, a cached value. This may or may not be what you want. If you want to make sure a function is invoked every time it is required, you need to export a function and call it after require.

Namespacing a javascript library, as optional

I'm about to start building a JS library that will have multiple modules. Let's suppose the library is called Library, and two modules will be called One and Two. I'd like for end users to be able to call the library in two different ways:
Library.One.somefunction(params)
or
somefunction(params)
Basically, I want to give the end users the option of including a namespace or not. Is there a good way to do this? Also, is there a good way to do this if I also want to provide a minified version of the library? This library is something that I could end up in Node.js; for now, I'm going to use it myself, but I want to design it in such a way that it's not too hard to turn in to a sharable project in the future.
Any references you can point me to would be great, thanks!
If you're using Node.js you could leverage the CommonJS module system.
math.js (your library)
exports.add = function() {
for (var i = arguments.length; i--;) {
sum += arguments[i];
}
return sum;
};
program.js (someone using it...)
var MyMath = require('math');
console.log(MyMath.add(1, 2)); // 3
// ... in different ways
var add = require('math').add;
console.log(add(1, 2)); // 3
The basic idea behind making a "namespace" optional is to assign the functions to the global scope, which is the window object:
window.somefunction = Library.One.somefunction;
You can write an include function that works similar to other languages:
var include = function (library, p) {
if (!p) {
for (var prop in library) {
if (library.hasOwnProperty(prop)) {
window[prop] = library[prop];
}
}
} else {
window[p] = library[p];
}
};
Then just do, as required:
include(Library.One);
Or use particular functions only:
include(Library.One, 'somefunction');
Warnings:
Executing the functions without the dot notation (One.somefunction) will cause the this keyword to refer to window rather than Library.One. This isn't a problem if you don't use this at all. If you have data to share to between functions then you can do so using closure scope instead of this:
var Library = {};
(function () {
// I'm a closure, I have local scope
var sharedData = "I'm shared but private to this scope";
Library.One = {};
Library.One.funcOne = function () {
alert(sharedData);
};
Library.One.funcTwo = function () {
sharedData += "!";
};
}) ();
Others have well-advised not to make your methods global. This is because once it is global, it is global for all files, and therefore likely to conflict with other code. What you can do is modify the import function above to create a new object, and assign everything to that object before returning it. Then files that need shortcuts to particular libraries can do:
(function () {
var _ = include(Library.One); // This stays within this scope
_.somefunction();
})();
well, i don't know what you mean by "good way".
First of all, the whole purpose of a namespace is to collect variables that are related and not scatter them all around your public namespace.
Personally I wouldn't use such a thing, but you could loop through your namespace's objects and attach them to the window :
for(var i in Namespace)
if(Namespace.hasOwnProperty(i))
window[i] = Namespace[i];
You could do this pretty easily, but are you certain you want to make all the methods global properties?
You could implement it like this (very simplified):
(function( window, undefined ) {
// Your code setting up namespaces
var Library = {One:{},Two:{}};
// function for adding library code to both namespaces.
// Could be modified to accept an Array of functions/names
function addToLibraryOne( id, fn ) {
window[id] = Library.One[id] = fn;
}
// add a function
addToLibraryOne( "somefunction", function( params ) {
// function code
});
window.Library = Library;
})( window );
I'd wonder if you really want to pollute the global namespace like this.
At the very least, I'd make the global properties an option, then only have the function add those if that option is selected.
Well, the second one means that you also want the functions and object and whatever in your modules to be in the global scope. Entirely possible of course, but so against best practices as to be somewhat abhorrent.
For the first part, just declare your Library namespace globally:
var Library = {};
and then start populating it with your modules:
Library.One = {};
Library.Two = {};
and then start adding the functionality to those modules.
(function($) {
var $.froobString = function(s) { .... };
...etc...
})(Library.One);
(Here I've done it as a self-executing anonymous function that passes in Library.One as $.)
To convert all that to globals, have a routine like this:
var convertToGlobals = function(module) {
for (name in module) {
window[name] = module[name];
}
};
convertToGlobals(Library.One)
But then again I'd advise against it.
I might be wrong about this (so this might get downvoted, but I want this evaluated), but I think you are setting up a contradiction with the requirements
1) I want to use namespaces
2) I want to be able to access namespace functionality without the namespace.
basically 2 is "I dont want namespaces".
For implementation, you could just define a bunch of functions globally that route into the namespace, but then why have the namespace to begin with?

Resources