Including concatenated scripts asynchronously with gulp.js - node.js

I'm trying to do the following:
gulp.src('js/*.js')
.pipe(concat('_temp.js'))
.pipe(gulp.dest('js/'));
gulp.src('build/js/app.js')
.pipe(replace('// includes', fs.readFileSync('js/_temp.js')))
.pipe(uglify())
.pipe(rename('app.min.js'))
.pipe(gulp.dest('build/js'));
So, I'm concatenating all .js files in js/. The concatenated file is named _temp.js;
After that, I'm reading a app.js and try to replace the // includes string with the concatenated _temp.js file. This doesn't work as node says the file doesn't exist. It does exist though, so I second time I run this task, it works.
This has most probably to do with asynchronisity, but I'm unable to see how I would do this differently?

You can split your task into 2 and make one of the tasks run after another by using Gulp's dependency resolution system.
gulp.task('task1', function () { ... });
gulp.task('task2', ['task1'], function () { ... });

Related

Node.js package script that runs every time a file is changed

I'm developing a node.js package that generates some boilerplate code for me.
I was able to create this package and if I run every module individual it works fine and generates the code as expected.
My idea now is to import this package in another project and have it generate the code.
I have no idea to how to achieve this or even if it's possible.
The perfect solution would be that every time a file changed in a set of folders it would run the package and generate the files but if this isn't possible it would be ok as well to expose or command to manually generate this files.
I have created a script to run the generator script but it only works on the package itself and not when I import it in another project.
Thanks
I think you want the fs.watch() function. It invokes a callback when a file (or directory) changes.
import { watch } from 'fs';
function watchHandler (eventType, filename) {
console.log(`event type is: ${eventType}`) /* 'change' or 'rename' */
if (filename) {
console.log(`filename provided: ${filename}`)
} else {
console.log('filename not provided');
}
}
const options = { persistent: true }
const watcher = fs.watch('the/path/you/want', options, watchHandler)
...
watcher.close()
You can use this from within your nodejs app to invoke watchHandler() for each file involved in your code generation problem.

Simulating Command Line Entries For Node Tests

I am writing some tests for a Node/MongoDB project that runs various modules via command line entries. My question is, for the tests, is there a way I can simulate a command line entry? For instance, if what I write in the command line is:
TASK=run-comparison node server
... is there a way I can effectively simulate that within my tests?
The common practice here as far as I know, is to wrap as much of your app as you can within a function/class where you pass the arguments, so you can easily test it with unit tests:
function myApp(args, env){
// My app code with given args and env variables
}
In your test file:
// Run app with given env variable
myApp("", { TASK: "run-comparison"});
In your particular case, if all your tasks are set through env variables, through editing of process.env, mocks, or .env files you may be able to test that without modifications on your code.
If that is not enough for your case (i.e. you really need to exactly simulate command line execution) I wrote a small library to solve this exact issue some time ago: https://github.com/angrykoala/yerbamate (I'm not sure if there are other alternatives available now).
With the example you provided, A test case could be something like this:
const yerbamate = require('yerbamate');
// Gets the package.json information
const pkg = yerbamate.loadPackage(module);
//Test the given command in the package.json root dir
yerbamate.run("TASK=run-comparison node server", pkg.dir, {}, function(code, out, errs) {
// This callback will be called once the script finished
if (!yerbamate.successCode(code)) console.log("Process exited with error code!");
if (errs.length > 0) console.log("Errors in process:" + errs.length);
console.log("Output: " + out[0]); // Stdoutput
});
In the end, this is a fairly simple wrapper of native child_process which you could also use to solve your problem by directly executing subprocesses.

Problems when trying to create rev.manifest

I'm trying to change a task from my gulpfile to create a rev manifest to be used in another moment. After this code work, I will add gulp-sourcemap to create some sourcemaps. But, this simple thing need to work first.
The objective is concatenate some scripts that are in scripts folder and inside a scripts subfolder (like 'c.js'), apply rev in this new script, vendor.js, and then fullfill the rev manifest to be used on another task.
I'm not a expert in Node.js or Gulp. It's de very first time I try to do this. So, it would be a stupid thing I forgot.
Here is my code (modified to look like an example) and thanks in advance
var vendorJs = ['scripts/a.js','scripts/b.js','scripts/anotherFolder/c.js'];
gulp.task("concat-vendor-js", function () {
return gulp.src(vendorJs)
.pipe(concat('vendor.js'))
.pipe(uglify())
.pipe(rev())
.pipe(gulp.dest('dist/Scripts'))
.pipe(rev.manifest())
.pipe(gulp.dest('dist'));
}
I'm getting this on my rev-manifest.json:
{
"/vendor.js": "/vendor-66687d0f7d.js"
}
But it should be like this:
{
"Scripts/vendor.js": "Scripts/vendor-66687d0f7d.js"
}

Is it possible in Node to read in a file an export its contents (without exporting asyncronly)?

TLDR: I want to read in a file's contents and then export a function which relies on those contents ... without making that exported function use promises or some other form of asynchronicity.
I'm trying to write an XML-validating module, and in order for it to do its thing I need to read in an XSD file. However, this only needs to happen once at "load time", so ideally I'd rather not have other modules that use my function have to wait for a promise to resolve to get their results. If I were using Webpack this would be easy, as I could use it's text file loader to bring in the XSD as if it were any other module ... but unfortunately I'm not.
In other words, currently I have to do (borderline pseudo-code):
module.exports.validate = () =>
new Promise((resolve) =>
fs.readFile(path, (file) => {
// use file to validate, then:
resolve(validationResult);
});
});
};
and instead I'd like to do:
fs.readFile(path, (file) => {
module.exports.validate = myValidationFunction;
});
But the above doesn't work because you can't export from callbacks, so my question is, is there any other way to accomplish this?
The https://github.com/jonschlinkert/to-exports library seems to offer exactly this, so it seems like it's possible ... but it doesn't work for me :(
P.S. At worst I could literally wrap the contents of the file inside the template string characters, rename the file to be .js, and export it that way:
module.exports = `*XSD contents go here*`;
However, that seems very kludgy, so I'm hoping there is a better way.
If you want to read a file synchronously, then use fs.readFileSync. It returns the contents of the file or throws an error.

Unable to delete a file with nodejs in protractor

I'm trying to delete the file with nodejs fs and I notice that file has been generated then trying to delete (failed to delete the file) while the file is not even uploaded on browser with protractor. Generate and delete file functions are created using nodejs fs.
So how can I put them in a way then wait until file is uploaded then delete the file?
helper.generateFile(filePath);
helper.uploadFile(UploadButtonElement, filePath);
uploadButtonElm.click();
helper.deleteFile(filePath);
Is there a way to execute deleteFile only when below two actions are completed.
helper.uploadFile(UploadButtonElement, filePath);
uploadButtonElm.click();
Thanks.
Protractor operations schedule promises to do things. They do not actually do them. Thus, your helper functions will end up running well before any of the protractor code actually accomplishes what you asked. Use then to chain your dependencies explicitly. Like so:
helper.generateFile(filePath);
helper.uploadFile(UploadButtonElement, filePath);
uploadButtonElm.click().then(function() {
helper.deleteFile(filePath);
});
Please read https://github.com/angular/protractor/blob/master/docs/control-flow.md and https://code.google.com/p/selenium/wiki/WebDriverJs#Understanding_the_API
function deleteAlreadyDownloadedFiles(extension,username) {
    let os = require('os');
    console.log('USERNAME HERE IS'+require("os").userInfo().username);
    var downloadDirectory = '/Users/'+require("os").userInfo().username+'/Downloads/';
    const fs = require('fs');
    const path = require('path');
    const directory = '/Users/'+require("os").userInfo().username+'/Downloads/';
    fs.readdir(directory, (err, files) => {
        if (err) throw err;
         for (const file of files) {
            fs.unlink(path.join(directory, file), err => {
                if (err
                    && (err.code === "EACCES" || err.code === "EPERM")) {
                    console.log("Retrying rename file: ")
                    return;
                }
            });
        }
    });
}

Resources