You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
193 lines
7.9 KiB
193 lines
7.9 KiB
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", {
|
|
value: true
|
|
});
|
|
exports.getConnectedDevices = getConnectedDevices;
|
|
exports.isEnabled = isEnabled;
|
|
exports.runOnDevice = runOnDevice;
|
|
function _debug() {
|
|
const data = _interopRequireDefault(require("debug"));
|
|
_debug = function () {
|
|
return data;
|
|
};
|
|
return data;
|
|
}
|
|
function _fs() {
|
|
const data = require("fs");
|
|
_fs = function () {
|
|
return data;
|
|
};
|
|
return data;
|
|
}
|
|
function _getenv() {
|
|
const data = require("getenv");
|
|
_getenv = function () {
|
|
return data;
|
|
};
|
|
return data;
|
|
}
|
|
function path() {
|
|
const data = _interopRequireWildcard(require("path"));
|
|
path = function () {
|
|
return data;
|
|
};
|
|
return data;
|
|
}
|
|
function _lib() {
|
|
const data = require("./native-run/ios/lib");
|
|
_lib = function () {
|
|
return data;
|
|
};
|
|
return data;
|
|
}
|
|
function _xcode() {
|
|
const data = require("./native-run/ios/utils/xcode");
|
|
_xcode = function () {
|
|
return data;
|
|
};
|
|
return data;
|
|
}
|
|
function _process() {
|
|
const data = require("./native-run/utils/process");
|
|
_process = function () {
|
|
return data;
|
|
};
|
|
return data;
|
|
}
|
|
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
const EXPO_USE_APPLE_DEVICE = (0, _getenv().boolish)('EXPO_USE_APPLE_DEVICE', false);
|
|
const debug = (0, _debug().default)('expo:xdl:ios:utils:device');
|
|
function isEnabled() {
|
|
return EXPO_USE_APPLE_DEVICE;
|
|
}
|
|
async function getConnectedDevices() {
|
|
const usbmuxClient = new (_lib().UsbmuxdClient)(_lib().UsbmuxdClient.connectUsbmuxdSocket());
|
|
const usbmuxDevices = await usbmuxClient.getDevices();
|
|
usbmuxClient.socket.end();
|
|
return Promise.all(usbmuxDevices.map(async d => {
|
|
const socket = await new (_lib().UsbmuxdClient)(_lib().UsbmuxdClient.connectUsbmuxdSocket()).connect(d, 62078);
|
|
const device = await new (_lib().LockdowndClient)(socket).getAllValues();
|
|
socket.end();
|
|
return device;
|
|
}));
|
|
}
|
|
async function runOnDevice({
|
|
udid,
|
|
appPath,
|
|
bundleId,
|
|
waitForApp,
|
|
deltaPath,
|
|
onProgress
|
|
}) {
|
|
const clientManager = await _lib().ClientManager.create(udid);
|
|
try {
|
|
await mountDeveloperDiskImage(clientManager);
|
|
const packageName = path().basename(appPath);
|
|
const destPackagePath = path().join('PublicStaging', packageName);
|
|
await uploadApp(clientManager, appPath, destPackagePath);
|
|
const installer = await clientManager.getInstallationProxyClient();
|
|
await installer.installApp(destPackagePath, bundleId, {
|
|
// https://github.com/ios-control/ios-deploy/blob/0f2ffb1e564aa67a2dfca7cdf13de47ce489d835/src/ios-deploy/ios-deploy.m#L2491-L2508
|
|
ApplicationsType: 'Any',
|
|
CFBundleIdentifier: bundleId,
|
|
CloseOnInvalidate: '1',
|
|
InvalidateOnDetach: '1',
|
|
IsUserInitiated: '1',
|
|
// Disable checking for wifi devices, this is nominally faster.
|
|
PreferWifi: '0',
|
|
// Only info I could find on these:
|
|
// https://github.com/wwxxyx/Quectel_BG96/blob/310876f90fc1093a59e45e381160eddcc31697d0/Apple_Homekit/homekit_certification_tools/ATS%206/ATS%206/ATS.app/Contents/Frameworks/CaptureKit.framework/Versions/A/Resources/MobileDevice/MobileInstallation.h#L112-L121
|
|
PackageType: 'Developer',
|
|
ShadowParentKey: deltaPath
|
|
// SkipUninstall: '1'
|
|
}, onProgress);
|
|
const {
|
|
[bundleId]: appInfo
|
|
} = await installer.lookupApp([bundleId]);
|
|
// launch fails with EBusy or ENotFound if you try to launch immediately after install
|
|
await (0, _process().wait)(200);
|
|
const debugServerClient = await launchApp(clientManager, {
|
|
appInfo,
|
|
detach: !waitForApp
|
|
});
|
|
if (waitForApp) {
|
|
(0, _process().onBeforeExit)(async () => {
|
|
// causes continue() to return
|
|
debugServerClient.halt();
|
|
// give continue() time to return response
|
|
await (0, _process().wait)(64);
|
|
});
|
|
debug(`Waiting for app to close...\n`);
|
|
const result = await debugServerClient.continue();
|
|
// TODO: I have no idea what this packet means yet (successful close?)
|
|
// if not a close (ie, most likely due to halt from onBeforeExit), then kill the app
|
|
if (result !== 'W00') {
|
|
await debugServerClient.kill();
|
|
}
|
|
}
|
|
} finally {
|
|
clientManager.end();
|
|
}
|
|
}
|
|
async function mountDeveloperDiskImage(clientManager) {
|
|
const imageMounter = await clientManager.getMobileImageMounterClient();
|
|
// Check if already mounted. If not, mount.
|
|
if (!(await imageMounter.lookupImage()).ImageSignature) {
|
|
// verify DeveloperDiskImage exists (TODO: how does this work on Windows/Linux?)
|
|
// TODO: if windows/linux, download?
|
|
const version = await (await clientManager.getLockdowndClient()).getValue('ProductVersion');
|
|
const developerDiskImagePath = await (0, _xcode().getDeveloperDiskImagePath)(version);
|
|
const developerDiskImageSig = (0, _fs().readFileSync)(`${developerDiskImagePath}.signature`);
|
|
await imageMounter.uploadImage(developerDiskImagePath, developerDiskImageSig);
|
|
await imageMounter.mountImage(developerDiskImagePath, developerDiskImageSig);
|
|
}
|
|
}
|
|
async function uploadApp(clientManager, srcPath, destinationPath) {
|
|
const afcClient = await clientManager.getAFCClient();
|
|
try {
|
|
await afcClient.getFileInfo('PublicStaging');
|
|
} catch (err) {
|
|
if (err instanceof _lib().AFCError && err.status === _lib().AFC_STATUS.OBJECT_NOT_FOUND) {
|
|
await afcClient.makeDirectory('PublicStaging');
|
|
} else {
|
|
throw err;
|
|
}
|
|
}
|
|
await afcClient.uploadDirectory(srcPath, destinationPath);
|
|
}
|
|
async function launchApp(clientManager, {
|
|
appInfo,
|
|
detach
|
|
}) {
|
|
let tries = 0;
|
|
while (tries < 3) {
|
|
const debugServerClient = await clientManager.getDebugserverClient();
|
|
await debugServerClient.setMaxPacketSize(1024);
|
|
await debugServerClient.setWorkingDir(appInfo.Container);
|
|
await debugServerClient.launchApp(appInfo.Path, appInfo.CFBundleExecutable);
|
|
const result = await debugServerClient.checkLaunchSuccess();
|
|
if (result === 'OK') {
|
|
if (detach) {
|
|
// https://github.com/libimobiledevice/libimobiledevice/blob/25059d4c7d75e03aab516af2929d7c6e6d4c17de/tools/idevicedebug.c#L455-L464
|
|
const res = await debugServerClient.sendCommand('D', []);
|
|
debug('Disconnect from debug server request:', res);
|
|
if (res !== 'OK') {
|
|
console.warn('Something went wrong while attempting to disconnect from iOS debug server, you may need to reopen the app manually.');
|
|
}
|
|
}
|
|
return debugServerClient;
|
|
} else if (result === 'EBusy' || result === 'ENotFound') {
|
|
debug('Device busy or app not found, trying to launch again in .5s...');
|
|
tries++;
|
|
debugServerClient.socket.end();
|
|
await (0, _process().wait)(500);
|
|
} else {
|
|
throw new Error(`There was an error launching app: ${result}`);
|
|
}
|
|
}
|
|
throw new Error('Unable to launch app, number of tries exceeded');
|
|
}
|
|
//# sourceMappingURL=AppleDevice.js.map
|