Skip to content

Instantly share code, notes, and snippets.

@duzun
Forked from therealjeffg/install-addon
Last active Aug 29, 2015
Embed
What would you like to do?
A node script that abuses child_process to run cfx and post the resulting xpi to Firefox.
#!/usr/bin/env node
/**
* A node script that abuses child_process to run cfx and post the resulting xpi to Firefox.
* Requires: a working installation of the Add-on SDK (with cfx on your PATH)
* and a recent version of Firefox with the 'Extension Auto-installer' extension installed.
*
* Original gist https://gist.github.com/canuckistani/9301061
*
* Improved by Dumitru Uzun (DUzun.Me)
*
* @version 1.1.0
*/
var fs = require('fs')
, path = require('path')
, http = require('http')
, url = require('url')
, watch = require('watch')
, spawn = require('child_process').spawn
;
var DEBUG = false
, host = '127.0.0.1'
, port = 8888
, cwd = process.cwd()
;
if (!module.parent) {
/*
1. get some info from package.json
2. run cfx
3. on completion, post the xpi file to Firefox
*/
var optimist = require('optimist');
var argv = optimist
.usage('addon-install -h http://localhost:8888/')
.default({h: host})
.describe('h', 'The host and port that the extension auto-installer is listening on')
.alias('p', 'port')
.alias('c', 'cwd')
.alias('w', 'watch')
.argv
;
install_addon(argv, function (err, res) {
if ( err ) return ;
if ( argv.w ) {
var _delay = 500;
var _to;
function _run_async() {
if ( _to ) clearTimeout(_to);
_to = setTimeout(function () {
if ( install_addon.running ) return _run_async();
install_addon(argv);
}, _delay);
}
watch.createMonitor(
argv.c ? path.resolve(cwd, argv.c) : cwd
, {
interval: _delay >>> 1
, ignoreDotFiles: true
, ignoreDirectoryPattern: /(node_modules|scripts)/
// , filter: function (f, stat) { return stat.isDirectory() || path.extname(f) === '.js'; }
}
, function (monitor) {
// monitor.files['/home/duzun/.zshrc'] // Stat object for my zshrc.
monitor.on("created", _run_async);
monitor.on("changed", _run_async);
monitor.on("removed", _run_async);
// monitor.stop(); // Stop watching
}
);
}
});
}
function install_addon(argv, cb) {
install_addon.running = Date.now();
var _cwd = argv.c ? path.resolve(cwd, argv.c) : cwd;
fs.readFile(
path.join(_cwd, 'package.json'), {encoding: 'utf8'}
, function(err, buffer) {
if (err) {
install_addon.running = false;
if ( cb ) {
cb(err);
return;
}
throw err;
}
var package_data = JSON.parse(buffer)
, xpi_name = package_data.name + '.xpi'
, xpi_path = path.resolve(_cwd, '..', xpi_name)
;
console.log("Building %s", xpi_name);
var builder = spawn(path.join(__dirname, 'cfx.cmd'), ['xpi', '--output-file='+xpi_path], { cwd: _cwd });
var error_in_builder = false;
builder.stdout.on('data', function(data) {
console.log("cfx> %s", data);
});
builder.stderr.on('data', function(data) {
error_in_builder = true;
console.log("cfx err> %s", data);
});
builder.on('error', function(err) {
error_in_builder = err;
console.log([].slice.call(arguments));
});
builder.on('close', function(err, result) {
if ( err ) {
console.log('err', err)
cb && cb(err);
return;
}
if ( error_in_builder ) {
console.log('error_in_builder', error_in_builder);
return;
}
var xpi_data = fs.readFileSync(xpi_path);
var req = http.request({
host: argv.h || host,
port: argv.p || port,
method: 'POST',
headers: {
'Content-Type' : 'application/x-www-form-urlencoded'
, 'Content-Length': xpi_data.length
}
}, function (res) {
console.log('http> status: %s %s', res.statusCode, res.statusMessage);
res.on('data', function (d) {
process.stdout.write(d);
});
res.on('end', function () {
install_addon.running = false;
console.log('http> %s', 'Done');
cb && cb(null, res);
})
});
req.on('error', function (err) {
console.log("http> %s", err);
});
console.log("http> %s", 'Sending xpi to FF ('+xpi_data.length+')');
req.write(xpi_data);
req.end();
});
}
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment