Grunt - get current calling folder, and not gruntfile current folder - javascript

If I have Grunt installed in some folder /foo, but my current folder is /foo/bar/baz, and I run "grunt sometask" from within my current folder, how can I get Grunt (or NodeJS for that matter) to determine my current path? That is to say, how can I programmatically GET the folder I was in when I called grunt?
When I use process.cwd(), I get the path of the gruntfile, ie, "foo", which is not what I want.
I don't have to do this in Grunt specifically, any nodejs-based solution would work.

According to the source code:
By default, all file paths are relative to the Gruntfile
And, voilá, this line of code shows how grunt actually changes the current directory to the path of the Gruntfile:
process.chdir(grunt.option('base') || path.dirname(gruntfile));
However, option --base is there for just that. See docs: http://gruntjs.com/api/grunt.file
If you don't need to do it from inside the Gruntfile, simply run a script that captures the process.cwd() and then execs grunt.
See: https://www.npmjs.com/package/exec
var exec = require('exec');
process.cwd(); // Will have your current path
exec(['grunt', 'mytask'], function(err, out, code) {
if (err instanceof Error)
throw err;
process.stderr.write(err);
process.stdout.write(out);
process.exit(code);
});

in the Mac or Linex, you can get this by
process.env.PWD
in the windows, unknown
You can edit the grunt-cli to get finish this.
grunt-cli/bin/grunt
require(gruntpath).cli({_originDir:basedir});
then in the gruntfile.js, you can follows:
grunt.option('_originDir')

Related

Is it necessary to specify directory when using appendFileSync?

I'm going through some of the nodejs documentation and starting to familiarize myself with some of the more basic functions. Specifically looking at appendFileSync function.
When trying to append a file, is it necessary to specify the directory? I don't recall this being a requirement in previous versions of Node but it seems when the directory is not specified, a new file is created in the root instead of appending the file.
I'm just trying to append a basic txt file, with this it creates a new file:
const fs = require('fs');
fs.appendFileSync('notes.txt', 'Changing the text with appendFileSync');
However, when specifying the directory, it appends the file just fine making me think this is required:
const fs = require('fs');
fs.appendFileSync('./nodejs/notes-app/notes.txt', ' Colin, changed the
text with appendFileSync', function (err) {
if (err) throw err; console.log('Notes updated');
});
Node -v 12.13.0
NPM -v 6.12.0
As with all fs operations that take a file path, if you don't specify any sort an absolute path, then the path you do specify is combined with the current working directory. In a nodejs program, the default current working directory (if you don't change it programmatically) is taken from the environment in which you started the node program.
If want to control the path directly without regard to the current working directory, then specify an absolute path.
This is what the fs module documentation says about file paths:
String form paths are interpreted as UTF-8 character sequences identifying the absolute or relative filename. Relative paths will be resolved relative to the current working directory as specified by process.cwd().
Note: For some situations, a developer wants to access the file system relative to the installation of the module that is running. That is typically done by building a path that is relative to __dirname which is the location of the current module like this.
path.join(__dirname, "somefile.txt");
Of course, you can always specific a full path name starting from root if you want.

require.resolve not finding file even though fs can

I'm having a problem with node.js require.resolve the method that makes no sense having with the test I'm running first.
So my Code
let checkPluginCanLoad = (pluginName, pluginFile) => {
return new Promise((res, rej) => {
// build the plugin's class files path
console.log(`looking for file at ${path}/${pluginName}/${pluginFile}`)
let req = `${path}/${pluginName}/${pluginFile}`
// check it exists blocking
let fileState = fs.existsSync(`${req}.js`);
if(fileState){
console.log(`File ${req}.js ${fileState?"exists.":"does not exist."}`);
// it exists try to load it
let plugin = require.resolve(`${req}`);
res(plugin);
}else{
// could not find or load the plugin
rej(`Plugin is invalid can't find or load class for ${pluginFile}`);
}
});
}
The vars are set to , path = "Plugins", pluginName = "TestPlugin", pluginFile = "TestPlugin";
My output is
Plugins from 'Plugins' have been loaded. index.js:36
looking for file at Plugins/TestPlugin/TestPlugin Plugins.js:133
File Plugins/TestPlugin/TestPlugin.js exists. Plugins.js:138 failed to
load plugin 'TestPlugin' with error 'Error: Cannot find module 'Plugins/TestPlugin/TestPlugin''
The final line
load plugin 'TestPlugin' ... comes from the system above this one catching the rejection.
So the file Exists according to FileSystem but the resolver can't find it.
I have tried prepending it with ../ before the path in case it's resolving from the file that is running it and not the application directory,
I have also tried prepending it with ./ in case it's running it from the application directory.
you need to add ./ to tell node that you are targeting local file.
let plugin = require.resolve(`./${req}`);
if you forgot node will search in steps described here
So this is a bug caused by symlinks on windows with junctioned directories,
So for my dev environment it junctions the directories from my Git Repository directory. but Node is running it through the junction directory but seeing the original directory.
E.G
Git repo is in D:\Projects\NodeAppRepo
then the dev environment is running inside D:\Project\NodeApp\
I have index.js, Core/, node_modules/ all running via a junction inside the NodeApp to the paths in the git repo.
so i'm running node index.js inside D:\Project\NodeApp\ wich is in turn loading D:\Project\NodeApp\Core\Core.js this then imports ./Plugins.js this is where the break happens because the path node has for plugins is not D:\Project\NodeApp\Core\Plugins.js it is D:\Projects\NodeAppRepo\Core\Plugin.js

Gulp Copy content from one file to another file

I am trying to copy the content from one file to another. I am trying the following code but its throwing me an error.
gulp
.src('core/core.config.local.tpl.js')
.pipe(gulp.dest(core/core.config.js));
Error: EEXIST: file already exists, mkdir 'C:\Users\krish\Documents\test\app\core\core.config.js'
at Error (native)
Is there any other process that I could use to copy content?
gulp.dest expects a directory as an argument. All files are written to this destination directory. If the directory doesn't exist yet, gulp tries to create it.
In your case gulp.dest tries to create a directory core/core.config.js, but fails since a regular file with the same name already exists.
If your goal is to have the regular file at core/core.config.js be overwritten with the contents of core/core.config.local.tpl.js on every build, you can do it like this:
var gulp = require('gulp');
var rename = require('gulp-rename');
gulp.task('default', function() {
gulp.src('core/core.config.local.tpl.js')
.pipe(rename({ basename: 'core.config'}))
.pipe(gulp.dest('core'));
});
I think you were missing the quotes only when entering the the question here, right?
gulp.dest() expects a folder to copy all the files in the stream, so you cannot use a single file name here (As the error says: "mkdir failed"). See: https://github.com/gulpjs/gulp/blob/master/docs/API.md#gulpdestpath-options
When you do your gulp.src() you can set a base path to build the relative path from and so gulp can copy your single file to the given output folder. See: https://github.com/gulpjs/gulp/blob/master/docs/API.md#optionsbase
As you also want to rename the file, you need something like gulp-rename: https://www.npmjs.com/package/gulp-rename

Loading grunt tasks from a remote Gruntfile.js

In the root directory of a project, I'm trying to load Grunt tasks, and all the content of the file as well, from a remote Gruntfile.js, accessible through a network (web or internal network).
I've already tried several things (see below), first hosting the Gruntfile.js on a local Apache server for the tests.
Using the --gruntfile option
> /project/path> grunt --gruntfile=http://localhost/Gruntfile.js build
Reading "Gruntfile.js" Gruntfile...ERROR
Fatal error: Unable to find "/project/path/http://localhost/Gruntfile.js" Gruntfile.
Using the --base option
> /project/path> grunt --base=http://localhost/Gruntfile.js build
process.chdir(grunt.option('base') || path.dirname(gruntfile));
Error: ENOENT, no such file or directory
Creating a Gruntfile.js located at the root directory of my project, which contains only the following code :
module.exports = function (grunt) {
grunt.loadTasks( 'http://localhost/Gruntfile.js' );
};
The result was :
> /project/path> grunt build
>> Tasks directory "http://localhost/Gruntfile.js" not found.
Warning: Task "build" not found. Use --force to continue.
Aborted due to warnings.
Another try with the Gruntfile.js
module.exports = function (grunt) {
require( 'http://localhost/Gruntfile.js' )( grunt );
};
Gave me this :
> /project/path> grunt build
Loading "Gruntfile.js" tasks...ERROR
>> Error: Cannot find module 'http://localhost/Gruntfile.js'
Warning: Task "build" not found. Use --force to continue.
Aborted due to warnings.
Edit: It seems there is no way of loading tasks from a grunt file not located on the disk. I will find another solution.
I ran into the same problem and this is my solution. I hope it helps someone in the present/future:
Create a npm package to host the Gruntfile.js and upload it to a repository (I´am currently using Bitbucket) This is how my package.json looks like:
{
"name": "my-remote-gruntfile-package",
"private": true,
"version": "0.0.1"
}
Configure it in the package.json of your current project and install it using npm install or just run
npm install git+ssh://git#bitbucket.org:user/my-remote-gruntfile-package.git#0.0.1
Create a bash script (or windows bash equivalent) to cover the problem of changing Gruntfile.js location and setting current base path. This is to avoid passing --gruntfile and --base parameters on every execution (this step is not mandatory)
#!/bin/bash
grunt --base ./ --gruntfile ./node_modules/my-remote-gruntfile-package/GruntFile.js $1
Note: take care of relative paths used on your Gruntfile.js
Requiring a separate file should work, note that you shouldn't refer to it via localhost, but rather the location on disk, for example ./somedir/yourtask.js. Here's an example:
yourtask.js:
module.exports = {
// your task config goes here
};
Your Gruntfile.js:
module.exports = function(grunt) {
var externalFile = require('./somedir/yourtask.js');
grunt.initConfig({
// some random tasks go here
yourtask: externalFile
});
};
This should work but I'm not able to run it right now and you haven't posted what kind of info you have defined in your separate file. You can also have a function in there as well.

How to make Grunt search a specific directory for node modules

Grunt looks in the same folder for node_modules, but how can I tell it to look in a different folder path? I want it to look in "./js/vendor" for its modules
This seems to work as described in the issue #696 on Grunt's GitHub issue tracker.
// if you want to overload the directory on the CLI
grunt --dir=<your dir to search>
// example CLI command (relative to Gruntfile)
grunt --dir=${PWD}/js/vendor2
/**
* Add the following code to your
* Gruntfile.
*/
// set the custom or default directory
var customDir = grunt.option('dir') || process.cwd() + '/js/vendor';
// get the current working directory
var cwd = process.cwd();
// switch to custom directory (contains node_modules folder)
process.chdir(customDir);
// load taks(s)
grunt.loadNpmTasks('grunt-browserify2');
// switch back to original directory
process.chdir(cwd);

Categories

Resources