Skip to content

Commit

Permalink
Merge pull request #24 from firebase/v1.0.6
Browse files Browse the repository at this point in the history
v1.0.6
  • Loading branch information
Chris Raynor committed Jun 5, 2014
2 parents 144aa99 + 816f047 commit 943b573
Show file tree
Hide file tree
Showing 8 changed files with 227 additions and 59 deletions.
20 changes: 20 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
## v1.0.6
- Adds `-s` functionality to all commands for silent mode while scripting - commands will error with non-zero status code instead of waiting for prompt if not enough information supplied
- `delete-site` command as a convenience method for removing a site from hosting. Site shows up as 'Site Not Found' as if never deployed to

## v1.0.5
- Gracefully handles error caused by symlinks in public directory until [isaacs/fstream#16](https://github.com/isaacs/fstream/pull/16) fix

## v1.0.4
- NPM artifact fix

## v1.0.3
- Allows command line params in `firebase deploy` to override `firebase.json` settings

## v1.0.2
- Enforces node 0.10.x and above after shown not to work on previous versions

## v1.0.1
- Fixes bug with `firebase bootstrap` on windows
- Adds 'ignore' to `firebase.json` to allow files to be ignored on deploy
- Prioritizes `--email` and `--password` command line arguments over current auth token if both passed
5 changes: 5 additions & 0 deletions bin/firebase
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ var argv = require('optimist')
.alias('m', 'message')
.alias('p', 'public')
.alias('r', 'rules')
.alias('s', 'silent')
.alias('t', 'template')
.alias('v', 'version')
.boolean('d')
.boolean('s')
.argv,
prompt = require('prompt'),
firebase = require('../lib/firebase'),
Expand Down Expand Up @@ -69,6 +71,9 @@ if (argv._.length === 0) {
case 'deploy':
app.deploy(argv);
break;
case 'delete-site':
app.deleteSite(argv);
break;
case 'open':
app.open(argv);
break;
Expand Down
154 changes: 114 additions & 40 deletions lib/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,32 +24,60 @@ var defaultSettings = {

temp.track();

function getPrompt(schema, onComplete, idx, results) {
function getPrompt(argv, schema, onComplete, index, results) {
if (!Array.isArray(schema)) {
console.log(chalk.red('An error occurred'));
process.exit(1);
}
onComplete = typeof onComplete !== 'function' ? function() {} : onComplete;
idx = typeof idx !== 'number' ? 0 : idx;
index = typeof index !== 'number' ? 0 : index;
results = typeof results !== 'object' ? {} : results;
var item = schema[idx];
var item = schema[index];
if (argv.silent) {
if (!prompt.override[item.name] || (item.pattern && !item.pattern.test(prompt.override[item.name]))) {
console.log(chalk.red('Input Error') + ' - Not enough or invalid parameters specified while in silent mode');
console.log('Required ' + chalk.bold(item.name) + ' parameter missing or invalid');
process.exit(1);
}
}
if (typeof item.beforeValue === 'function') {
item.beforeValue(results);
}
prompt.get(schema[idx], function (error, result) {
prompt.get(schema[index], function (error, result) {
if (error) {
console.log(chalk.red('Input Error'));
process.exit(1);
}
results[item.name] = result[item.name];
if (++idx < schema.length) {
getPrompt(schema, onComplete, idx, results);
if (++index < schema.length) {
getPrompt(argv, schema, onComplete, index, results);
} else {
onComplete(results);
}
});
}

function getSettings(argv) {
var settingsFile = path.resolve('./firebase.json');
var settingsJSON, settings;
if (!fs.existsSync(settingsFile)) {
console.log(chalk.red('Initialization Error') + ' - Directory not ' +
'initialized');
process.exit(1);
}
try {
settingsJSON = fs.readFileSync(settingsFile);
settings = JSON.parse(settingsJSON);
} catch (err) {
console.log(chalk.red('Initialization Error') +' - Could not read ' +
'firebase.json settings file');
process.exit(1);
}
util._extend(settings, argv);

return settings;
}

module.exports = {
init: function(argv) {
auth.listFirebases(argv).then(function(res) {
Expand Down Expand Up @@ -110,7 +138,7 @@ module.exports = {
}
}];

getPrompt(schema, function(results) {
getPrompt(argv, schema, function(results) {
if (path.relative('.', results['public']).match(/^\./)) {
console.log(chalk.red('init cancelled - the public directory must be within the current working directory'));
process.exit(1);
Expand Down Expand Up @@ -200,7 +228,7 @@ module.exports = {
type: 'string'
}];

getPrompt(schema, function(results) {
getPrompt(argv, schema, function(results) {
var firebase = results.firebase;
var dir = firebase;
var projectDir = path.resolve(dir);
Expand Down Expand Up @@ -334,22 +362,7 @@ module.exports = {
console.log(chalk.red('Login Error'));
process.exit(1);
}
var settingsFile = path.resolve('./firebase.json');
var settingsJSON, settings;
if (!fs.existsSync(settingsFile)) {
console.log(chalk.red('Initialization Error') + ' - Directory not ' +
'initialized');
process.exit(1);
}
try {
settingsJSON = fs.readFileSync(settingsFile);
settings = JSON.parse(settingsJSON);
} catch (err) {
console.log(chalk.red('Initialization Error') +' - Could not read ' +
'firebase.json settings file');
process.exit(1);
}
util._extend(settings, argv);
var settings = getSettings(argv);
if (typeof(settings.firebase) !== 'string') {
console.log(chalk.red('Initialization Error') +' - Could not read ' +
'firebase.json settings file');
Expand Down Expand Up @@ -440,7 +453,7 @@ module.exports = {
message = argv.message;
}

upload.send(settings.firebase, settings['public'], settings.ignore || defaultSettings.ignore, directoryRef.name(), message, function(err, directory) {
upload.send(settings.firebase, settings['public'], settings.ignore, directoryRef.name(), message, function(err, directory) {
if (err) {
console.log(chalk.red('Deploy Error') + ' - Couldn\'t upload app');
console.log(err);
Expand All @@ -451,22 +464,83 @@ module.exports = {
});
});
},
deleteSite: function(argv) {
auth.requireLogin(argv, function(err) {
if (err) {
console.log(chalk.red('Login Error'));
process.exit(1);
}
var settings = getSettings(argv);
if (typeof(settings.firebase) !== 'string') {
console.log(chalk.red('Initialization Error') +' - Could not read ' +
'firebase.json settings file');
process.exit(1);
}
auth.checkCanAccess(settings.firebase, function(err, tokens) {
if (err) {
console.log(chalk.red('Permission Error') + ' - You do not have ' +
'permission to use this Firebase');
process.exit(1);
}
var firebaseRef = new Firebase(api.realtimeUrl.replace(/\/\//, '//firebase.'));
firebaseRef.auth(tokens.firebaseToken, function(error, result) {
if (error) {
console.log('Firebase authentication failed!');
process.exit(1);
}
});
var directoryRef = firebaseRef
.child('hosting/versions')
.child(settings.firebase)
.push();
var bar = null;
var total = 0;
directoryRef.on('value', function(snapshot) {
var status = snapshot.child('status').val();
if (status === 'deploying') {
if (!bar && snapshot.hasChild('fileCount')) {
total = snapshot.child('fileCount').val();
bar = new ProgressBar(chalk.yellow('progress: :percent'), {
total: total
});
}
if (bar) {
var uploadedCount = snapshot.hasChild('uploadedCount') ? snapshot.child('uploadedCount').val() : 0;
bar.update(uploadedCount / total);
}
} else if (status === 'removed') {
console.log(chalk.green('Sucessfully removed'));
process.exit(0);
} else if (status === 'failed') {
if (bar) {
bar.terminate();
}
var message = chalk.red('Deploy Failed');
if (snapshot.hasChild('statusMessage')) {
message += ' - ' + snapshot.child('statusMessage').val();
}
console.log(message);
process.exit(1);
}
});

var message = null;
if (argv.message && (typeof(argv.message) === 'string')) {
message = argv.message;
}

upload.deleteSite(settings.firebase, directoryRef.name(), message, function(err, directory) {
if (err) {
console.log(chalk.red('Deploy Error') + ' - Couldn\'t upload app');
console.log(err);
process.exit(1);
}
});
});
});
},
open: function(argv) {
var settingsFile = path.resolve('./firebase.json');
var settingsJSON, settings;
if (!fs.existsSync(settingsFile)) {
console.log(chalk.red('Initialization Error') + ' - Directory not ' +
'initialized');
process.exit(1);
}
try {
settingsJSON = fs.readFileSync(settingsFile);
settings = JSON.parse(settingsJSON);
} catch (err) {
console.log(chalk.red('Initialization Error') +' - Could not read ' +
'firebase.json settings file');
process.exit(1);
}
var settings = getSettings(argv);
if (typeof(settings.firebase) !== 'string') {
console.log(chalk.red('Initialization Error') +' - Could not read ' +
'firebase.json settings file');
Expand Down
48 changes: 31 additions & 17 deletions lib/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@ var auth = {
var that = this;

if (argv.email && argv.password) {
this._attemptLogin(this.maxRetries, callback);
this._attemptLogin(argv, this.maxRetries, callback);
} else if ((this.email.length === 0) || (this.token.length === 0)) {
console.log('Please sign into your Firebase account to continue...');
this._attemptLogin(this.maxRetries, callback);
this._attemptLogin(argv, this.maxRetries, callback);
} else {
this._validate(function(err) {
if (err) {
console.log('Please sign into your Firebase account to continue...');
that._attemptLogin(that.maxRetries, callback);
that._attemptLogin(argv, that.maxRetries, callback);
} else {
setTimeout(callback, 0, null, that.email, that.token);
}
Expand Down Expand Up @@ -55,20 +55,24 @@ var auth = {
}
);
},
login: function(callback) {
this._attemptLogin(this.maxRetries, callback);
login: function(argv, callback) {
this._attemptLogin(argv, this.maxRetries, callback);
},
_attemptLogin: function(tries, callback) {
_attemptLogin: function(argv, tries, callback) {
var that = this;
if (tries > 0) {
if (tries !== this.maxRetries) {
if (argv.silent) {
console.log(chalk.red('Input Error') + ' - Email or password incorrect');
process.exit(1);
}
console.log('Email or password incorrect, please try again');
delete prompt.override.email;
delete prompt.override.password;
}
this._loginRequest(function(err, email, token) {
this._loginRequest(argv, function(err, email, token) {
if (err) {
that._attemptLogin(tries - 1, callback);
that._attemptLogin(argv, tries - 1, callback);
} else {
setTimeout(callback, 0, null, email, token);
}
Expand All @@ -78,28 +82,38 @@ var auth = {
process.exit(1);
}
},
_loginRequest: function(callback) {
_loginRequest: function(argv, callback) {
var that = this,
schema = {
properties: {
email: {
schema = [
{
name: 'email',
description: 'Email:',
pattern: /@/,
message: 'Must be a valid email address',
required: true,
type: 'string'
},
password: {
},{
name: 'password',
description: 'Password:',
hidden: true,
required: true,
type: 'string'
}
}
};
];

if (this.email.length > 0) {
schema.properties.email.default = this.email;
schema[0].default = this.email;
}

if (argv.silent) {
for (var i in schema) {
var item = schema[i];
if (!prompt.override[item.name] || (item.pattern && !item.pattern.test(prompt.override[item.name]))) {
console.log(chalk.red('Input Error') + ' - Not enough or invalid parameters specified while in silent mode');
console.log('Required ' + chalk.bold(item.name) + ' parameter missing or invalid');
process.exit(1);
}
}
}

prompt.get(schema, function(err, result) {
Expand Down
2 changes: 1 addition & 1 deletion lib/firebase.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ var auth = require('./auth'),

module.exports = {
login: function(argv) {
auth.login(function(err) {
auth.login(argv, function(err) {
if (err) {
console.log(chalk.red('Login Unsuccessful'));
process.exit(1);
Expand Down
Loading

0 comments on commit 943b573

Please sign in to comment.