read a JS file which has objects in Node.JS

I have a JS file, in whcih I have lots of objects; I want to read this file in Node.Js and loop through the objects. The JS file looks like:

User = {
    fields: {
        name: {
            type: "STRING"
        },
        id: {
            type: "integer"
        },
        password: {
            type: "STRING"
        }
    }
};

car = {
    fields: {
        model: {
            type: "STRING"
        },
        color: {
            type: "STRING"
        }

    }
};

I tried the following but it does not work:

var Model = fs.readFileSync("Model.js");
data_test = JSON.stringify(Model);
response.send(data_test);

Clearly the file is JS, not JSON, therefore JSON.stringify isn't going to work. If you have absolutely no control over the file then you could technically get this to work with some hacking

function requireFromString(src, filename) {
    var Module = module.constructor;
    var m = new Module();
    m._compile(src, filename);
    return m.exports;
}
var moduleStr = fs.readFileSync("Model.js");
moduleStr = 'module.exports = {' + moduleStr + '}';
response.send(requireFromString(moduleStr));

On-the-fly module compilation code example stolen borrowed from this answer.


The idea behind the above example was to attempt to export Model.js as a single object because I assumed you didn't know what type of objects resided in there. However, looking back at it I can see that it's not going to work because

module.exports = { 
     User = { ... };
     car = { ... };
}

Is not valid JS. If you do know which objects you want to export then you can of course just modify the moduleStr to do that

moduleStr = moduleStr + '\nmodule.exports = { User: User, Car: car }';

Also, your approach gave me the following error: "SyntaxError: Unexpected token = at Module._compile (module.js:439:25) at requireFromString"

A slight tweak to @James' answer should do the trick:

function requireFromString(src, filename) {
    var Module = module.constructor;
    var m = new Module();
    m._compile(src, filename);
    return m.exports;
}
var moduleStr = fs.readFileSync("Model.js");
//moduleStr = 'module.exports = {' + moduleStr + '}';
moduleStr = moduleStr + '\nmodule.exports = { User: User, car: car };';
response.send(requireFromString(moduleStr));

Explanation:

As others have commented, valid JSON !== valid Javascript; and if a file loads in the browser, that means that it is valid Javascript, but not necessarily valid JSON.

Essentially what you are trying to do is load a Javascript file in NodeJs. Unfrotunately NodeJs uses a different system when loading different files and managing the dependencies between them. In the browser, it is based on a first-come-first-served basis. Essentially the variables are created in the order that files are loaded.

In NodeJs OTOH, you specify qa single Javascript file as the entry point, and that file should 'require()' any other Javascript files that it needs. Whatever each file exports is what the require-ing file sees.

tl;dr Browsers and NodeJs load Javascript files in incompatible ways.

So, how do you solve you problem? Well James' solution provides a way to compile a NodeJs module manually, by compiling a string.

This is great, except that way that string is modified to export what you have in your file simply will not yield valid Javascript:

module.exports = { foo = 'bar'; }

What my solution does instead is this, which yields valid Javascript:

foo = 'bar';
module.exports = { foo: foo };