NodeJS execSync is File Exist using Bash Script - javascript

I'm trying to use unix utils in nodejs. I'm testing advantages. I have a function like that:
function unix_creat(src){
if(src != undefined && typeof src === 'string'){
const { execSync } = require("child_process");
if(execSync(`if [ -f "${src}" ]; then echo "1"; else echo "0"; fi`, {encoding: 'utf8'}).includes(1) === true){
return(1);
} else { return(0); }
} else { return(0); };
};
return(unix_creat('test.js'));
In this code, execSync(`if [ -f "${src}" ]; then echo "1"; else echo "0"; fi`, {encoding: 'utf8'}).includes(1) === true) part has problems. When I console.log this, I get valid output. When I launch all code, I get this:
user#pc:~/Project/UnixCommand$ node index.js
{}
How can I get 1 or 0 ?
** I use .includes(1) part because output is somehow weird:
1
{}

Oh I solved. Actually there's no problem at all. I just used my index.js file as module. I was making module so that make sanse.

Related

How to replace file data

In my folder I have app.js, app.test.js and config.json
My config.json is filled with the correct information but I want to test the negative scenario, when the file does not contain any data data.length === 0
How can I replace the config.json for the test without actually replacing the file correct data?
const fileData = fs.readFileSync(path.resolve(__dirname, './config.json'));
const data = JSON.parse(fileData);
if (!data || data.length === 0) {
console.error('data is required!');
return;
}
...
// Test
it('#lambdaHandler should validate data configuration file', async() => {
const response = await app.myFunction();
});
You can try a simple solution that would involve duplicating the file and emptying it or simply creating a new one from scratch and doing the text on the latter.
Anyway, be careful, the JSON.parse function can throw an exception. It correctly handles the exception that might be created with a try/catch block (do it now). For example, if you parse an empty file it should return error since an empty string is not eligible for JSON.parse.
Below is an implementation I made to test that it worked
const fs = require( "fs");
const path = require( "path")
const fileData = fs.readFileSync(path.resolve(__dirname, './config.json'));
try{
const data = JSON.parse(fileData);
if (Object.keys(data).length === 0) {
console.error('Data is required! Please provide json with data');
}else{
console.error('Yes! Json loaded correctly with data');
console.log(data)
}
}catch(error){
console.log("Parsing json operation, failed");
}

recursive function in NodeJS to check file or directory

I'm trying to build a function in NodeJS which recursively check whether it is file or directory using fs library to infinitely deep sub-directories, my code is something like this:
function generateComponents(path) {
fs.readdirSync(path).forEach((file) => {
if(fs.existsSync(file) && fs.lstatSync(file).isDirectory()) {
generateComponents(path+'/'+file);
}
else {
//Do some code
}
});
}
It works for first folder/directory but when it goes for next directory it accepts as files and condition goes into else part. Am I doing something wrong?
One problem is that file in your code is JUST a filename. To recurse you have to recombine the filename with the path in order to call generateComponents in a directory that's different than the original path. That includes when you call fs.existsSync() and fs.lstatSync():
const path = require('path');
function generateComponents(dir) {
fs.readdirSync(dir).forEach((file) => {
let fullPath = path.join(dir, file);
if (fs.lstatSync(fullPath).isDirectory()) {
console.log(`directory: ${fullPath}`)
generateComponents(fullPath);
} else {
console.log(`filename: ${fullPath}`)
//Do some code
}
});
}
FYI, you should also use the withFileTypes option for fs.readdirSync() as that will save you the fs.lstatSync() call and the fs.existsSync() call is entirely unnecessary. fs.readdirSync() just told you the file was there, you don't have to check if it's there again.
That simplified version using withFileTypes would look like this:
const path = require('path');
function generateComponents(dir) {
fs.readdirSync(dir, {withFileTypes: true}).forEach((entry) => {
let fullPath = path.join(dir, entry.name);
if (entry.isDirectory()) {
console.log(`directory: ${fullPath}`)
generateComponents(fullPath);
} else if (entry.isFile()) {
//Do some code with fullPath file
console.log(`filename: ${fullPath}`)
} else {
// apparently there are some other things that could be here
// like a symlink, so this is defensive coding
console.log(`unexpected type: ${fullPath}`);
}
});
}

How to execute local bash code from VSCode extension

I am creating an extension for simple git commands, and when a user enters a command in the Command Palette, like Init, I want to call git init on their current directory.
Unfortunately, there is no documentation on executing code locally with the VSCode extensions API. Is there any way to do this?
Yes, this is possible, by using child_process.spawn. I have used it in my extension to run a Java jar. The core of the execution is shown here:
let spawnOptions = { cwd: options.baseDir ? options.baseDir : undefined };
let java = child_process.spawn("java", parameters, spawnOptions);
let buffer = "";
java.stderr.on("data", (data) => {
let text = data.toString();
if (text.startsWith("Picked up _JAVA_OPTIONS:")) {
let endOfInfo = text.indexOf("\n");
if (endOfInfo == -1) {
text = "";
} else {
text = text.substr(endOfInfo + 1, text.length);
}
}
if (text.length > 0) {
buffer += "\n" + text;
}
});
java.on("close", (code) => {
// Handle the result + errors (i.e. the text in "buffer") here.
}

Error: Unknown type: typeaheadjs while running from grunt jasmine:coverage

I'm testing edit in place module and I have this in my spec file:
if (typeof module !== 'undefined' && module.exports) {
var jsdom = require('jsdom').jsdom;
global.document = jsdom('<html></html>', {});
global.window = document.defaultView;
global.jQuery = global.$ = global.window.jQuery = require('jquery');
global.navigator = {
userAgent: ''
};
$.platform = $.platform || {};
require('../runtime/platform/js/modules/platform.editInPlace.js');
require('../runtime/platform/js/modules/platform.formSupport.js');
require('../runtime/vendor/parsleyjs/2.2.0-rc1/dist/parsley.js');
require('../runtime/vendor/bootstrap/3.1.1/js/bootstrap.js');
require('../runtime/vendor/x-editable/1.5.1/bootstrap3-editable/js/bootstrap-editable.js');
require('../runtime/vendor/typeaheadjs/0.9.3/typeahead.js');
require('../runtime/vendor/x-editable/1.5.1/inputs-ext/typeaheadjs/typeaheadjs.js');
require('../runtime/platform/js/modules/platform.utility.js');
}
when I'm running grunt test:coverage (using instanbul) it throw exception (when I'm initializing edit in place type typaheadjs).
encountered a declaration exception......×
Error: Unknown type: typeaheadjs in file:///C:/Launchpad/synergy/src/main/resources/runtime/vendor/jquery/2.1.4/jquery.js (line 250) (1)
(line 250 is error function that throw exception with specified message)
but it work fine when I call that spec from node when I add this code:
function describe(str, callback) {
callback();
}
function it(str, callback) {
callback();
}
function expect() {
return {toEqual: function() {}};
}
Any clue why I got this error when I'm running jasmine from grunt?
EDIT:
I've included console.log in both typeahead files and only the first one shows up when I run from grunt, it show both when I'm running from node.
I was executing the spec using phantomjs so the code inside:
if (typeof module !== 'undefined' && module.exports) {
}
was never executed, to add typeaheadjs.js I've needed to add vendor file inside grunt file.

Node.js - child_process.exec and output redirection

I'm trying to write a file templating script using Node.js. I have a JSON file called template.json which stores template information. The idea behind my script is that, if I type something like:
tmpl.js java Joe
it will do the following:
Call touch Joe.java
Read template.json to get the template for Java files
Use its information to replace all the placeholders with Joe
Write the result to Joe.java
Execute emacsclient Joe.java
Now, I wrote this script as follows:
#!/usr/local/bin/node --harmony
var templates = require('./config/template.json'),
args = process.argv;
if (args.length < 4) {
console.log("Not enough arguments!");
}
else {
var type = args[2],
name = args[3];
if (type in templates) {
var tmpl = templates[type],
contents = make_output(tmpl["format"],name),
file_name = name + tmpl["extension"],
command = "touch " + file_name + " && echo -e '" + contents +
"' &> " + file_name + " && emacsclient " + file_name;
invoke(command);
}
else {
console.log("No template for %s", type);
}
}
//Helpers
//Invokes comm with args in the terminal, returns all output
//Does not play nice with command redirection
function invoke(comm) {
var exec = require('child_process').exec,
child = exec(comm,
function (error, stdout, stderr) {
if (error !== null) {
console.log(stderr);
}
});
}
//If template is a format string, processes it with x as the
//replacement. Otherwise, just evaluates.
//Limited to one replacement at most.
function make_output(template, x) {
if(/.*\%s.*/i.test(template)) {
var util = require('util');
return util.format(template,x);
}
else {
return template;
}
}
Basically, the command it ends up building is something like:
touch Joe.java && echo -e `bunch of template stuffs` &> Joe.java && emacsclient Joe.java
Now, the problem I am getting is that the above command relies on output redirection, which my invoke command doesn't deal with very well - specifically, everything executes, but I get an empty file! Is there a way I can change either invoke or what I'm constructing to be invoked to avoid this problem?
The issue is that Node's child_process.exec starts sh but you are using features that are peculiar to bash. The &> is interpreted as & > in sh (two operators: a control operator and a redirection operator) and echo -e will use sh's builtin implementation of echo, which does not understand -e.
It would probably be possible to work around the issues above but using the shell like you do is fragile. For instance if your template contains single quotes ('), these quotes may interfere with the single quotes you use in your command. A more robust way to do it would be to change the main part of your code to use fs.writeFileSync rather than using shell commands to write to your file:
var templates = require('./config/template.json'),
fs = require("fs"),
args = process.argv;
if (args.length < 4) {
console.log("Not enough arguments!");
}
else {
var type = args[2],
name = args[3];
if (type in templates) {
var tmpl = templates[type],
contents = make_output(tmpl["format"],name),
file_name = name + tmpl["extension"],
command = "emacsclient " + file_name;
fs.writeFileSync(file_name, contents);
invoke(command);
}
else {
console.log("No template for %s", type);
}
}
You'd also want to modify make_output to perform the transformations that echo -e would have done for you.

Categories