Files
bower/lib/commands/init.js
2013-07-22 23:40:09 +01:00

191 lines
4.8 KiB
JavaScript

var mout = require('mout');
var fs = require('graceful-fs');
var path = require('path');
var Q = require('q');
var inquirer = require('inquirer');
var Logger = require('bower-logger');
var endpointParser = require('bower-endpoint-parser');
var cli = require('../util/cli');
var Project = require('../core/Project');
var defaultConfig = require('../config');
function init(config) {
var project;
var logger = new Logger();
config = mout.object.deepFillIn(config || {}, defaultConfig);
project = new Project(config, logger);
// Start with existing JSON details
readJson(project, logger)
// Fill in defaults
.then(setDefaults.bind(null, config))
// Now prompt user to make changes
.then(promptUser)
// Set ignore based on the response
.spread(setIgnore)
// Set dependencies based on the response
.spread(setDependencies.bind(null, project))
// All done!
.spread(saveJson.bind(null, project))
.then(function (json) {
logger.emit('end', json);
})
.fail(function (error) {
logger.emit('error', error);
});
return logger;
}
function readJson(project, logger) {
return project.hasJson()
.then(function (json) {
if (json) {
logger.warn('existing', 'The existing ' + path.basename(json) + ' file will be used and filled in');
}
return project.getJson();
});
}
function saveJson(project, json) {
// Cleanup empty props, including objects and arrays
mout.object.forOwn(json, function (value, key) {
if (mout.lang.isEmpty(value)) {
delete json[key];
}
});
// Save json (true forces file creation)
return project.saveJson(true);
}
function setDefaults(config, json) {
var name;
// Name
if (!json.name) {
json.name = path.basename(config.cwd);
}
// Version
if (!json.version) {
json.version = '0.0.0';
}
// Main
if (!json.main) {
// Remove '.js' from the end of the package name if it is there
name = path.basename(json.name, '.js');
if (fs.existsSync(path.join(config.cwd, 'index.js'))) {
json.main = 'index.js';
} else if (fs.existsSync(path.join(config.cwd, name + '.js'))) {
json.main = name + '.js';
}
}
return json;
}
function promptUser(json) {
var deferred = Q.defer();
var questions = [
{
'name': 'name',
'message': 'name',
'default': json.name,
'type': 'input'
},
{
'name': 'version',
'message': 'version',
'default': json.version,
'type': 'input'
},
{
'name': 'main',
'message': 'main file',
'default': json.main,
'type': 'input'
},
{
'name': 'dependencies',
'message': 'set currently installed components as dependencies?',
'default': !mout.object.size(json.dependencies) && !mout.object.size(json.devDependencies),
'type': 'confirm'
},
{
'name': 'ignore',
'message': 'add commonly ignored files to ignore list?',
'default': true,
'type': 'confirm'
}
];
inquirer.prompt(questions, function (answers) {
json.name = answers.name;
json.version = answers.version;
json.main = answers.main;
return deferred.resolve([json, answers]);
});
return deferred.promise;
}
function setIgnore(json, answers) {
if (answers.ignore) {
json.ignore = mout.array.combine(json.ignore || [], [
'**/.*',
'node_modules',
'bower_components',
'test',
'tests'
]);
}
return [json, answers];
}
function setDependencies(project, json, answers) {
if (answers.dependencies) {
return project.getTree()
.spread(function (tree, flattened, extraneous) {
if (extraneous.length) {
json.dependencies = {};
// Add extraneous as dependencies
// TODO: The final expanded source is used instead of the original source
// While this the most correct it might be confusing to users
extraneous.forEach(function (extra) {
var jsonEndpoint = endpointParser.decomposed2json(extra.endpoint);
mout.object.mixIn(json.dependencies, jsonEndpoint);
});
}
return [json, answers];
});
}
return [json, answers];
}
// -------------------
init.line = function () {
return init();
};
init.options = function (argv) {
return cli.readOptions(argv);
};
init.completion = function () {
// TODO:
};
module.exports = init;