I have this directory structure:
project/
mymodule.js
test/
run.js
node_modules/
canvas/
I have code like so:
run.js
var Canvas = require(__dirname+"/../mymodule");
mymodule.js
if (typeof require==='function' && typeof module==='object'){
// when using mymodule with Node the 'canvas' module must be available
var canvas = require('canvas');
module.exports = canvas;
} else {
// code that works in a web browser, without Node
}
The result of node test/run.js is Error: Cannot find module 'canvas'.
How can I make it so that the require from mymodule knows to look relative to the original script? Or is that contrary to the way Node modules work? Must I move canvas (which is only used for testing on my end) out of the test directory?
When you don't put a path in the require statement, it assumes you're trying to load a module. If you want to load something in your code, be sure to include a relative or absolute path. In your case:
var canvas = require('./test/node_modules/canvas');
The other way to do this is to have your node_modules directory in root, and not web-accessible.
project/
mymodule.js
node_modules/
canvas/
test/
run.js
Then in your run.js or your mymodule.js you can require('canvas') as you'd expect.
Related
I have the following structure:
-- node_modules
-- websites
---- common
------- config.js
---- testing
------- test.js
Inside config I have some variables set, which are being exported using module.export.
I am trying to retrieve those variables when running node test.js from config.js using the following codes:
var configData = require('./common/config.js')
var configData = require('../common/config.js')
None of them work. What can I do to retrieve the data from the other folder?
var configData = require('./../common/config.js');
./ is testing/
./../ is websites/
./../common/ is websites/common/
./../common/config.js is websites/common/config.js
from test.js:
const configData = require('../common/config');
You can safely omit '.js'.
As documentation say:
File Modules
If the exact filename is not found, then Node.js will attempt to load the required filename with the added extensions: .js,
.json, and finally .node.
.js files are interpreted as JavaScript text files, and .json files
are parsed as JSON text files. .node files are interpreted as compiled
addon modules loaded with dlopen.
A required module prefixed with '/' is an absolute path to the file.
For example, require('/home/marco/foo.js') will load the file at
/home/marco/foo.js.
A required module prefixed with './' is relative to the file calling
require(). That is, circle.js must be in the same directory as foo.js
for require('./circle') to find it.
Without a leading '/', './', or '../' to indicate a file, the module
must either be a core module or is loaded from a node_modules folder.
If the given path does not exist, require() will throw an Error with
its code property set to 'MODULE_NOT_FOUND'.
More info about how require() work here.
const cheerio = require('../node_modules/cheerio');
const request = require('../node_modules/request-promise');
const vl = require('../node_modules/validator');
const crypto = require('crypto');
const fs = require('fs');
I'm in the process of building an npm package which will be installed globally. Is it possible to have non-code files installed alongside code files that can be referenced from code files?
For example, if my package includes someTextFile.txt and a module.js file (and my package.json includes "bin": {"someCommand":"./module.js"}) can I read the contents of someTextFile.txt into memory in module.js? How would I do that?
The following is an example of a module that loads the contents of a file (string) into the global scope.
core.js : the main module file (entry point of package.json)
//:Understanding: module.exports
module.exports = {
reload:(cb)=>{ console.log("[>] Magick reloading to memory"); ReadSpellBook(cb)}
}
//:Understanding: global object
//the following function is only accesible by the magick module
const ReadSpellBook=(cb)=>{
require('fs').readFile(__dirname+"/spellBook.txt","utf8",(e,theSpells)=>{
if(e){ console.log("[!] The Spell Book is MISSING!\n"); cb(e)}
else{
console.log("[*] Reading Spell Book")
//since we want to make the contents of .txt accesible :
global.SpellBook = theSpells // global.SpellBook is now shared accross all the code (global scope)
cb()//callBack
}
})
}
//·: Initialize :.
console.log("[+] Time for some Magick!")
ReadSpellBook((e)=>e?console.log(e):console.log(SpellBook))
spellBook.txt
ᚠ ᚡ ᚢ ᚣ ᚤ ᚥ ᚦ ᚧ ᚨ ᚩ ᚪ ᚫ ᚬ ᚭ ᚮ ᚯ
ᚰ ᚱ ᚲ ᚳ ᚴ ᚵ ᚶ ᚷ ᚸ ᚹ ᚺ ᚻ ᚼ ᚽ ᚾ ᚿ
ᛀ ᛁ ᛂ ᛃ ᛄ ᛅ ᛆ ᛇ ᛈ ᛉ ᛊ ᛋ ᛌ ᛍ ᛎ ᛏ
ᛐ ᛑ ᛒ ᛓ ᛔ ᛕ ᛖ ᛗ ᛘ ᛙ ᛚ ᛛ ᛜ ᛝ ᛞ ᛟ
ᛠ ᛡ ᛢ ᛣ ᛤ ᛥ ᛦ ᛧ ᛨ ᛩ ᛪ ᛫ ᛬ ᛭ ᛮ ᛯ
If you require it from another piece of code, you will see how it prints to the console and initializes by itself.
If you want to achieve a manual initalization, simply remove the 3 last lines (·: Initialize :.) and use reload() :
const magick = require("core.js")
magick.reload((error)=>{ if(error){throw error}else{
//now you know the SpellBook is loaded
console.log(SpellBook.length)
})
I have built some CLIs which were distributed privately, so I believe I can illuminate a bit here.
Let's say your global modules are installed at a directory called $PATH. When your package will be installed on any machine, it will essentially be extracted at that directory.
When you'll fire up someCommand from any terminal, the module.js will be invoked which was kept at $PATH. If you initially kept the template file in the same directory as your package, then it will be present at that location which is local to module.js.
Assuming you edit the template as a string and then want to write it locally to where the user wished / pwd, you just have to use process.cwd() to get the path to that directory. This totally depends on how you code it out.
In case you want to explicitly include the files only in the npm package, then use files attribute of package.json.
As to particularly answer "how can my code file in the npm package locate the path to the globally installed npm folder in which it is located in a way that is guaranteed to work across OSes and is future proof?", that is very very different from the template thingy you were trying to achieve. Anyway, what you're simply asking here is the global path of npm modules. As a fail safe option, use the path returned by require.main.filename within your code to keep that as a reference.
When you npm publish, it packages everything in the folder, excluding things noted in .npmignore. (If you don't have an .npmignore file, it'll dig into .gitignore. See https://docs.npmjs.com/misc/developers#keeping-files-out-of-your-package) So in short, yes, you can package the text file into your module. Installing the module (locally or globally) will get the text file into place in a way you expect.
How do you find the text file once it's installed? __dirname gives you the path of the current file ... if you ask early enough. See https://nodejs.org/docs/latest/api/globals.html#globals_dirname (If you use __dirname inside a closure, it may be the path of the enclosing function.) For the near-term of "future", this doesn't look like it'll change, and will work as expected in all conditions -- whether the module is installed locally or globally, and whether others depend on the module or it's a direct install.
So let's assume the text file is in the same directory as the currently running script:
var fs = require('fs');
var path = require('path');
var dir = __dirname;
function runIt(cb) {
var fullPath = path.combine(__dirname, 'myfile.txt');
fs.readFile(fullPath, 'utf8' , function (e,content) {
if (e) {
return cb(e);
}
// content now has the contents of the file
cb(content);
}
}
module.exports = runIt;
Sweet!
I have the following structure:
-- node_modules
-- websites
---- common
------- config.js
---- testing
------- test.js
Inside config I have some variables set, which are being exported using module.export.
I am trying to retrieve those variables when running node test.js from config.js using the following codes:
var configData = require('./common/config.js')
var configData = require('../common/config.js')
None of them work. What can I do to retrieve the data from the other folder?
var configData = require('./../common/config.js');
./ is testing/
./../ is websites/
./../common/ is websites/common/
./../common/config.js is websites/common/config.js
from test.js:
const configData = require('../common/config');
You can safely omit '.js'.
As documentation say:
File Modules
If the exact filename is not found, then Node.js will attempt to load the required filename with the added extensions: .js,
.json, and finally .node.
.js files are interpreted as JavaScript text files, and .json files
are parsed as JSON text files. .node files are interpreted as compiled
addon modules loaded with dlopen.
A required module prefixed with '/' is an absolute path to the file.
For example, require('/home/marco/foo.js') will load the file at
/home/marco/foo.js.
A required module prefixed with './' is relative to the file calling
require(). That is, circle.js must be in the same directory as foo.js
for require('./circle') to find it.
Without a leading '/', './', or '../' to indicate a file, the module
must either be a core module or is loaded from a node_modules folder.
If the given path does not exist, require() will throw an Error with
its code property set to 'MODULE_NOT_FOUND'.
More info about how require() work here.
const cheerio = require('../node_modules/cheerio');
const request = require('../node_modules/request-promise');
const vl = require('../node_modules/validator');
const crypto = require('crypto');
const fs = require('fs');
Within a karma test beforeEach) block I would like to access (read) a file from the project directory. However, I do not know how to get access to that directory, since process.cwd() returns the directory the test is running in, which is a random private dir assigned by node or gulp.
How can I find what the project dir is within a running test?
describe.only('convertClaimTypes', function () {
var claimTypes;
before(function () {
var base = process.cwd();
claimTypes = fs.readFileSync(path.join(base, 'build/resources/claimTypes.json'));
claimTypes = JSON.parse(claimTypes);
});
...
Try using __dirname in place of process.cwd() as it gives you the directory of the current file rather than the directory of the executable.
For example, if your tests are within a directory /test and /build is a directory within the root of your application, access /build from /test like so:
path.resolve(__dirname, '../build/');
How can I make require look in the relative path of the executing script (not whatever script has require'd the executing script)? Example:
index.js
require('lib/foo.js');
--
lib/foo.js
var barFunction = require('./bar.js').barFunction;
barFunction();
--
lib/bar.js
module.exports.barFunction = function(){
return true;
}
When you node index.js, foo.js looks for bar.js instead of lib/bar.js.
If foo.js is amended to require('lib/bar.js'), then node foo.js will stop working.
How can I set up require in a way that I can both node index.js and node lib/foo.js and have then both work?
You can use __dirname to get the absolute directory the currently executing script resides in. For example:
index.js:
require(__dirname + '/lib/foo.js');
lib/foo.js:
var barFunction = require(__dirname + '/bar.js').barFunction;
barFunction();