Can I create an npm package that sets up another npm package? - node.js

I want to create an npm package that would be installed globally, with a binary to call. Calling that binary would set up the initial files for a new project, like your standard folders, standard license and layouts, a package.json with your common dependencies. Then you could call npm install to actually set up that project.
Like the Express application generator, or like rails new does in Ruby. The usage would be like
mkdir new_project
cd new_project
myCoolGenerator new
npm install
But I'm confused about how I'd implement this. The simple approach, which I'm doing now, is to create the standard vanilla folder, ship it with the generator package, and then just have the main binary use ncp to copy that folder into wherever the caller currently is.
My problem there is that I don't know how I can access the folder included in the globally-installed package to copy over. And additionally, npm lets you specify a files array in your package.json to specify files included with the package, but it's apparently hardwired to ignore package.json from that.
What's the recommended procedure for this sort of thing?

Related

Are all packages also modules in Node?

I've read npm doc, but still couple of my concepts are still unclear which may seem naive, are as follows:
Q1.
A package is a file or directory that is described by a package.json
file.
What do they meant by "described by a package.json file"? Any example to understand easily?
Q2.
Condition to be a package
A package is a file or directory that is described by a package.json
file.
Condition to be a module
To be loaded by the Node.js require() function, a module must be one
of the following:
A folder with a package.json file containing a "main" field.
A folder with an index.js file in it.
A JavaScript file.
Note: Since modules are not required to have a package.json file, not
all modules are packages. Only modules that have a package.json file
are also packages.
So, as per the Note, shouldn't it also implies that all packages are also modules as all packages have package.json files?
A module is anything that can be loaded with require() and does something useful. It can be a single file. It does not need to have a package.json associated with it. In fact, many locally developed "modules" do not. You can have many modules in the same directory.
A package is a set of code designed for easy distribution. If you are using the NPM package manager, then an NPM package will contain a package.json file that has a bunch of meta data about the package, including things like dependencies on other modules, author info, repository info, info on how to test the module, info on which file is the startup file for the module, etc...
FYI, NPM is not the only package manager so it's not the only way of doing things, but for node.js development it is certainly the most widely used and it offers a central repository that makes it easy the "publish" packages for wide and simple distribution.
Are all packages also modules in Node?
I suppose it's possible to distribute something other than runnable code in a package, but the primary use of an NPM package is to distribute modules.
Here's an example of destributing static data rather than code: JSON Data Node Modules Part 1: Using NPM to Store and Distribute Static Data.

How to modify an npm package built with TypeScript

I want to try and make some changes to a package published in npm? (I've suggest some changes as an issue but I think they are simple enough for me to attempt them).
https://www.npmjs.com/package/bt-presence#contributing--modifying
The author supplies some information on how to modify the package, but not really enough for someone doing it for the first time.
Where should I clone the GitHub repo to? The folder where the package is installed? I tried it in my home folder and that would not build (unmodified).
The command npm run build - where is this run from? The root folder of the package where the package.json is?
Will I need to modify the package.json?
In general what is the best way to develop something like this for npm? I've worked on packages before but they were simply Javascript.
If you want to work on the bt-presence package in isolation, you can put the cloned repository anywhere. If you want to use your modified version of bt-presence in combination with an application, my recommended approach is to register bt-presence as a dependency in the application's package.json file with the version set to a relative path to your bt-presence repository; then running npm install in the application will make a symlink from node_modules/bt-presence in the application to your bt-presence repository.
npm run build should indeed be run from the root folder that contains the package.json of bt-presence.
If you just want to change the code of bt-presence, you won't need to modify its package.json. You would only modify the package.json if you need to change any of the settings in there, e.g, if you need to add additional dependencies to your version of bt-presence.
None of the above is really specific to TypeScript. (Some JavaScript packages have build processes too if they need to transform or package the JavaScript files in some way.)

Build strategies for utilizing npm packages

This must be a commonly solved problem, but I cannot find a whole lot on Google/SO so far.
When we run npm install and fetch say 50+ packages including devDependencies as well as runtime dependencies, npm creates node_modules (if needed) and adds each of those packages inside that folder. This means we end up with thousands of extraneous files included under node_modules. Each of those packages contains their own package.json, README.md, minified files, source files, etc. Our application really only cares about jquery.js (for DEV) and jquery.min.js (for PROD), so it seems to be a waste to include all of these other files into our build and therefore our web server.
Is there a standard when it comes to handle these npm packages in a way so that we simply expose ONLY the necessary files to the user? I imagine many people have this kind of issue but I don't see any built in npm constructs that allow us to do this easily.
See below.. the yellow highlighted files are the only files we really care about in Production, but we get all these extra files as well including the source code.
The most common solution consist of bundling your application on a different machine and then expose the built artefacts on production server.
There are a lot of great JS bundlers out there. The ones I have personally used are Browserify, Webpack, and Rollup. All amazing tools.
The main idea consists of writing your application in a Node environment and then bundle it to make it readable to the browser.
For simpler projects I find Browserify a very good compromise between power and ease of configuration. But it's a matter of taste, at the end. :)
Base on what I read about npm install documentation I do not think there is a option to manipulate the installation in the way you want. The packages will install the way the package author decides to package it, sometimes minified sometimes not.
Having said that, you should look for third party solutions like modclean which does exactly what you want post package installation. Run this command in the root of your project directory
npm install modclean -g
modclean
As long as your test coverage is good, ModClean would be perfect for your need.
Edit the package.json file and remove all the unnecessary dependencies then do
npm install --save
By doing this, it will create a local node_modules folder and only download the necessary packages into it (not the global node_modules folder)
Keep in mind, by default, node checks for local node_modules folder. If it couldn't find it, it will use the global folder.
Also, you don't expose all the packages in the node_modules folder. In fact, they will not be used unless you require(); them in the node.js file
EDIT:
For jQuery to work in Node, a window with a document is required. Since no such window exists natively in Node, one can be mocked by tools such as jsdom. This can be useful for testing purposes. https://www.npmjs.com/package/jquery
require("jsdom").env("", function(err, window) {
if (err) {
console.error(err);
return;
}
var $ = require("jquery")(window);
});
So jquery module do things a bit differently behind the scene for node.js comparing to the regular front-end jquery.
It requires jsdom so you will have to download that as well from here https://github.com/tmpvar/jsdom

Download node module sources without installing them?

I would like to download node module packages (listed in a package.json file, in the present working directory) source code to a node_modules subdirectory of the present working directory, without compiling, or installing those modules. Now I have seen the related question download source from npm without npm install xxx but that question dealt with downloading the source code of individual modules specified to NPM directly (i.e., without using a package.json file). The reason why I want to do this is because I am working on developing an Atom package for the Open Build Service (OBS) of openSUSE and this seems like one of the necessary steps I need to go through in order to achieve this.
The source code is not shipped with the npm distributed code. The best you could do is read the package.json and look for the { repository: url { } } key if it exists and if it's a git repo (which most of them will be) clone it.
However be aware that the source code often requires a build step before it can be used, as in an npm prepublish step defined in the source code. In modern Javascript projects a common example of this is transpiling ES6 code to ES5 code for use in NodeJS and the browser.
I have not made an Atom package but I'm fairly certain you don't need to do any of this.

NPM Link Vs. requiring using path

NPM link seems cool, but what are the differences between NPM link and requiring the module by giving the path? Could you please elaborate the advantageous of each?
When you use npm link you can require it like:
var foo = require("foo");
but if you use the path, you require it like:
var foo = require("./lib/foo");
Thanks
Npm link is useful if you are developing some node_module which has dependency to other standalone node_module you are also developing simultaneously (which you then may upload to the npm when it is ready / releasable). Using this setup you will always get the freshest version of "other module" without need to push releases to npm.
It is better than using relative dependencies because relative paths can be individual (per developer), but npm link works as if it was required from npm (located in node_modules folder).
Conclusion: I usually use relative dependencies inside of module itself to require other files and npm link to specify dependencies between simultaneously developed standalone modules.

Resources