I'm currently learning nodeJS and running version v6.10.2, I was taking a look at the fs.js module source code located in the graceful-js folder and noticed this code in it:
'use strict'
var fs = require('fs')
module.exports = clone(fs)
function clone (obj) {
if (obj === null || typeof obj !== 'object')
return obj
if (obj instanceof Object)
var copy = { __proto__: obj.__proto__ }
else
var copy = Object.create(null)
Object.getOwnPropertyNames(obj).forEach(function (key) {
Object.defineProperty(copy, key, Object.getOwnPropertyDescriptor(obj, key))
})
return copy
}
How can a module require itself does it have to do with the clone keyword? I couldn't find any other module named fs.js either.
You're looking at part of the code for the graceful-fs package which is a wrapper around the builtin fs module in NodeJS. So this code is not requiring itself - the require statement imports the builtin fs module and the rest of the code clones it so that other parts of the graceful-fs package can override some of the default fs functionality without affecting the original module.
Related
I found this npm package online which is no longer maintained. The package uses
if (typeof module !== 'undefined' && module.exports) {
module.exports = Dymo;
} else {
window.Dymo = Dymo;
}
at the end to export a Dymo class. Now I wanted to change a few things on this code, so I decided to copy this and make some changes but stored is as a local js file.
So instead of calling Dymo as
const Dymo = require('dymojs');
I tried doing
const Dymo = require('./dymojs')
But when I do:
let dymo = new Dymo();
I get
TypeError: Dymo is not a constructor
Does anyone have any examples of how to use reflect-metadata in nodejs? I am using atom-typescript also. I downloaded using it via npm but i keep getting random errors. I see Reflect is a blank object. Just looking for an example of how to incorporate this into a module or node project.
When I faced the same problem and nothing worked, I opened Reflect.ts file in node_modules. At the end, you can see it hooking Reflect at global level.
// hook global Reflect
(function(__global: any) {
if (typeof __global.Reflect !== "undefined") {
if (__global.Reflect !== Reflect) {
for (var p in Reflect) {
__global.Reflect[p] = (<any>Reflect)[p];
}
}
}
else {
__global.Reflect = Reflect;
}
})(
typeof window !== "undefined" ? window :
typeof WorkerGlobalScope !== "undefined" ? self :
typeof global !== "undefined" ? global :
Function("return this;")());
So, I removed require reflect-metadata from all other files, and moved it to main file.
require('reflect-metadata/Reflect');
Now, I can use it inside all modules (without requiring reflect-metadata) with the following syntax,
(<any>global).Reflect.getMetadata("design:type", target, key); // In Typescript
EDIT:
We can also reference reflect-metadata.d.ts file from node_modules and then use the API directly.
/// <reference path="../../node_modules/reflect-metadata/reflect-metadata.d.ts" />
Reflect.getMetadata("design:type", target, propertyKey);
In TypeScript#2.0+, you can use it like this:
npm i -S reflect-metadata
npm i -D #types/reflect-metadata
// your.ts
import 'reflect-metadata'
Reflect.getMetadata(...)
Reflect.metadata(...)
Here is a function from jasmine 2.0.0 standalone project:
function getJasmineRequireObj() {
if (typeof module !== "undefined" && module.exports) {
return exports;
} else {
window.jasmineRequire = window.jasmineRequire || {};
return window.jasmineRequire;
}
}
I guess that if I would use the standard require method the module property will be define.
When I load this file using the VM module as follows the module global property is undefined:
var fs = require('fs');
var vm = require('vm');
var jasmineFile = fs.readFileSync(__dirname + '/jasmine.js');
vm.runInThisContext(src, jasmineFile);
Is this the expected behavior of the VM module or a defect?
It is the expected behaviour. Your code is evaluated in the same context, but not in the same scope, so module, exports and whatnot are undefined. You can do something like this:
var m = require('module')
var src = 'module.exports = 42'
var res = require('vm').runInThisContext(m.wrap(src))(exports, require, module, __filename, __dirname)
console.log(module.exports)
but there is no much point in doing that, because it's basically what require does
Purpose: making a Node.js module or a Requirejs AMD module, from a plain old JavaScript file like this:
var foo = function () {};
I have no control and I can't edit foo.js.
Whyfoo is is a plain empty object inside the first if? How can I "include" a plain JavaScript file in my module? File mymodule.js:
(function(root) {
if(typeof exports === 'object') { // Node.js
var foo = require('./foo');
console.log(foo); // { }
} else if (typeof define === 'function' && define.amd) { // RequireJS AMD
define(['foo'], function () {
return foo;
});
}
}());
Node modules loaded with require must populate an exports object with everything that the module wants to make public. In your case, when you require the file nothing is added to exports, hence it shows up as empty. So the short answer is that you need to modify the contents of foo.js somehow. If you can't do it manually, then you need to do it programmatically. Why do you have no control over it?
The easiest being that you programmatically wrap the contents if foo.js in the code needed to make it a proper module.
// Add an 'exports' line to the end of the module before loading it.
var originalFoo = fs.readFileSync('./foo.js', 'utf8');
fs.writeFileSync('./foo-module.js', originalFoo + "\nexports.foo = foo;");
var foo = require('./foo-module.js');
You Could Try:
var fs = require('fs');
var foo = fs.readFileSync('foo.js', 'utf8') // Or request it somehow, just get it as a string
foo += "module.exports.foo = module.exports = foo;";
fs.writeFileSync('fooModule.js',foo);
var foo = require('./fooModule');
// foo() and foo.foo() are both the same
Note: This requires node.
I have a javascript lib, basically this is how it is structured so far:
var Ns = (function(){
var that = {};
// add stuff to 'that'
return that;
})();
//use Ns.foo() and Ns.bar()
The thing is that now, I wanted the same lib to be available with node and npm. So far this is what I could come up with:
this.Ns = (function(){ //same as previous snippet })()
//use Ns.foo() and Ns.bar()
The problem is that, while this works in the browser, in node I need to do this:
var Ns = require('ns').Ns
Problem: I'd love to be able to do var Ns = require('ns') but in order to do that I have to export this.foo and this.bar which will break the browser inclusion. Ideas?
// create local scope.
(function () {
var myModule = ...
// check for node module loader
if (typeof module !== "undefined" && typeof require !== "undefined") {
module.exports = myModule;
} else {
window["name"] = myModule;
}
})();
Creating a scope is probably the best route to go (so you don't have name collision issues), but an easier way to do this, by polluting the global scope, looks like this:
instead of
var x = require('x');
write
var x = (typeof require !== "undefined") ? require('x') : window;
and similarly, before added to exports, check if that object exists:
if (typeof exports !== "undefined)
exports.my_func = my_func;
The consequences of this, though, is that in the browser version everything gets dumped into global scope. Also, it assumes that the browser version loads the necessary scripts into the page. Easy to get working on a small scale... but I'm guessing it won't scale well.