'use strict';
var mkdirp = require('mkdirp'),
fs = require('fs'),
changeName = require('./changename'),
path = require('path'),
safename = require('safename');
/*!
* Rename file and launch callback
* @param {String} oldPath path to file to move
* @param {String} newPath path of destination
* @param {Function} callback signature: null, {filename, filepath}
*/
var move = function (oldPath, newPath, callback) {
fs.rename( oldPath, newPath, function (err) {
if (err) {
callback( err );
} else {
callback( null, {
filename: newPath.split( '/' ).pop(),
filepath: newPath
});
}
});
};
/*!
* return safename file path
* @param {String} route target to analyze
* @return {String} route analyze
*/
var checkSafeName = function (route) {
if ( this.safenames ) {
route = route.split( '/' );
var name = route.pop();
name = safename( name );
route.push( name );
return route.join( '/' );
} else {
return route;
}
};
/*!
* check if params are right
*/
var checker = function (folder, oldPath, newPath, callback) {
var cb = callback || function () {};
if (typeof newPath === 'function') {
cb = newPath;
newPath = oldPath.split( '/' ).pop();
} else if (!newPath) {
newPath = oldPath.split( '/' ).pop();
}
// check for valid arguments
if (folder && oldPath && (typeof folder === 'string') && (typeof oldPath === 'string') && fs.existsSync( oldPath )) {
// check for existing folder
if (this.folders[folder]) {
// set target
newPath = path.resolve( this.folders[folder], newPath );
newPath = checkSafeName.call( this, newPath );
return {newPath: newPath, callback: cb};
} else {
cb( 'invalid folder' );
return false;
}
} else {
cb( 'folder or origin not valid' );
return false;
}
};
/**
* Filesaver constructor.
*
* Options:
*
* - folders: *Object* with folder routes
* - safename: *Boolean* use safe name for files
*
* Example:
*
* ```js
* var folders = {
* images: './images',
* books: './books'
* }
* var filesaver = new Filesaver({
* folders: folders,
* safenames: true
* });
* ```
*
* @param {Object} options folders and safenames
*/
var Filesaver = function (options) {
var x;
options = options || {};
// Store folders
this.folders = options.folders || {};
this.safenames = options.safenames || false;
// check for existing folders
for (x in this.folders) {
if (!fs.existsSync( this.folders[x] )){
// create folder if not exists
mkdirp( this.folders[x] );
}
}
};
/**
* Add a new folder
*
* Example:
*
* ```js
* filesaver.folder( 'documents', './path/to/folder', function () {
* // do something
* });
* ```
* @param {String} name name of new folder collection
* @param {Object} path path to its folder
* @param {Function} callback no signature callback
*/
Filesaver.prototype.folder = function (name, folderPath, callback) {
var _this = this;
fs.exists( folderPath, function (exists) {
if (!exists) {
// create folder if not exists
mkdirp( folderPath );
}
// add folder
_this.folders[name] = folderPath;
// optional callback
if (callback){
callback();
}
});
};
/**
* Write or overwrite file
*
* Example:
*
* ```js
* filesaver.put( 'images', '/path/temp/file.jpg', 'photo.jpg', function (err, data) {
* console.log( data );
* // ->
* // filename: 'photo.jpg',
* // filepath: './images/photo.jpg'
* });
* ```
*
* @param {String} folder name of parent folder folder
* @param {String} oldPath path to origin file
* @param {String} newPath name of newPath file
* @param {Function} callback Signature: error, data. Data signature:{filename, filepath}
*/
Filesaver.prototype.put = function (folder, oldPath, newPath, callback) {
var data = checker.call( this, folder, oldPath, newPath, callback );
if (data) {
move( oldPath, data.newPath, data.callback );
}
};
/**
* Write a file without overwriting anyone.
*
* Example:
*
* ```js
* filesaver.add( 'images', '/path/temp/file.jpg', 'photo_1.jpg', function (err, data) {
* console.log( data );
* // ->
* // filename: 'photo_2.jpg',
* // filepath: './images/photo_2.jpg'
* });
* ```
*
* @param {String} folder name of parent folder folder
* @param {String} oldPath path to origin file
* @param {String} newPath Optional: name of newPath file
* @param {Function} callback Optional: Signature: error, data. Data signature:{filename, filepath}
*/
Filesaver.prototype.add = function (folder, oldPath, newPath, callback) {
var data = checker.call( this, folder, oldPath, newPath, callback );
if (data) {
newPath = changeName( data.newPath );
move( oldPath, newPath, data.callback );
}
};
module.exports = Filesaver;