You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by je...@apache.org on 2013/09/27 16:26:29 UTC

[25/50] [abbrv] webworks commit: [CB-4544] Adds a --query flag to query the user for their password when we need it - Rewrite the run script for maintenance

[CB-4544] Adds a --query flag to query the user for their password when we need it
 - Rewrite the run script for maintenance

  Reviewed By: Bryan Higgins <bh...@blackberry.com>
  Tested By: Tracy Li <tl...@blackberry.com>


Project: http://git-wip-us.apache.org/repos/asf/cordova-blackberry/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-blackberry/commit/011f8421
Tree: http://git-wip-us.apache.org/repos/asf/cordova-blackberry/tree/011f8421
Diff: http://git-wip-us.apache.org/repos/asf/cordova-blackberry/diff/011f8421

Branch: refs/heads/3.1.x
Commit: 011f8421082ecbe14cb4226610d3cd0a652d8199
Parents: f81a762
Author: Jeffrey Heifetz <jh...@blackberry.com>
Authored: Thu Aug 15 10:24:05 2013 -0400
Committer: Jeffrey Heifetz <jh...@blackberry.com>
Committed: Thu Aug 29 09:41:15 2013 -0400

----------------------------------------------------------------------
 blackberry10/.gitignore                         |   1 +
 blackberry10/bin/lib/utils.js                   |  34 +-
 .../templates/project/cordova/lib/localize.js   |   3 +
 .../bin/templates/project/cordova/lib/run       | 439 ++++++++++---------
 .../project/cordova/lib/target-utils.js         |  40 +-
 blackberry10/package.json                       |   4 +-
 6 files changed, 291 insertions(+), 230 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-blackberry/blob/011f8421/blackberry10/.gitignore
----------------------------------------------------------------------
diff --git a/blackberry10/.gitignore b/blackberry10/.gitignore
index a87ff43..bd46f91 100644
--- a/blackberry10/.gitignore
+++ b/blackberry10/.gitignore
@@ -18,6 +18,7 @@ build/
 dist/
 bin/node_modules
 bin/templates/project/lib
+bin/templates/project/cordova/lib/utils.js
 example/
 node_modules/
 .tmp

http://git-wip-us.apache.org/repos/asf/cordova-blackberry/blob/011f8421/blackberry10/bin/lib/utils.js
----------------------------------------------------------------------
diff --git a/blackberry10/bin/lib/utils.js b/blackberry10/bin/lib/utils.js
index 627cbdd..9831223 100644
--- a/blackberry10/bin/lib/utils.js
+++ b/blackberry10/bin/lib/utils.js
@@ -20,6 +20,7 @@ var fs = require('fs'),
     wrench = require('wrench'),
     localize = require("./localize"),
     os = require('os'),
+    prompt = require("prompt"),
     DEFAULT_BAR_NAME = "bb10app",
     PROPERTY_FILE_NAME = 'blackberry10.json',
     CORDOVA_DIR = '.cordova',
@@ -234,7 +235,7 @@ _self = {
             i;
 
         for (i = 0; i < args.length; i++) {
-            if (args[i].indexOf(" ") !== -1) {
+            if (args[i] && args[i].indexOf(" ") !== -1) {
                 if (!_self.isWindows()) {
                     //remove any escaped spaces on non-Windows platforms and simply use quotes
                     args[i] = args[i].replace(/\\ /g, " ");
@@ -247,6 +248,8 @@ _self = {
 
         //delete _customOptions from options object before sending to exec
         delete options._customOptions;
+        //Use the process env by default
+        options.env = options.env || process.env;
 
         proc = childProcess.exec(args.join(" "), options, callback);
 
@@ -301,6 +304,35 @@ _self = {
 
     genBarName: function () {
         return DEFAULT_BAR_NAME;
+    },
+
+    clone: function (original) {
+        var clone = {};
+        if (typeof original !== "object") {
+            clone = original;
+        } else if (Array.isArray(original)) {
+            clone =original.slice();
+        } else {
+            for (var prop in original) {
+                clone[prop] = original[prop];
+            }
+        }
+
+        return clone;
+    },
+    prompt: function (options, done) {
+        var promptSchema = {
+                properties: {
+                    "property": options
+                }
+            };
+        prompt.start();
+        prompt.colors = false;
+        prompt.message = "";
+        prompt.delimiter = "";
+        prompt.get(promptSchema, function (err, results) {
+            done(err, results.property);
+        });
     }
 
 };

http://git-wip-us.apache.org/repos/asf/cordova-blackberry/blob/011f8421/blackberry10/bin/templates/project/cordova/lib/localize.js
----------------------------------------------------------------------
diff --git a/blackberry10/bin/templates/project/cordova/lib/localize.js b/blackberry10/bin/templates/project/cordova/lib/localize.js
index d51629a..df260f8 100755
--- a/blackberry10/bin/templates/project/cordova/lib/localize.js
+++ b/blackberry10/bin/templates/project/cordova/lib/localize.js
@@ -198,6 +198,9 @@ var Localize = require("localize"),
         },
         "PROGRESS_GENERATING_DEBUG_TOKEN": {
             "en": "Generating debug token"
+        },
+        "WARN_RUN_DEVICE_OVERIDES_EMULATOR": {
+            "en": "Skipping emulator detection and detecting device. Please provide only 1 of --target, --device, and --emulator"
         }
 
     }, "", ""); // TODO maybe a bug in localize, must set default locale to "" in order get it to work

http://git-wip-us.apache.org/repos/asf/cordova-blackberry/blob/011f8421/blackberry10/bin/templates/project/cordova/lib/run
----------------------------------------------------------------------
diff --git a/blackberry10/bin/templates/project/cordova/lib/run b/blackberry10/bin/templates/project/cordova/lib/run
index 63b7d24..1375859 100755
--- a/blackberry10/bin/templates/project/cordova/lib/run
+++ b/blackberry10/bin/templates/project/cordova/lib/run
@@ -27,30 +27,26 @@ var childProcess = require("child_process"),
     localize = require("./localize"),
     pkgrUtils = require("./packager-utils"),
     debugTokenHelper = require("./debugtoken-helper"),
-    targets = utils.getProperties(),
     program = require('commander'),
     xml2js = require('xml2js'),
-    jWorkflow = require("jWorkflow"),
     logger = require("./logger"),
-    pin,
-    needCreateDebugToken = false,
-    needDeployDebugToken = false,
-    commandStr,
-    target,
-    ip,
-    password,
+    async = require("async"),
+    properties = utils.getProperties(),
     workingdir = path.normalize(__dirname + "/..");
 
-function generateOptions(uninstall) {
+function generateOptions(deployTarget, uninstall) {
     var options = [],
-        barPath = pkgrUtils.escapeStringForShell(path.normalize(__dirname + "/../../build/" + targets.targets[target].type + "/" + utils.genBarName() + ".bar"));
+        barPath = pkgrUtils.escapeStringForShell(
+            path.normalize(__dirname + "/../../build/" +
+                           (deployTarget.type === "device" ? "device" : "simulator") +
+                           "/" + utils.genBarName() + ".bar"));
 
     options.push("-device");
-    options.push(ip);
+    options.push(deployTarget.ip);
 
-    if (password) {
+    if (deployTarget.password) {
         options.push("-password");
-        options.push(password);
+        options.push(deployTarget.password);
     }
 
     options.push("-package");
@@ -80,12 +76,12 @@ function execNativeDeploy(options, callback) {
     }, callback);
 }
 
-function checkDeviceInfo(ip, deviceType, callback) {
+function checkDeviceInfo(ip, deviceType, devicePass, done) {
     var props = utils.getProperties(),
         targetName;
 
-    targetUtils.getDeviceInfo(ip, program["devicepass"], function (device) {
-        if (device.name) {
+    targetUtils.getDeviceInfo(ip, devicePass, function (err, device) {
+        if (!err) {
             targetName = device.name + "-" + device.pin;
             props.targets[targetName] = {
                 ip: ip,
@@ -93,239 +89,262 @@ function checkDeviceInfo(ip, deviceType, callback) {
                 type: deviceType
             };
             utils.writeToPropertiesFile(props);
-            target = targetName;
-            callback();
-        } else {
-            if (deviceType === "device") {
-                console.error("Unable to authenticate with device at " + ip);
-            } else {
-                console.error("Unable to authenticate with simulator at " + ip);
-            }
-
-            if (!program["devicepass"]) {
-                console.error("Please provide device password using --devicepass");
-            }
-
-            process.exit(1);
         }
+        done(err, targetName);
     });
 }
 
-function setTarget(callback) {
-    target = program.args[0] ? program.args[0] : targets.defaultTarget;
-    if (program["device"]) {
-        targetUtils.findConnectedDevice(function (ip) {
-            if (!ip) {
-                console.error("No connected device found");
-                process.exit(1);
-            } else {
-                checkDeviceInfo(ip, "device", callback);
-            }
-        });
-    } else if (program["emulator"]) {
-        targetUtils.findConnectedSimulator(function (ip) {
-            if (!ip) {
-                console.error("No connected BlackBerry 10 simulator found");
-                process.exit(1);
-            } else {
-                checkDeviceInfo(ip, "simulator", callback);
+function getTargetName (done) {
+    var ipFinder = program.device ? targetUtils.findConnectedDevice : targetUtils.findConnectedSimulator,
+        targetType = program.device ? "device" : "emulator";
+
+    if (program.target) {
+        done(null, program.target);
+    } else if (program.device || program.emulator) {
+        if (program.device && program.emulator) {
+            localize.translate("WARN_RUN_DEVICE_OVERIDES_EMULATOR");
+        }
+
+        async.series(
+            {
+                ip: function (done) {
+                    ipFinder(function (ip) {
+                        done(null, ip);
+                    });
+                },
+                devicePass: function (done) {
+                    if (!program.devicepass && program.devicepass !== "") {
+                        if (program.query) {
+                            utils.prompt({description: "Please enter your " + targetType +  " password: ", hidden: true}, done);
+                        } else {
+                            done("Please provide device password using --devicepass");
+                        }
+                    } else {
+                        done(null, program.devicepass);
+                    }
+                }
+            },
+            function (err, results) {
+                if (err) {
+                    done(err);
+                } else if (!results.ip) {
+                    done("No connected BlackBerry 10 " + targetType + " found");
+                } else {
+                    program.devicepass = results.devicePass;
+                    checkDeviceInfo(results.ip, targetType, results.devicePass, done);
+                }
             }
-        });
+        );
     } else {
-        callback();
+        done(null, properties.defaultTarget);
     }
 }
 
-function checkTarget() {
-    if (!target) {
-        console.log("No target exists, to add that target please run target add <name> <ip> [-t | --type <device | simulator>] [-p <password>] [--pin <devicepin>]");
-        console.log(program.helpInformation());
-        return false;
-    }
-    if (!targets.targets[target]) {
-        console.log("The target \"" + target + "\" does not exist, to add that target please run target add " + target + " <ip> [-t | --type <device | simulator>] [-p <password>] [--pin <devicepin>]");
-        console.log(program.helpInformation());
-        return false;
-    }
-    if (targets.targets[target].ip) {
-        ip = targets.targets[target].ip;
-    } else {
-        console.log("IP is not defined in target \"" + target + "\"");
-        console.log(program.helpInformation());
-        return false;
-    }
-    if (targets.targets[target].password) {
-        password = targets.targets[target].password;
+
+function validateTarget(targetName, allDone) {
+    var deployTarget,
+        err,
+        runTasks = [];
+
+    if (!targetName) {
+        err = "No target exists, to add that target please run target add <name> <ip> [-t | --type <device | simulator>] [-p <password>] [--pin <devicepin>]";
+    } else if (!properties.targets[targetName]) {
+        err = "The target \"" + targetName + "\" does not exist, to add that target please run target add " + targetName + " <ip> [-t | --type <device | simulator>] [-p <password>] [--pin <devicepin>]";
     } else {
-        password = program["devicepass"];
+        deployTarget = utils.clone(properties.targets[targetName]);
+        deployTarget.name = targetName;
+
+        if (!deployTarget.ip) {
+            if (program.query) {
+                runTasks.push(function (done) {
+                    utils.prompt({description: "Please enter the IP address for target " + deployTarget.name + ": "}, function (e, ip) {
+                        deployTarget.ip = ip;
+                        done(e);
+                    });
+                });
+            } else {
+                err = "IP is not defined in target \"" + target + "\"";
+            }
+        }
+
+        if (!deployTarget.password && deployTarget.password !== "") {
+            if (program.devicepass || program.devicepass === "") {
+                deployTarget.password = program.devicepass;
+            } else {
+                if (program.query) {
+                    runTasks.push(function (done) {
+                        utils.prompt({description: "Please enter your " + deployTarget.type +  " password: ", hidden: true}, function (e, devicePass) {
+                            deployTarget.password = devicePass;
+                            done(e);
+                        });
+                    });
+                } else {
+                    err = "Please provide device password using --devicepass or add one to the target " + deployTarget.name + " defined at " + utils.getPropertiesFilePath();
+                }
+            }
+        }
     }
-    return true;
-}
 
-function deploy() {
-    var options = generateOptions(false);
-    execNativeDeploy(options, function (code) {
-        if (code) {
-            process.exit(2);
-        } else {
-            process.exit(0);
+    async.series(runTasks, function (e) {
+        var finalErr = err || e;
+        if (!finalErr && deployTarget) {
+            logger.info("Target " + deployTarget.name + " selected");
         }
+        allDone(err || e, deployTarget);
     });
 }
 
-function uninstall() {
+function uninstall(deployTarget, allDone) {
     var script = path.join(process.env.CORDOVA_BBTOOLS, "blackberry-deploy"),
         args = [
             "-listInstalledApps",
             "-device",
-            ip,
-            "-password",
-            password
-        ];
+            deployTarget.ip
+        ],
+        projectRootDir = path.normalize(path.join(__dirname, "..")),
+        installedAppsOutput,
+        runTasks = [];
 
-    utils.exec(script, args, {
-        "cwd": workingdir,
-        "env": process.env,
-        _customOptions: { silent: true}
-    }, function (error, stdout, stderr) {
-        var parser = new xml2js.Parser();
-        fs.readFile(path.join(__dirname + "/../../www/", "config.xml"), function (err, data) {
-            parser.parseString(data, function (err, result) {
-                if (stdout.indexOf(result['@'].id) !== -1) {
-                    var options = generateOptions(true);
-                    execNativeDeploy(options, function () {
-                        deploy();
-                    });
+    if (program.uninstall) {
+        if (deployTarget.password) {
+            args.push("-password", deployTarget.password);
+        }
+        runTasks = [
+            utils.exec.bind(this, script, args, { "cwd": projectRootDir, _customOptions: {silent: true}}),
+            function listInstalledAppsOutput (stdout, stderr, done) {
+                installedAppsOutput = stdout;
+                fs.readFile(path.join(__dirname + "/../../www/", "config.xml"), done);
+            },
+            function configXMLOutput (result, done) {
+                var parser = new xml2js.Parser();
+                parser.parseString(result, done);
+            },
+            function parsedConfigXMLOutput (result, done) {
+                if (installedAppsOutput.indexOf(result['@'].id) !== -1) {
+                    var options = generateOptions(deployTarget, true);
+                    execNativeDeploy(options, done);
                 } else {
-                    deploy();
+                    done();
                 }
-            });
-        });
-    });
+            }
+
+        ]
+    }
+
+    async.waterfall(runTasks,
+        function (err, results) {
+            //Absorb error for uninstallation
+            allDone(null, deployTarget);
+        }
+    );
 }
 
-function checkDebugtoken(previous, baton) {
-    baton.take();
+function handleDebugToken(deployTarget, allDone) {
+    program.keystorepass = program.keystorepass || properties.keystorepass;
 
     // if target has no pin, skip the debug token feature
-    if (targets.targets[target].pin) {
-        debugTokenHelper.checkDebugToken(targets.targets[target].pin, function (valid) {
-            // If the debug token is not valid, we need create new debug token
-            if (valid) {
-                // No need to create the debug token
+    if (deployTarget.pin) {
+        async.waterfall(
+            [
+                debugTokenHelper.checkDebugToken.bind(this, deployTarget.pin),
+                function (done) {
+                    //If no keystorepass is provided debugTokenHelper will throw an error.
+                    if (!program.keystorepass && program.query) {
+                        utils.prompt({description: "Please enter your keystore password: ", hidden: true}, function (err, result) {
+                            program.keystorepass = result;
+                            done(err, result);
+                        });
+                    } else {
+                        done(program.keystorepass);
+                    }
+                },
+                debugTokenHelper.createToken.bind(this, properties, "all")
+
+        ],
+        function (err, results) {
+            // If the error is true, then the debug token is valid and creation was skipped.
+            if (err === true) {
                 logger.info(localize.translate("PROGRESS_DEBUG_TOKEN_IS_VALID"));
-                needDeployDebugToken = true;
-            } else {
-                needCreateDebugToken = true;
+                //Clear the error so it is still deployed
+                err = null;
             }
-            baton.pass();
-        });
-    } else {
-        baton.pass();
-    }
-}
 
-function createDebugToken(previous, baton) {
-    var keystorepass = program["keystorepass"] ? program["keystorepass"] : targets.keystorepass;
-
-    baton.take();
-
-    if (needCreateDebugToken) {
-        debugTokenHelper.createToken(targets, "all", keystorepass, function (error, stdout, stderr) {
-            if (!error) {
-                // Deploy the debug token if created
-                needDeployDebugToken = true;
+            if (!err) {
+                debugTokenHelper.deployToken(deployTarget.name, deployTarget.ip, deployTarget.password, function (code) {
+                    allDone(code, deployTarget);
+                });
+            } else {
+                allDone(err);
             }
-
-            baton.pass();
-        });
+        }
+        );
     } else {
-        baton.pass();
+        allDone(null, deployTarget);
     }
 }
 
-function deployDebugToken(previous, baton) {
-    baton.take();
-
-    // If in debug build and debug token was created, deploy the debug token and wait until the deployment is finished
-    if (needDeployDebugToken) {
-        debugTokenHelper.deployToken(target, ip, password, function () {
-            baton.pass();
-        });
-    } else {
-        baton.pass();
-    }
+function install(deployTarget, done) {
+    var buildCmd = utils.isWindows() ? "build" : "./build",
+        buildArgs = program.keystorepass ? ["-k", program.keystorepass] : [],
+        projectRootDir = path.normalize(path.join(__dirname, ".."));
+
+    async.series(
+        [
+            utils.exec.bind(this, buildCmd, buildArgs, {"cwd": projectRootDir}),
+            uninstall.bind(this, deployTarget),
+            execNativeDeploy.bind(this, generateOptions(deployTarget))
+        ],
+        done
+    );
 }
 
-function handleBuildOutput(data) {
-    var msg = data.toString().replace(/[\n\r]/g, '');
-    console.log(msg);
-}
 
-function build(previous, baton) {
-    var execName = utils.isWindows() ? "build" : "./build",
-        callback = function (code) {
-            // If error happened during building the bar, exit
-            if (code === 2) {
-                process.exit(2);
-            }
-
-            baton.pass();
-        };
-
-    baton.take();
-
-    utils.exec(execName, [], {
-        "cwd": path.normalize(__dirname + "/.."),
-        "env": process.env
-    }, callback);
-}
-
-function postBuild() {
-    if (program.uninstall) {
-        uninstall();
-    } else {
-        deploy();
-    }
-}
+program
+    .usage('[--device] [--emulator] [--target=<id>]    [--query] [-k | --keystorepass] [-devicepass]    [--no-launch] [--no-uninstall] [--no-build]')
+    .option('-k, --keystorepass <password>', 'the password of signing key; needed for creating debug token')
+    .option('--device', 'run on connected device')
+    .option('--emulator', 'run on BB10 simulator')
+    .option('--devicepass <password>', 'device password')
+    .option('--target <id>', 'specifies the target to run the application')
+    .option('--query', 'query on the commandline when a password is needed')
+    .option('--no-uninstall', 'does not uninstall application from device')
+    .option('--no-launch', 'do not launch the application on device')
+    .option('--no-build', 'deploy the pre-built bar file and skip building')
+    .on('--help', function() {
+        console.log('  Examples:');
+        console.log('');
+        console.log("  Deploying to a predefined target");
+        console.log('    $ run --target=Z10');
+        console.log("  Deploying to a connected device");
+        console.log('    $ run --device --devicepass devicePassword --keystorepass keystorePassword');
+        console.log('');
+    });
 
-function exec() {
-    program
-        .usage('[--device] [--emulator] [--devicepass] [--target=<id>] [-k | --keystorepass] [--no-launch] [--no-uninstall] [--no-build]')
-        .option('-k, --keystorepass <password>', 'the password of signing key; needed for creating debug token')
-        .option('--device', 'run on connected device')
-        .option('--emulator', 'run on BB10 simulator')
-        .option('--devicepass <password>', 'device password')
-        .option('--target', 'specifies the target to run the application')
-        .option('--no-uninstall', 'does not uninstall application from device')
-        .option('--no-launch', 'do not launch the application on device')
-        .option('--no-build', 'deploy the pre-built bar file and skip building');
-
-    commandStr = typeof process.argv[2] === "string" ? process.argv[2] : undefined;
-    if (commandStr && commandStr.indexOf("--target=") === 0) {
-        // Convert "--target=<id>" into "--target id"
-        process.argv[2] = "--target";
-        process.argv.splice(3, 0, commandStr.substring("--target=".length));
+process.argv.forEach(function (argument, index, args) {
+    if (argument.match(/^--target=/)) {
+        args.splice(index, 1, "--target", argument.substr("--target=".length));
     }
-
-    program.parse(process.argv);
-
-    setTarget(function () {
-        if (checkTarget()) {
-            if (program.build) {
-                jWorkflow.order(checkDebugtoken)
-                    .andThen(createDebugToken)
-                    .andThen(deployDebugToken)
-                    .andThen(build)
-                    .andThen(postBuild)
-                    .start();
-            } else {
-                postBuild();
+});
+
+program.parse(process.argv);
+
+async.waterfall(
+    [
+        getTargetName,
+        validateTarget,
+        handleDebugToken,
+        install
+    ],
+    function (err) {
+        if (err) {
+            if (typeof err === "string") {
+                logger.error(err);
+                process.exit(1);
+            } else if (typeof err === "number") {
+                process.exit(err);
             }
         } else {
-            process.exit(1);
+            process.exit(0);
         }
-    });
-}
-
-exec();
+    }
+);

http://git-wip-us.apache.org/repos/asf/cordova-blackberry/blob/011f8421/blackberry10/bin/templates/project/cordova/lib/target-utils.js
----------------------------------------------------------------------
diff --git a/blackberry10/bin/templates/project/cordova/lib/target-utils.js b/blackberry10/bin/templates/project/cordova/lib/target-utils.js
index af95296..3e83200 100644
--- a/blackberry10/bin/templates/project/cordova/lib/target-utils.js
+++ b/blackberry10/bin/templates/project/cordova/lib/target-utils.js
@@ -80,7 +80,8 @@ _self = {
         }
 
         bb10_utils.exec(cmd, args, options, function (error, stdout, stderr) {
-            var result = {},
+            var err = error,
+                result = {},
                 name = /modelname::(.*?)(\r?)\n/.exec(stdout),
                 pin = /devicepin::0x(.*?)(\r?)\n/.exec(stdout);
             if (name && name.length > 0) {
@@ -90,30 +91,33 @@ _self = {
                 result.pin = pin[1];
             }
 
-            callback(result);
+            if (!result.name) {
+                if (stdout.indexOf("Error:") !== -1) {
+                    err = stdout.slice(stdout.indexOf("Error:") + 6);
+                } else if (stdout === "" && stderr.indexOf("Error:") === 0) {
+                    err = stderr.slice(7);
+                } else {
+                    err = "Unable to authenticate with BlackBerry 10 device/emulator at " + ip + ".";
+                }
+            }
+
+            callback(err, result);
         });
     },
 
     findConnectedDevice: function (callback) {
         var defaultIp = '169.254.0.1';
         _self.discoverUsb(function (result) {
-            if (result) {
-                _self.checkConnection(result, 'device', function (connection) {
-                    if (connection)  {
-                        callback(result);
-                    } else {
-                        callback();
-                    }
-                });
-            } else {
-                _self.checkConnection(defaultIp, 'device', function (connection) {
-                    if (connection) {
-                        callback(defaultIp);
-                    } else {
-                        callback();
-                    }
-                });
+            if (!result) {
+                result = defaultIp;
             }
+            _self.checkConnection(result, 'device', function (connection) {
+                if (connection)  {
+                    callback(result);
+                } else {
+                    callback();
+                }
+            });
         });
     },
 

http://git-wip-us.apache.org/repos/asf/cordova-blackberry/blob/011f8421/blackberry10/package.json
----------------------------------------------------------------------
diff --git a/blackberry10/package.json b/blackberry10/package.json
index 166c66a..2185b89 100644
--- a/blackberry10/package.json
+++ b/blackberry10/package.json
@@ -26,7 +26,9 @@
     "validator": "0.4.1",
     "wrench": "1.3.9",
     "shelljs":"0.1.3",
-    "elementtree": "0.1.5"
+    "elementtree": "0.1.5",
+    "prompt": "0.2.11",
+    "async": "0.2.9"
   },
   "devDependencies": {
     "jake":"*",