Pulling files from a directory into the root folder for NPM - npm

I am publishing a library to NPM.
When I build the library, the resulting artifact is placed in the dist folder located in the root of my project as index.js.
When users install from NPM I would like index.js to be present in the root of the folder created in their node_modules folder. Presently, it remains in a directory named dist.
How can I do this?
My packages.json:
{
"name": "my-package",
"version": "0.0.9",
"files": ["dist/*"],
"main": "index.min.js",
"private": false,
"dependencies": {},
"devDependencies": {},
"repository": "git#github.com:username/my-package.git"
}

I had exactly the same problem.
I solved it not by copying the files up, but by copying the files I needed down into the ./dist/ folder and then doing an npm publish from there; NPM then treats that folder as a complete package and everything works very nicely. The only files I needed to copy from the root folder were:
package.json
README.md
Because we're going to copy these files down into the ./dist/ folder before we do the publish, we do NOT want the package.json file to reference ./dist/. So remove the package.json's files entry completely, because we don't need to tell it which files we'll take - we're going to take everything in the ./dist/ folder. I'm using TypeScript so I also have a typings entry, and again no reference to ./dist/.
{
"name": "my-package",
"version": "0.0.9",
"main": "index.min.js",
"typings": "index.d.ts",
"private": false,
"dependencies": {},
"devDependencies": {},
"repository": "git#github.com:username/my-package.git"
}
Now for the publish step. I built a gulp task that will perform the publish for me, making it nice and automated (except for incrementing the package version #).
From gulp I'll use Node's spawn() to kick-off the npm process. However, because I'm actually working on Windows I used "cross-spawn" rather than the normal built-in Node.js spawn (which I learned the hard way didn't work when I had spaces in my path!).
Here's my gulp file, with the TypeScript bits removed:
var gulp = require('gulp');
var del = require('del');
var spawn = require('cross-spawn'); // WAS: require('child_process').spawn;
var config = {
src: { tsFiles: './src/**/*.ts' },
out: { path: './dist/' }
}
gulp.task('clean', () => {
return del('dist/*');
});
gulp.task('build', ['clean'], () => {
....
});
gulp.task('publish', ['build'], (done) => {
// Copy the files we'll need to publish
// We just use built-in gulp commands to do the copy
gulp.src(['package.json', 'README.md']).pipe(gulp.dest(config.out.path));
// We'll start the npm process in the dist directory
var outPath = config.out.path.replace(/(\.)|(\/)/gm,'');
var distDir = __dirname + '\\' + outPath + '\\';
console.log("dist directory = " + distDir);
// Start the npm process
spawn('npm', ['publish'], { stdio:'inherit', cwd:distDir } )
.on('close', done)
.on('error', function(error) {
console.error(' Underlying spawn error: ' + error);
throw error;
});
});
Notice when we call spawn() we pass in a 3rd argument which is the options. The main entry here is the cwd:distDir, which tells spawn to run the npm process from the ./dist/ directory. Because using spawn can cause problems I've hooked into the spawn error handling. As I was troubleshooting my use of spawn() I found the following StackOverflow article very helpful.
This worked like a charm; my published package has all the files in the root directory and the ./dist/ folder is not published.

Related

download a zip file via http with npm

There is a zip file at some http:// | https:// location.
In this case it's a zip of assets, in particular a font, so it's not a js package and has no git repository or other kind of repository.
With bower one could just reference the location and it would download and extract the zip file.
How can I achieve this with npm? Preferably without hacks, because my postinstall script already does a bunch of stuff.
Add this in file package.json:
"scripts": {
"postinstall": "node download.js && <whatever you had here before>"
},
"dependencies": {
"download-file": "0.1.5"
}
And then add this in file download.js next to file package.json:
var download = require('download-file')
const url = "https://YourFileLocation";
const options = {directory: "YourDirName", filename: "YourFileName"};
console.log("Installing " + options.directory + "/" + options.filename);
download(url, options, function(error) {if (error) throw error;});
See: https://www.npmjs.com/package/download-file

GULP: gulp is not defined

As shown in the screen shot below I am not able to run gulp to concat the JavaScript files. Its saying that gulp is not defined.
I have tried the following commands:
npm install -g gulp
npm install gulp
npm install gulp --save-dev
I have also set the environment variables as following:
C:\Users\<user>\AppData\Roaming\npm;C:\Python27;C:\Users\<user>\AppData\Roaming\npm\node_modules;C:\Users\<user>\AppData\Roaming\npm\node_modules\gulp;
var concat = require('gulp-concat');
var rename = require('gulp-rename');
var uglify = require('gulp-uglify');
//script paths
var jsFiles = 'scripts/*.js',
jsDest = 'dist/scripts';
gulp.task('scripts', function() {
return gulp.src(jsFiles)
.pipe(concat('scripts.js'))
.pipe(gulp.dest(jsDest));
});
you just need to install and require gulp locally, you probably only installed it globally
At the command line
cd <project-root> && npm install --save-dev gulp
In your gulpfile.js
var gulp = require('gulp');
this is a different dependency than the command line dependency (that you installed globally). More specifically, it is the same NPM package, but the command line program will execute code usually from a different entry point in the NPM package then what require('X') will return.
If we go to the package.json file in the Gulp project on Github, it will tell the whole story:
{
"name": "gulp",
"description": "The streaming build system",
"version": "3.9.1",
"homepage": "http://gulpjs.com",
"repository": "gulpjs/gulp",
"author": "Fractal <contact#wearefractal.com> (http://wearefractal.com/)",
"tags": [ ],
"files": [
// ...
],
"bin": {
"gulp": "./bin/gulp.js"
},
"man": "gulp.1",
"dependencies": {
// ...
},
"devDependencies": {
// ...
},
"scripts": {
"prepublish": "marked-man --name gulp docs/CLI.md > gulp.1",
"lint": "eslint . && jscs *.js bin/ lib/ test/",
"pretest": "npm run lint",
},
"engines": {
"node": ">= 0.9"
},
"license": "MIT"
}
so at the command line:
$ gulp default
will execute this:
"bin": {
"gulp": "./bin/gulp.js"
},
on the other hand, require('gulp') in your code will return the value of this:
https://github.com/gulpjs/gulp/blob/master/index.js
normally we see this in a package.json file as:
"main": "index.js"
but since this is the default, they just omitted it (which is dumb IMO, better to be explicit, but they aren't the first project I have seen take the lame shorthand route.).
Its occurs on Windows and usually one of the following fixes it:
If you didn't, run npm install gulp on the project folder, even if
you have gulp installed globally.
Normally, It isn't a problem on Windows, but it could be a issue with
the PATH. The package will try to get the PATH from the environment,
but you can override it by adding exec_args to your gulp settings.
For example, on Ubuntu:
"exec_args": {
"path": "/bin:/usr/bin:/usr/local/bin"
}
Hope It will be OK.
Source: https://github.com/NicoSantangelo/sublime-gulp/issues/12

project.json scripts events can delete folders?

I am trying to delete a folder on post compile but cant make rd or del commands to work. Is there a way to delete a folder and subfolders from the scripts events?
Put the commands that you need in a batch or shell file and invoke that file in the post compile step
Use npm and gulp task, that not depends on the OS
Add a package.json file in your project root with gulp and gulp-rimraf dependencies:
{
"version": "1.0.0",
"description": "your description",
"name": "your project name",
"readme": "yuour readme",
"license": "Apache-2.0",
"dependencies": {
},
"devDependencies": {
"gulp": "3.9.1",
"gulp-rimraf": "0.2.0",
},
"scripts": {
"gulp": "gulp",
}
}
Add a gulpfile.js in your project root containing the cleanup task :
/// <binding Clean='clean' />
"use strict";
var gulp = require("gulp"),
rimraf = require("gulp-rimraf");
gulp.task("clean:js", function (cb) {
return rimraf("path to js folder to delete", cb);
});
gulp.task("clean:css", function (cb) {
return rimraf("path to css folder to delete", cb);
});
gulp.task("default", ["clean:js", "clean:css"]);
In your project.json, call the npm script :
{
...
"scripts": {
"precompile": "npm run gulp" // this will call the default gulp task
},
}
For more information, you can read the doc about how to use gulp on the asp.net docs site
You can do the same using grunt instead of gulp if you want

Move browserify workflow into gulp task [vueify, browserify, babelify]

I'm trying to migrate the following browserify workflow into a single gulp task:
package.json:
"scripts": {
"build": "browserify src/main.js > dist/build.js"
},
...
"browserify": {
"transform": [
"vueify",
"babelify"
]
}
.babelrc file:
{
"presets": ["es2015"]
}
Since gulp-browserify is now longer maintained, I used this recipe to get the whole workflow into a single gulp task:
gulp.task('build', function () {
var b = browserify({
entries: './src/main.js',
debug: true,
transform: [vueify, babelify.configure({presets: ["es2015"]})]
});
return b.bundle()
.pipe(source('build.js'))
.pipe(buffer())
.on('error', gutil.log)
.pipe(gulp.dest('./dist/'));
});
Unfortunately, the generated build.js files are different and only the build.js file generated by the command npm run build is running my Vue.js App properly.
I just managed to get past this problem myself. After spending a bit of time in the debugger I found that the array of transforms used by browserify contained 'babelify' and 'vueify' twice.
What happens then is probably that the transforms are applied like so: bablify -> vueify -> babelify -> vueify. I didn't spend much time figuring out exactly how that blew up my stuff since the problem is easy enough to get rid of.
Either specify browserify transforms in package.json OR in your gulp file. Not both.

Exclude non-minified files from publish in `project.json` with ASP.NET Core

I am trying to find a proper configuration for the publishOptions inside project.json (ASP.NET Core 1.0 / Full Framework) so that non-minified files are not published.
Official documetation doesn't help much: project.json reference.
Searching for globbing patterns, and finding some artilcles with gulp examples, I came up with this wwwroot/js/**/*!(*.min.js), but it doesn't seem to work.
Is my syntax wrong? Or, it's just that project.json and dotnet publish don't support this syntax?
"publishOptions": {
"include": [
"wwwroot",
"Views",
"Areas/**/Views",
"appsettings.json",
"web.config"
],
"exclude": [
"wwwroot/lib",
"wwwroot/js/**/*!(*.min.js)",
"wwwroot/css/*.less",
"wwwroot/_references.js"
],
"includeFiles": [],
"excludeFiles": []
},
The typical workflow for JavaScript files/libraries management is to use gulp or grunt tasks to copy over the necessary files into the wwwroot folder which may happen on certain events (prebuild, postbuild, project open, clean).
In the latest tooling, the default MVC doesn't include gulpfile.js anymore as the most common usage was to minify and bundle js files, even when no external libraries were used so gulp may be a bit overwhelming for new users.
But it can easily be brought back, when you right-click the bundleconfig.json file in the solution explorer and choose "Bundler & Minifier" > "Convert to Gulp".
This creates a gulpfile.js and package.json (nodejs dependencies) in the root of your project and adds npm folder to the "Dependencies" section of Solution Explorer. When you watch in the Windows Explorer, you'll see a node_modules folder in the project root folder. That's where npm will download all packages and it's dependencies.
The generated gulpfile.js looks like this and has a few predefined tasks. i won't use this file as example, as it is strongly based on the bundleconfig.json and it's structure and use my gulpfile.json which used to be shipped with older templates.
"use strict";
var gulp = require("gulp"),
rimraf = require("rimraf"),
concat = require("gulp-concat"),
cssmin = require("gulp-cssmin"),
uglify = require("gulp-uglify");
var webroot = "./wwwroot/";
var paths = {
app: webroot + "app/",
libs: webroot + "lib/",
js: webroot + "js/**/*.js",
minJs: webroot + "js/**/*.min.js",
css: webroot + "css/**/*.css",
minCss: webroot + "css/**/*.min.css",
concatJsDest: webroot + "js/app.min.js",
concatCssDest: webroot + "css/app.min.css"
};
gulp.task("clean:js", function (cb) {
rimraf(paths.concatJsDest, cb);
});
gulp.task("clean:libs", function (cb) {
rimraf(paths.libs, cb);
});
gulp.task("clean:css", function (cb) {
rimraf(paths.concatCssDest, cb);
});
gulp.task("clean", ["clean:js", "clean:css", "clean:libs"]);
gulp.task("min:js", function () {
return gulp.src([paths.js, "!" + paths.minJs], { base: "." })
.pipe(concat(paths.concatJsDest))
.pipe(uglify())
.pipe(gulp.dest("."));
});
gulp.task("min:css", function () {
return gulp.src([paths.css, "!" + paths.minCss])
.pipe(concat(paths.concatCssDest))
.pipe(cssmin())
.pipe(gulp.dest("."));
});
gulp.task("min", ["min:js", "min:css"]);
gulp.task("libs", function (cb) {
gulp.src([
'bootstrap/**/*.js',
'bootstrap/**/*.css',
'jquery/**/*.js`, // we can also limit this to `jquery/dist/**/*.js to only include distribution files
'jquery/**/*.css'
], {
cwd: "node_modules/**"
})
.pipe(gulp.dest(paths.libs));
});
gulp.task("app", function (cb) {
gulp.src([
'app/**.js'
])
.pipe(gulp.dest(paths.app));
});
gulp.task("default", ['clean', 'libs']);
It looks more complicated than it actually is. There are several minizier tasks (min:js, min:css) and one general minifier task min which just runs all others in sequence.
A clean task which deletes the output file(s) from wwwroot. When converting from the template, it deletes only the default wwwroot/js/site.min.js file.
Since there are no javascript libraries used in the default template, except of what's inside the wwwroot/lib folder already the packages are not handled that way.
So first thing you may want is to grab bootstrap and jquery from npm rather than the static versions provided by the template. So we add the dependencies to the package.json.
{
"name": "app",
"version": "0.0.0",
"private": true,
"dependencies": {
"bootstrap": "3.3.6",
"jquery": "2.2.0"
},
"devDependencies": {
"gulp": "3.8.11",
"gulp-concat": "2.5.2",
"gulp-cssmin": "0.1.7",
"gulp-uglify": "1.2.0",
"rimraf": "2.2.8"
}
}
The libs task from the gulpfile.js above for example will copy over all required files of a package to wwwroot. I said required, because in the packages there are often unbundled files for debugging and stuff, which we usually don't want inside wwwroot (they can grow quite big).
gulp.task("libs", function (cb) {
gulp.src([
'bootstrap/**/*.js',
'bootstrap/**/*.css'
], {
cwd: "node_modules/**"
})
.pipe(gulp.dest(paths.libs));
});
It will look for all *.js and *.css files within the bootstrap folder in node_modules folder and copy them over to path.libs which is configured as wwwroot/lib/.
The app task does the same for our own code. clean clears the folders and (i.e. before switching from debug to release build or before publishing).
Finally you can bind the tasks to certain VS Events. You need to open the "Task Runner Explorer" View (View > Other Window > Task Runner Explorer). There you can choose a task and right-click it, then "Binding" and choose one of the binding (Before Build, After Build, Clean, Projct Open). They are pretty self explaining, "Clean" means when you do "Build > Clean Solution".
Now to the publishing part. You can run certain command, when you publish your application (either via dotnet or Visual Studio).
In the project.json there is a scripts section for this.
"scripts": {
"prepublish": [ "npm install", "bower install", "gulp clean", "gulp min", "gulp libs" ],
"postpublish": [ "dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%" ]
}
Each of the entries "prepublish" is one command to be executed. In this example, before the publishing begins, npm install will be executed first in order to restore all npm dependencies. Then bower install to install the dependencies managed by bower (remove it if you don't use bower and do all via npm).
The next three commands are the interesting ones, they will execute gulp tasks. We can also simplify this by adding a "publish" task.
gulp.task("publish", ['clean', 'libs', 'min']);
"scripts": {
"prepublish": [ "npm install", "bower install", "gulp publish" ],
"postpublish": [ "dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%" ]
}
This will copy all the necessary files for publishment into the wwwroot folder, publish the files and then call the "postpublish" scripts.
That's a rough introduction in gulp. It's has a learning curve, but once you get it working it imrpoves the overall workflow.
What's not covered here is to add a watch task which may look into a certain folder (I usually use app folder in the project root) and when any file changes there run the app task, so the our code gets minifed and copied over to wwwroot and is available when we debug it.
A simple alternative is:
Rename unminified source to *.debug.js and *.debug.css
They are now easier to exclude:
"publishOptions": {
"include": [
"wwwroot"
],
"exclude": [
"wwwroot/**/*.debug.*"
]
}
IMHO unminified source should stick out and look abnormal. It is more deserving of a file name wart than minified code.
This also brings the build output files into line with the rest of the .Net build configuration. It makes it clear that your debug versions may well include extra logging and debug utilities and that its not for production.