最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - npm global packages: Reference content files from package - Stack Overflow

programmeradmin1浏览0评论

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?

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?

Share edited May 22, 2018 at 16:14 Jacob Horbulyk asked Apr 25, 2018 at 15:57 Jacob HorbulykJacob Horbulyk 2,6575 gold badges26 silver badges37 bronze badges 5
  • First question, why a txt file...and second question, do the path for that file matter? – Hackerman Commented May 22, 2018 at 16:01
  • @Hackerman Doesn't necessarily have to be a .txt file. The idea is that I want to build a cli tool (in node.js which is published and distributed through npm), which can reference data not stored in code. In my particular case, I want to build a scaffolding tool which when run, picks up a template file, slightly transforms the template file and then saves the result in the local directory in which the scaffolding task was run. The tool needs the path of the template file so that it can read that file when executed. – Jacob Horbulyk Commented May 22, 2018 at 16:08
  • It seems to me that an npm package is simply a folder with a package.json. So if you include other files, like a .txt file, it should be accessible. Do you want to know if it's accessible, or how to access it? Because for the latter it seems like you'd access these files like regular files. – mgul Commented May 22, 2018 at 16:24
  • @mgul That is my understanding of npm as well. I suppose my question can be rephrased to “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?” Once I have that I can construct the path to individual files in that folder and interact with them as normal files. – Jacob Horbulyk Commented May 22, 2018 at 16:34
  • 1 I think you should look into this question: stackoverflow./questions/10265798/… It essentialy provides you ways to access your project root to access files there. – mgul Commented May 22, 2018 at 16:37
Add a ment  | 

3 Answers 3

Reset to default 2 +25

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.

  1. 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.

  2. 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.

  3. 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.

  4. 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./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/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.bine(__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!

发布评论

评论列表(0)

  1. 暂无评论