UNPKG

7.04 kBJavaScriptView Raw
1/**
2 * Detects Windows Phone devices.
3 *
4 * @module device
5 *
6 * @copyright
7 * Copyright (c) 2014 by Appcelerator, Inc. All Rights Reserved.
8 *
9 * @license
10 * Licensed under the terms of the Apache Public License.
11 * Please see the LICENSE included with this distribution for details.
12 */
13
14const
15 appc = require('node-appc'),
16 async = require('async'),
17 fs = require('fs'),
18 magik = require('./utilities').magik,
19 path = require('path'),
20 spawn = require('child_process').spawn,
21 windowsphone = require('./windowsphone'),
22 wptool = require('./wptool'),
23 __ = appc.i18n(__dirname).__;
24
25var cache;
26
27exports.detect = detect;
28exports.connect = connect;
29exports.install = install;
30
31/**
32 * Detects connected Windows Phone devices.
33 *
34 * @param {Object} [options] - An object containing various settings.
35 * @param {Boolean} [options.bypassCache=false] - When true, re-detects all Windows Phone devices.
36 * @param {Function} [callback(err, results)] - A function to call with the device information.
37 *
38 * @emits module:device#detected
39 * @emits module:device#error
40 *
41 * @returns {EventEmitter}
42 */
43function detect(options, callback) {
44 return magik(options, callback, function (emitter, options, callback) {
45 if (cache && !options.bypassCache) {
46 emitter.emit('detected', cache);
47 return callback(null, cache);
48 }
49
50 wptool.enumerate(options, function (err, results) {
51 var result = {
52 devices: [],
53 issues: []
54 };
55
56 if (!err) {
57 var tmp = {};
58
59 Object.keys(results).forEach(function (wpsdk) {
60 results[wpsdk].devices.forEach(function (dev) {
61 if (!tmp[dev.udid]) {
62 tmp[dev.udid] = result.devices.length+1;
63 result.devices.push(dev);
64 } else if (dev.wpsdk) {
65 result.devices[tmp[dev.udid]-1] = dev;
66 }
67 });
68 });
69
70 cache = result;
71 }
72
73 emitter.emit('detected', result);
74 callback(null, result);
75 });
76 });
77};
78
79/**
80 * Tries to connect to the specified device and will error if there are no devices connected
81 * or there are more than one connected devices.
82 *
83 * @param {String} udid - The UDID of the device to connect to or null if you want windowslib to pick one.
84 * @param {Object} [options] - An object containing various settings.
85 * @param {Boolean} [options.bypassCache=false] - When true, re-detects the environment configuration.
86 * @param {Function} [callback(err)] - A function to call when the simulator has launched.
87 *
88 * @returns {EventEmitter}
89 */
90function connect(udid, options, callback) {
91 return wptool.connect(udid, options, callback);
92}
93
94/**
95 * Installs the specified app to an Windows Phone device. If the device is not
96 * connected or more than one is connected, then an error is returned. After the
97 * app is installed, it will be automatically launched if possible and the options.skipLaunch flag isn't false
98 *
99 * @param {String} udid - The UDID of the device to install the app to or null if you want windowslib to pick one.
100 * @param {String} appPath - The path to the Windows Phone app to install.
101 * @param {Object} [options] - An object containing various settings.
102 * @param {Boolean} [options.bypassCache=false] - When true, re-detects the environment configuration.
103 * @param {Boolean} [options.skipLaunch=false] - When true, only installs the app, does not attempt to launch it.
104 * @param {Number} [options.timeout] - Number of milliseconds to wait before timing out. Minimum of 1000 milliseconds.
105 * @param {String} [options.wpsdk] - The Windows Phone SDK to use for the deploy tool. If not specified, it will autodetect.
106 * @param {Function} [callback(err)] - A function to call when the app is installed. To know when the app gets launched, hook an event listener for 'launched' event
107 *
108 * @emits module:device#error
109 * @emits module:device#installed
110 * @emits module:device#launched
111 *
112 * @returns {EventEmitter}
113 */
114function install(udid, appPath, options, callback) {
115 return magik(options, callback, function (emitter, options, callback) {
116 if (typeof appPath !== 'string' || !appPath) {
117 var ex = new Error(__('Missing required "%s" argument', 'appPath'));
118 emitter.emit('error', ex);
119 return callback(ex);
120 }
121
122 if (!fs.existsSync(appPath)) {
123 var ex = new Error(__('App path does not exist: ' + appPath));
124 emitter.emit('error', ex);
125 return callback(ex);
126 }
127
128 // detect devices, use cached listing!
129 detect(options, function (err, devInfo) {
130 if (err) {
131 emitter.emit('error', err);
132 return callback(err);
133 }
134
135 var devHandle;
136 var devices = devInfo.devices;
137
138 if (udid) {
139 // validate the udid
140 devices.some(function (dev) {
141 if (dev.udid === udid) {
142 devHandle = appc.util.mix({}, dev);
143 return true;
144 }
145 return false;
146 });
147
148 if (!devHandle) {
149 err = new Error(__('Unable to find a Windows Phone device with the UDID "%s"', udid));
150 }
151 } else if (devices.length) {
152 devHandle = appc.util.mix({}, devices[0]);
153 } else {
154 // user experience!
155 if (options.wpsdk) {
156 err = new Error(__('Unable to find a Windows Phone %s device.', options.wpsdk));
157 } else {
158 err = new Error(__('Unable to find a Windows Phone device.'));
159 }
160 }
161
162 if (err) {
163 emitter.emit('error', err);
164 return callback(err);
165 }
166
167 // connect to the device to see if it's connected...
168 // this will add a second or two to the build time, but at least if there was
169 // an error, we'll get a decent message
170 wptool.connect(devHandle.udid, options)
171 .on('error', function (err) {
172 emitter.emit('error', err);
173 return callback(err);
174 })
175 .on('connected', function (dev) {
176 devHandle.ip = dev.ip; // copy the IP address we got from connecting
177 devHandle.running = dev.running || true; // copy running status we got fromc onnecting
178 // device is good to go, install the app!
179 var timeout = options.timeout !== void 0 && Math.max(~~options.timeout, 1000), // minimum of 1 second
180 mixedOptions = appc.util.mix({timeout: timeout}, options);
181 wptool.install(devHandle, appPath, mixedOptions)
182 .on('error', function (err) {
183 emitter.emit('error', err);
184 callback(err);
185 }).on('installed', function () {
186 emitter.emit('installed', devHandle);
187 // If we're not going to launch, this is the end of the lifecycle here.
188 if (mixedOptions.skipLaunch) {
189 callback(null, devHandle);
190 }
191 }).on('launched', function () {
192 emitter.emit('launched', devHandle);
193 // Don't do callback until we launch if we're supposed to be launching
194 if (!mixedOptions.skipLaunch) {
195 callback(null, devHandle);
196 }
197 }).on('timeout', function (err) {
198 err || (err = new Error(__('Timed out after %d milliseconds waiting to launch the device.', timeout)));
199 emitter.emit('timeout', err);
200 callback(err);
201 });
202 });
203 });
204 });
205}