Change other file inside EventStream of other gulp - gulp

I have one interesting question. Is it possible to change some file inside open stream (EventStream) inside gulp?
I have that stuff. I want to read some file inside opened stream and write that stuff to other file. How I can do it? Thanks.
gulp.task('handleGlobalStorage', function () {
return gulp.src('./global_storage.js')
.pipe(setEnvHostAndProxy())
.pipe(gulp.dest('./built'));
});
function setEnvHostAndProxy() {
return es.map(function(file, cb) {
var fileContent = file.contents.toString();
//some changes inside content
// if (!gutil.env.dev) return;
/* I have stuff that fetched from file and I modify it that I send it
down to pipe. But also I want to insert this stuff inside other
file. How I can do it? Should I create WritableStream of that file
and merge it ?*/
file.contents = new Buffer(fileContent);
// send the updated file down the pipe
cb(null, file);
});
}

I resolved that issue, here is solution (I will not show all code, only general). The main concept is - open file and write new stuff inside pipe :) that's all.
function setEnvHostAndProxy() {
var bsConfigFileContent = fs.readFileSync('./bs-config.js', 'utf8'),
bsConfigProxyPattern = /(proxyUrl\s?=\s?)["|'](.*)["|']/;
return es.map(function (file, cb) {
var fileContent = file.contents.toString(),
prodHost = fileContent.match(generateRegExpForHosts('prodHost'))[1],
prodProxy = fileContent.match(generateRegExpForHosts('prodProxy'))[1],
devProxy = fileContent.match(generateRegExpForHosts('devProxy'))[1],
devHost = fileContent.match(generateRegExpForHosts('devHost'))[1],
changedBsConfigFileStream,
res;
if (!gutil.env.dev) {
res = prodHandler();
changedBsConfigFileStream = bsConfigHandler(prodHost);
} else {
res = devHandler();
changedBsConfigFileStream = bsConfigHandler(devProxy);
}
fs.writeFile('./bs-config.js', changedBsConfigFileStream, 'utf8', function (err) {
if (err) throw (err);
});
file.contents = new Buffer(res);
cb(null, file);
} });

Related

Run a gulp plugin that requires the current file path and name

I am using purgeCSS to removed unused CSS. My challenge is that I need to do this dynamically. Depending on the current .css file that is being processed, I need to get its path and file name so I can dynamically insert the content HTML path for Purge to run.
Here is how my code looks like:
const gulp = require("gulp"),
appRoot = require("app-root-path"),
sass = require("gulp-sass"),
purgecss = require("gulp-purgecss"),
tap = require("gulp-tap"),
path = require("path"),
utilities = require(appRoot + "/Tools/Utilities-Functions/utilities-functions.js");
gulp.task("sass", () => {
let htmlContentPath = "";
return (
gulp
.src("./Pages/**/*.scss")
// Compile .scss into .css
.pipe(sass())
// Get path for HTML file (dynamic)
.pipe(
tap(function (file, t) {
let fileName = path.basename(file.path);
// This is a simple function that returns the file name without extension (homepage.css >> homepage)
fileName = utilities.getFileNameWithoutExtension(fileName);
htmlContentPath = "/fullPath/Pages/" + fileName + "/compiled/html/" + fileName + ".html";
})
)
// Remove unused CSS
.pipe(
purgecss({
content: [htmlContentPath]
})
)
// Set the destination folder (main css)
.pipe(gulp.dest("./dist/css"))
);
})
For some reason happens that "htmlContentPath" for the Purge is empty. Even though I would expect "tap" plugin to always set a value to it. As a result this provokes an error on the purgecss:
As stated above, this error is due to having "htmlContentPath" empty.
Another attempt I tried was to do the Purge inside the Tap plugin, like this:
const gulp = require("gulp"),
appRoot = require("app-root-path"),
sass = require("gulp-sass"),
purgecss = require("gulp-purgecss"),
tap = require("gulp-tap"),
path = require("path"),
utilities = require(appRoot + "/Tools/Utilities-Functions/utilities-functions.js");
gulp.task("sass", () => {
return (
gulp
.src("./Pages/**/*.scss")
// Compile .scss into .css
.pipe(sass())
// Get path for HTML file (dynamic)
.pipe(
tap(function (file, t) {
let fileName = path.basename(file.path);
// This is a simple function that returns the file name without extension (homepage.css >> homepage)
fileName = utilities.getFileNameWithoutExtension(fileName);
let htmlContentPath = "/fullPath/Pages/" + fileName + "/compiled/html/" + fileName + ".html";
// Remove unused CSS
purgecss({
content: [htmlContentPath]
})
})
)
// Set the destination folder (main css)
.pipe(gulp.dest("./dist/css"))
);
})
This time it doesn't give an error, but the Purge is totally ignored...
Any solution on how I could solve this?
After attempting dozens of approaches here is the one that worked for me and thought would be worth sharing with others that might be going through a similar challenge:
const gulp = require("gulp"),
appRoot = require("app-root-path"),
sass = require("gulp-sass"),
path = require("path"),
utilities = require(appRoot + "/Tools/Utilities-Functions/utilities-functions.js"),
fs = require("fs"),
through = require("through2"),
uncss = require("uncss");
gulp.task("sass", () => {
return (
gulp
.src("./Pages/**/*.scss")
// Compile .scss into .css
.pipe(sass())
// Remove unused CSS
.pipe(
through.obj(function(file, encoding, callback) {
try {
const cssFileContent = file.contents.toString(); // Get the css file contents
let transformedFile = file.clone(), // Clone new file for manipulation
fileName = path.basename(file.path),
htmlFilePath;
// This is a simple function that returns the file name without extension (homepage.css >> homepage)
fileName = utilities.getFileNameWithoutExtension(fileName);
// File path for the .html file
htmlFilePath = "/fullPath/Pages/" + fileName + "/compiled/html/" + fileName + ".html";
// Check if there is any css to be checked and if .html file exists
if (cssFileContent.length && fs.existsSync(htmlFilePath)) {
// Call uncss to remove unused css
uncss([htmlFilePath], { raw: cssFileContent }, function(error, output) {
if (error) {
callback(null, transformedFile);
}
// Set new contents with the "used" css only (uncss' output)
transformedFile.contents = Buffer.from(output);
callback(null, transformedFile);
});
} else {
callback(null, transformedFile);
}
} catch (e) {
console.log("Gulp error - uncss: " + e.message);
callback(null, transformedFile);
}
})
)
// Set the destination folder (main css)
.pipe(gulp.dest("./dist/css"))
);
});
Basically I built a custom gulp stream using through. This allows you to read information about the current file processed, do whatever logic you want, and then invoke callback with the new transformed file.
In more details what I have done:
Read file information (file name and its location)
Get the location for the HTML I want to check my CSS against
Run uncss (instead of purgecss I was using initially) because on this tool I can send raw CSS which is handy in my case
From the output of uncss, I affect the contents of the CSS file with this output
Invoke callback with this new transformed file

uploading a file (photo), save it to a local folder as a string (to the Database) and show it from the specific folder as jpg

i got this project in React , and the Admin can add Vacations manually (in modal bootstrap) - and show it on the screen.
one of the requirements is that he can upload an existing file (photo) which will use as a photo of the vacation he adds.
the picture need to be sent to the server as and be save to Uploads file (of all the images of the vacations) , and be saves as a string (in the database) to the location of the specific folder(and to be shown on the screen of course.)
im trying to use npm express-fileupload / save it as base 64 to image but both of the methods are not working...
router.post('/addvacation', async (req, res, next) => {
console.log(req.body);
const imgPath = 'should be uploaded to the Uploads file and make it as a string to the location of the specific folder.';
//saveImage(req.body.image,req.body.name);
let insertQuery = `
INSERT INTO users.vacations (name, price, start, end, followers ,image, description )
VALUES ('${req.body.name}' , ${req.body.price},'${req.body.start}' , '${req.body.end}', '[]' , '${imgPath}', '${req.body.description}' )
`;
const itemData = {...req.body,image: imgPath };
try {
await pool.query(insertQuery);
}
catch(e) {
console.error(e.message);
res.status(401).json("Fail");
return;
}
ws.io.emit('add', itemData);
res.status(200).json("OK");
});
i also tried to use this code but it didnt work also.
// function saveImage(data,name) {
// var fs = require('fs');
// var bytes = data.split("%");
// var b = new Buffer(bytes.length);
// var c = "";
// for (var i = 0;i < bytes.length;i++) {
// b[i] = bytes[i];
// c = c + " " + bytes[i]
// }
// fs.writeFile(`../public/uploads/${name}.jpg`, c, "binary",function(err) {
// if(err) {
// console.log(err);
// } else {
// console.log("The file was saved!");
// }
// });
// return `localhost:3000/public/uploads/${id}.jpg`;
// }

Reading JSON file in angular 2 application

I have a file data.json which I want to import in my angular 2 application. I am getting file with HTML input tag.
<input type="file" (change)="onImport($event)"/>
in my typescript file I want to read this data.json file and store the content of file in JSON array. I have searched but couldn't find any way to read file or any library which could help me with this.
Use FileReader from the File API and JSON.parse() method like:
onImport(event) {
var file = event.srcElement.files[0];
if (file) {
var reader = new FileReader();
reader.readAsText(file, "UTF-8");
reader.onload = function (evt) {
console.log(JSON.parse(evt.target.result));
}
reader.onerror = function (evt) {
console.log('error reading file');
}
}
}
I tried to apply #Stanislav solution but faced few issues. Eventually the following code worked
Ref: get the value from a FileReader in Angular 2
html code
<input (change)=readJson($event);" type="file" />
component.ts code
readJson(event) {
var file = event.srcElement.files[0];
if (file) {
var reader = new FileReader();
reader.readAsText(file, "UTF-8");
reader.onload = function (evt) {
console.log(JSON.parse(evt.target["result"]));
}
reader.onerror = function (evt) {
console.log('error reading file');
}
}
}
event.target["result"] is the part I modified.

Apply another gulp plugin in my own gulp plugin using through2

I am writing my own gulp plugin which looks like this...
var through2 = require('through2');
var order = require('gulp-order');
module.exports = function() {
return through2.obj(function(file, encoding, callback) {
callback(null, transform(file));
});
};
function transform(file) {
// I will modify file.contents here - its ok
return file;
}
and I would like to apply some other gulp plugin on my buffer which came from gulp.src. Is it possible using through2? For example before calling through2.obj() I would like to apply gulp-order plugin - how can I do this?
If you want to chain different gulp plugins together lazypipe is generally is good option:
var through2 = require('through2');
var order = require('gulp-order');
function yourPlugin()
return through2.obj(function(file, encoding, callback) {
callback(null, transform(file));
});
}
function transform(file) {
// I will modify file.contents here - its ok
return file;
}
function orderPlugin()
return order(['someFolder/*.js', 'someOtherFolder/*.js']);
}
module.exports = function() {
return lazypipe().pipe(orderPlugin).pipe(yourPlugin)();
};

NodeJS MySQL Dump

I've attempted to write a basic cron script to run and 'dump' a mysql database. For some reason, when it 'successfully saves the file', it does create the file, but it is empty. If instead of saving the file, I perform a console.log, it prints an empty string. Any thoughts on what I may be doing wrong?
Thanks in advance.
var mysql_backup = function(){
this.backup = '';
this.mysql = require('mysql'),
this.init = function(){
this.connection = this.mysql.createConnection({
user: 'root',
password: 'root',
database: 'test'
});
}
this.query = function(sql, callback) {
this.connection.query(sql, function (error, results, fields) {
if (error) {
throw error;
}
if (results.length > 0) {
callback(results);
}
});
}
this.get_tables = function(callback){
var me = this;
me.query('SHOW TABLES',
function(tables) {
for (var table in tables){
me.query(
'SHOW CREATE TABLE ' + tables[table].Tables_in_test,
function(r){
for (var t in r) {
me.backup += "DROP TABLE " + r[t].Table + "\n\n";
me.backup += r[t]["Create Table"] + "\n\n";
}
}
)
}
me.save_backup();
});
}
this.save_backup = function(){
var fs = require('fs');
fs.writeFile("./backup_test.txt", this.backup, function(err) {
if(err) {
console.log(err);
} else {
console.log("The file was saved!");
}
});
}
};
var db = new mysql_backup;
db.init();
db.get_tables();
db.connection.destroy();
The code as written didn't even get to a file saving for me. There seem like a few issues. Not sure if this is the actual code or some things got lost in the copy paste. However, based on what you've got:
A big one is that you never connect to the database in your code with connection.connect().
The code you want to run once connected should be inside the connection.connect() callback. e.g.
connection.connect(function (err, empty) {
if (err)
throw new Error ('Panic');
// if no error, we are off to the races...
}
However, even if you quickly refactor your code to wrap your last lines inside of that get connection callback, you'll still have problems, because you are destroying the connection before the various SQL calls are getting made, so you will want to move the code into some sort of final callback.
Even after you do that, you'll still have an empty file, because you're calling save_backup from your 'SHOW TABLES' callback rather than after you have actually populated it via the inner callback where you get the CREATE TABLE statement and populate the backup property.
This is the minimal rewriting of your code which will do what you are intending. An important thing to note is the "counter" which manages when to write the file and close the connection. I would make other changes if it were mine, including:
Using 'self' instead of 'me'
Using a numeric for loop rather than the for (... in ...) syntax
Having my own callbacks fall the node convention of (err, stuff)
A more substantial changes is that I would rewrite this to use promises, as doing so can spare you some grief with the confusion inherent with deeply nested callbacks. I personally like the Q library, but there are several options here.
Hope this helped.
var mysql_backup = function(){
this.backup = '';
this.mysql = require('mysql');
this.init = function(){
this.connection = this.mysql.createConnection({
user : 'root',
password : 'root',
database : 'test'
});
};
this.query = function(sql, callback) {
this.connection.query(sql, function (error, results, fields) {
if (error) {
throw error;
}
if (results.length > 0) {
callback(results);
}
});
};
this.get_tables = function(callback){
var counter = 0;
var me = this;
this.query('SHOW TABLES',
function(tables) {
for (table in tables){
counter++;
me.query(
'SHOW CREATE TABLE ' + tables[table].Tables_in_mvc,
function(r){
for (t in r) {
me.backup += "DROP TABLE " + r[t].Table + "\n\n";
me.backup += r[t]["Create Table"] + "\n\n";
}
counter--;
if (counter === 0){
me.save_backup();
me.connection.destroy();
}
}
)
}
});
};
this.save_backup = function(){
var fs = require('fs');
fs.writeFile("./backup_test.txt", this.backup, function(err) {
if(err) {
console.log(err);
} else {
console.log("The file was saved!");
}
});
}
};
var db = new mysql_backup;
db.init();
db.connection.connect(function (err){
if (err) console.log(err);
db.get_tables(function(x){;});
});
Update: If you are curious, here is a heavily-commented implementation using promises. Note that without the comments explaining the Q promise library functions, it is somewhat shorter than the original version and also offers more comprehensive error handling.
var MysqlBackup = function(connectionInfo, filename){
var Q = require('q');
var self = this;
this.backup = '';
// my personal preference is to simply require() inline if I am only
// going to use something a single time. I am certain some will find
// this a terrible practice
this.connection = require('mysql').createConnection(connectionInfo);
function getTables(){
// return a promise from invoking the node-style 'query' method
// of self.connection with parameter 'SHOW TABLES'.
return Q.ninvoke(self.connection,'query', 'SHOW TABLES');
};
function doTableEntries(theResults){
// note that because promises only pass a single parameter around,
// if the 'denodeify-ed' callback has more than two parameters (the
// first being the err param), the parameters will be stuffed into
// an array. In this case, the content of the 'fields' param of the
// mysql callback is in theResults[1]
var tables = theResults[0];
// create an array of promises resulting from another Q.ninvoke()
// query call, chained to .then(). Note that then() expects a function,
// so recordEntry() in fact builds and returns a new one-off function
// for actually recording the entry (see recordEntry() impl. below)
var tableDefinitionGetters = [];
for (var i = 0; i < tables.length ; i++){
// I noticed in your original code that your Tables_in_[] did not
// match your connection details ('mvc' vs 'test'), but the below
// should work and is a more generalized solution
var tableName = tables[i]['Tables_in_'+connectionInfo.database];
tableDefinitionGetters.push(Q.ninvoke(self.connection, 'query', 'SHOW CREATE TABLE ' + tableName)
.then(recordEntry(tableName)) );
}
// now that you have an array of promises, you can use Q.allSettled
// to return a promise which will be settled (resolved or rejected)
// when all of the promises in the array are settled. Q.all is similar,
// but its promise will be rejected (immediately) if any promise in the
// array is rejected. I tend to use allSettled() in most cases.
return Q.allSettled(tableDefinitionGetters);
};
function recordEntry (tableName){
return function(createTableQryResult){
self.backup += "DROP TABLE " + tableName + "\n\n";
self.backup += createTableQryResult[0][0]["Create Table"] + "\n\n";
};
};
function saveFile(){
// Q.denodeify return a promise-enabled version of a node-style function
// the below is probably excessively terse with its immediate invocation
return (Q.denodeify(require('fs').writeFile))(filename, self.backup);
}
// with the above all done, now you can actually make the magic happen,
// starting with the promise-return Q.ninvoke to connect to the DB
// note that the successive .then()s will be executed iff (if and only
// if) the preceding item resolves successfully, .catch() will get
// executed in the event of any upstream error, and finally() will
// get executed no matter what.
Q.ninvoke(this.connection, 'connect')
.then(getTables)
.then(doTableEntries)
.then(saveFile)
.then( function() {console.log('Success'); } )
.catch( function(err) {console.log('Something went awry', err); } )
.finally( function() {self.connection.destroy(); } );
};
var myConnection = {
host : '127.0.0.1',
user : 'root',
password : 'root',
database : 'test'
};
// I have left this as constructor-based calling approach, but the
// constructor just does it all so I just ignore the return value
new MysqlBackup(myConnection,'./backup_test.txt');