Skip to content

Commit

Permalink
Merge pull request #54 from saadtazi/add-cli
Browse files Browse the repository at this point in the history
Add cli
  • Loading branch information
saadtazi committed Apr 9, 2015
2 parents 14a7257 + fc32a85 commit 0acc218
Show file tree
Hide file tree
Showing 12 changed files with 335 additions and 56 deletions.
13 changes: 13 additions & 0 deletions .npmignore
@@ -0,0 +1,13 @@
firefox-profile.sublime-*
.DS_Store
node_modules/
npm-debug.log
coverage/
doc/
examples/
test/
.travis.yml
.coveralls.yml
.jshintrc
Gruntfile.js
secret.config.*
4 changes: 4 additions & 0 deletions CHANGELOG.md
@@ -1,3 +1,7 @@
# 0.3.11

* added a cli to create or copy profile

# 0.3.10

* added .npmignore
Expand Down
6 changes: 3 additions & 3 deletions Gruntfile.js
Expand Up @@ -31,8 +31,8 @@ module.exports = function(grunt) {
}
},
options: {
require: './test/require',
files: ['test/*.js', 'test/**/*.js', '!test/extensions/**/*.js']
require: './test/require.js',
files: ['test/*.js', 'test/cli.js', 'test/spec/*.js', '!test/require.js', '!test/extensions/**/*.js']
}


Expand All @@ -43,7 +43,7 @@ module.exports = function(grunt) {
},
watch: {
scripts: {
files: ['**/*.js'],
files: ['lib/**/*.js', 'test/**/*.js'],
tasks: ['mochacov'],
options: {
spawn: false,
Expand Down
24 changes: 22 additions & 2 deletions README.md
Expand Up @@ -21,6 +21,8 @@ This class allows you to:

More info on user preferences [here](http://kb.mozillazine.org/User.js_file).

It also contains a [command line interface](#command-line-interface) that allows to copy or create profiles.

## Installation

~~"real" npm support is on its way... soon... maybe... Open an issue if you need it...~~ Use npm:
Expand Down Expand Up @@ -48,7 +50,7 @@ Make sure you have selenium server running... or use 'selenium-webdriver/remote'
* with selenium webdriverJs
* installs firebug
* and make http://saadtazi.com the url that is opened on new tabs
/******************************************************************
/******************************************************************/
var webdriver = require('selenium-webdriver');

// create profile
Expand Down Expand Up @@ -83,7 +85,7 @@ Make sure you have selenium server running... or use 'selenium-webdriver/remote'
/**************************************************
/* with admc/wd
/* installs firebug, and make it active by default
/**************************************************
/**************************************************/

var FirefoxProfile = require('firefox-profile'),
wd = require('wd');
Expand Down Expand Up @@ -117,6 +119,24 @@ Make sure you have selenium server running... or use 'selenium-webdriver/remote'

You can also copy an existing profile... Check the doc `FirefoxProfile.copy(...)`.

## Command Line Interface

It allows to copy (from profile name or profile directory) or create firefox profiles with installed extensions. Note that it does not allow to load user preferences... yet.

Run `node_modules/bin/firefox-profile -h` to get the help message:

```
usage: firefox-profile [-v] [-p profilename || -c profile_dir] [-e extension_path1 [-e extension_path2]] [-o destination_dir || --ouput destination_dir || -b [file_path] || --base64 [file_path]]
-v: verbose mode (same as --verbose)
-h: show this message (same as --help)
-p profilename: profile to copy (same as --profile)
-c profile_dir: profile folder path to copy (same as --copy)
-e extension_path: file path to extension to add to the profile. Can be present multiple times (same as --extension)
-o destination_dir (or --output destination_dir): folder where the profile will be created.
-b [file_path](or --base64): write the encoded firefox profile to stdout or to file_path if specified.
```

## API Documentation

The API documentation can be found in [doc/](./doc/).
Expand Down
22 changes: 14 additions & 8 deletions doc/firefox_profile.md
Expand Up @@ -35,11 +35,15 @@ If you need optimzed async version, use `FirefoxProfile.copy(profileDirectory, c

**Parameters:**

- `{Object | String | null} options` optional. if it is an object, it can contain the following option: * profileDirectory: the profile to copy. Not recommended: use [FirefoxProfile.copy](#firefoxprofilecopyoptions) instead
* destinationDirectory: where the profile will be stored. If not provided,
a tmp direcoty will be used WARNING: if it will be emptied!!
if it is a string it will copy the directory synchronously.
(not recommended at all, kept for backward compatibility)
- `{Object | String | null} options` optional.

If it is an object, it can contain the following option:
* profileDirectory: the profile to copy. Not recommended: use [FirefoxProfile.copy](#firefoxprofilecopyoptions) instead
* destinationDirectory: where the profile will be stored. If not provided,
a tmp directory will be used WARNING: if the tmp directory will be deleted when the process will terminate.

if it is a string it will copy the directory synchronously
(not recommended at all, kept for backward compatibility).

<sub>Go: [TOC](#tableofcontents)</sub>

Expand All @@ -49,9 +53,11 @@ If you need optimzed async version, use `FirefoxProfile.copy(profileDirectory, c
**Parameters:**

- `{Object | String | null} options` if it is an object: * profileDirectory - required - the profile to copy.
* destinationDirectory: where the profile will be stored. If not provided,
a tmp direcoty will be used. WARNING: if it will be emptied!!
- `{Object | String | null} options`
if it is an object, the following properties are available:
* profileDirectory - required - the profile to copy.
* destinationDirectory: where the profile will be stored. If not provided,
a tmp directory will be used. WARNING: if the tmp directory will be deleted when the process exits.

<sub>Go: [TOC](#tableofcontents) | [FirefoxProfile](#toc_firefoxprofile)</sub>

Expand Down
131 changes: 131 additions & 0 deletions lib/cli.js
@@ -0,0 +1,131 @@
#!/usr/bin/env node
var minimist = require('minimist'),
util = require('util'),
fs = require('fs'),
_ = require('lodash'),
FirefoxProfile = require('./firefox_profile');

var argv = minimist(process.argv.slice(2), {
string: [
'o', 'output',
'p', 'profile',
'c', 'copy'],
boolean: [
'v', 'verbose',
'h', 'help'
]
});

function displayHelp() {
console.log('usage: firefox-profile [-v] [-p profilename || -c profile_dir] [-e extension_path1 [-e extension_path2]] [-o destination_dir || --ouput destination_dir || -b [file_path] || --base64 [file_path]]');
console.log('');
console.log('-v: verbose mode (same as --verbose)');
console.log('-h: show this message (same as --help)');
console.log('-p profilename: profile to copy (same as --profile)');
console.log('-c profile_dir: profile folder path to copy (same as --copy)');
console.log('-e extension_path: file path to extension to add to the profile. Can be present multiple times (same as --extension)');
console.log('-o destination_dir (or --output destination_dir): folder where the profile will be created.');
console.log('-b [file_path](or --base64): write the encoded firefox profile to stdout or to file_path if specified.');
}

if (argv.h || argv.help) {
displayHelp();
process.exit(0);
}

function displayError(msg, err) {
console.error('ERROR:', msg, err);
}

var destinationDirectory = argv.o || argv.ouput,
encoded = argv.b || argv.base64;

if (!destinationDirectory && !encoded) {
console.log('ERROR: you need to specify a destination directory (-o or --output) or ouput the encoded profile to stdout (-b64 or --base64)\n');
displayHelp();
process.exit(1);
}

var verbose = !!(argv.v || argv.verbose),
profileName = argv.p || argv.profile,
profileDirectory = argv.c || argv.copy,
extensionPaths = (argv.e || []).concat(argv.extension || []);


function log() {
if (verbose) {
console.log.apply(null, arguments);
}
}
log('arguments:', argv);

// copy or create a new profile depending on params
// TODO: use async instead?
function createProfile(cb) {
if (profileName || profileDirectory) {
var copyMethod = argv.p ? 'copyFromUserProfile' : 'copy',
copyOptions = {
destinationDirectory: destinationDirectory,
name: profileName,
profileDirectory: profileDirectory
};
log(util.format('calling FirefoxProfile.`%s` method with options %s', copyMethod, JSON.stringify(copyOptions)));
FirefoxProfile[copyMethod](copyOptions, function(err, fp) {
cb(err, fp);
});
return;

}
log('creating an empty profile...');
cb(null, new FirefoxProfile({
destinationDirectory: destinationDirectory
}));
}


createProfile(function(err, fp) {
if (err) {
displayError('cannot copy the profile', err);
process.exit(2);
}

if (_.isString(extensionPaths)) {
extensionPaths = [extensionPaths];
}
// still not an array? it should be ok to call addExtensions with empty array...
if (!_.isArray(extensionPaths)) {
extensionPaths = [];
}
log('adding extensions::', extensionPaths);
fp.addExtensions(extensionPaths, function(err) {
if (err) {
displayError('unable to add extensions', err);
process.exit(2);
}
if (!encoded) {
// we're done
console.log('profile created in', fp.profileDir);
process.exit(0);
}
log('encoding profile...');

fp.encoded(function(zippedProfileString) {
if (encoded === true) {
process.stdout.write(zippedProfileString);
process.exit(0);
}
log('writing encoded profile to file', encoded);
fs.writeFile(encoded, zippedProfileString, function (err) {
if (err) {
displayError('unable to write encoded profile', err);
process.exit(3);
}
process.exit(0);
})
});
});


});


26 changes: 16 additions & 10 deletions lib/firefox_profile.js
Expand Up @@ -97,12 +97,16 @@ function parseOptions(opts) {
* which is not optimized.
* If you need optimzed async version, use `FirefoxProfile.copy(profileDirectory, cb);`
*
* @param {Object|String|null} options optional. if it is an object, it can contain the following option:
* * profileDirectory: the profile to copy. Not recommended: use FirefoxProfile.copy instead
* * destinationDirectory: where the profile will be stored. If not provided,
* a tmp direcoty will be used WARNING: if it will be emptied!!
* if it is a string it will copy the directory synchronously.
* (not recommended at all, kept for backward compatibility)
* @param {Object|String|null} options optional.
*
*
* If it is an object, it can contain the following option:
* * profileDirectory: the profile to copy. Not recommended: use FirefoxProfile.copy instead
* * destinationDirectory: where the profile will be stored. If not provided,
* a tmp directory will be used WARNING: if the tmp directory will be deleted when the process will terminate.
*
* if it is a string it will copy the directory synchronously
* (not recommended at all, kept for backward compatibility).
*/
function FirefoxProfile(options) {
var opts = parseOptions(options),
Expand Down Expand Up @@ -167,10 +171,12 @@ FirefoxProfile.prototype._copy = function(profileDirectory, cb) {
/**
* creates a profile Profile from an existing firefox profile directory asynchronously
*
* @param {Object|String|null} options if it is an object:
* * profileDirectory - required - the profile to copy.
* * destinationDirectory: where the profile will be stored. If not provided,
* a tmp direcoty will be used. WARNING: if it will be emptied!!
* @param {Object|String|null} options
*
* if it is an object, the following properties are available:
* * profileDirectory - required - the profile to copy.
* * destinationDirectory: where the profile will be stored. If not provided,
* a tmp directory will be used. WARNING: if the tmp directory will be deleted when the process exits.
*/

FirefoxProfile.copy = function(options, cb) {
Expand Down
62 changes: 36 additions & 26 deletions package.json
Expand Up @@ -14,6 +14,7 @@
]
}
},
"bin" : { "firefox-profile" : "./lib/cli.js" },
"repository": {
"type": "git",
"url": "git://github.com/saadtazi/firefox-profile-js.git"
Expand All @@ -30,28 +31,36 @@
"bugs": {
"url": "https://github.com/saadtazi/firefox-profile-js/issues"
},
"contributors": [{
"name": "testingbot",
"url": "http://www.testingbot.com"
}, {
"name": "David Sturley",
"url": "https://github.com/circusbred"
}, {
"name": "Jordan Santell",
"url": "http://jsantell.com"
}, {
"name": "Piotr Kuczynski",
"url": "https://github.com/pkuczynski"
}, {
"name": "halo2376",
"url": "https://github.com/halo2376"
}, {
"name": "XrXr",
"url": "https://github.com/XrXr"
}, {
"name": "Christoph Dorn",
"url": "http://www.christophdorn.com/"
}],
"contributors": [
{
"name": "testingbot",
"url": "http://www.testingbot.com"
},
{
"name": "David Sturley",
"url": "https://github.com/circusbred"
},
{
"name": "Jordan Santell",
"url": "http://jsantell.com"
},
{
"name": "Piotr Kuczynski",
"url": "https://github.com/pkuczynski"
},
{
"name": "halo2376",
"url": "https://github.com/halo2376"
},
{
"name": "XrXr",
"url": "https://github.com/XrXr"
},
{
"name": "Christoph Dorn",
"url": "http://www.christophdorn.com/"
}
],
"devDependencies": {
"blanket": "~1.1.x",
"chai": "~1.9.x",
Expand All @@ -69,16 +78,17 @@
"wd": "~0.3.x"
},
"dependencies": {
"jetpack-id": "0.0.4",
"adm-zip": "~0.4.x",
"archiver": "~0.14.3",
"async": "~0.9.0",
"fs-extra": "~0.16.x",
"ini": "~1.3.3",
"jetpack-id": "0.0.4",
"lazystream": "~0.1.0",
"lodash": "~3.5.0",
"minimist": "^1.1.1",
"node-uuid": "~1.4.1",
"wrench": "~1.5.8",
"xml2js": "~0.4.4",
"ini": "~1.3.3"
"xml2js": "~0.4.4"
}
}
}

0 comments on commit 0acc218

Please sign in to comment.