@expo/cli 0.18.1 → 0.18.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,353 @@
1
+ /**
2
+ * Copyright © 2024 650 Industries.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */ "use strict";
7
+ Object.defineProperty(exports, "__esModule", {
8
+ value: true
9
+ });
10
+ function _export(target, all) {
11
+ for(var name in all)Object.defineProperty(target, name, {
12
+ enumerable: true,
13
+ get: all[name]
14
+ });
15
+ }
16
+ _export(exports, {
17
+ devicectlAsync: ()=>devicectlAsync,
18
+ getConnectedAppleDevicesAsync: ()=>getConnectedAppleDevicesAsync,
19
+ launchAppWithDeviceCtl: ()=>launchAppWithDeviceCtl,
20
+ hasDevicectlEverBeenInstalled: ()=>hasDevicectlEverBeenInstalled,
21
+ installAndLaunchAppAsync: ()=>installAndLaunchAppAsync
22
+ });
23
+ function _getUserState() {
24
+ const data = require("@expo/config/build/getUserState");
25
+ _getUserState = function() {
26
+ return data;
27
+ };
28
+ return data;
29
+ }
30
+ function _jsonFile() {
31
+ const data = /*#__PURE__*/ _interopRequireDefault(require("@expo/json-file"));
32
+ _jsonFile = function() {
33
+ return data;
34
+ };
35
+ return data;
36
+ }
37
+ function _chalk() {
38
+ const data = /*#__PURE__*/ _interopRequireDefault(require("chalk"));
39
+ _chalk = function() {
40
+ return data;
41
+ };
42
+ return data;
43
+ }
44
+ function _childProcess() {
45
+ const data = require("child_process");
46
+ _childProcess = function() {
47
+ return data;
48
+ };
49
+ return data;
50
+ }
51
+ function _fs() {
52
+ const data = /*#__PURE__*/ _interopRequireDefault(require("fs"));
53
+ _fs = function() {
54
+ return data;
55
+ };
56
+ return data;
57
+ }
58
+ function _nodeAssert() {
59
+ const data = /*#__PURE__*/ _interopRequireDefault(require("node:assert"));
60
+ _nodeAssert = function() {
61
+ return data;
62
+ };
63
+ return data;
64
+ }
65
+ function _os() {
66
+ const data = require("os");
67
+ _os = function() {
68
+ return data;
69
+ };
70
+ return data;
71
+ }
72
+ function _path() {
73
+ const data = /*#__PURE__*/ _interopRequireDefault(require("path"));
74
+ _path = function() {
75
+ return data;
76
+ };
77
+ return data;
78
+ }
79
+ function _tempy() {
80
+ const data = /*#__PURE__*/ _interopRequireDefault(require("tempy"));
81
+ _tempy = function() {
82
+ return data;
83
+ };
84
+ return data;
85
+ }
86
+ const _xcrun = require("./xcrun");
87
+ const _log = /*#__PURE__*/ _interopRequireWildcard(require("../../../log"));
88
+ const _errors = require("../../../utils/errors");
89
+ const _exit = require("../../../utils/exit");
90
+ const _interactive = require("../../../utils/interactive");
91
+ const _ora = require("../../../utils/ora");
92
+ const _prompts = require("../../../utils/prompts");
93
+ function _interopRequireDefault(obj) {
94
+ return obj && obj.__esModule ? obj : {
95
+ default: obj
96
+ };
97
+ }
98
+ function _getRequireWildcardCache(nodeInterop) {
99
+ if (typeof WeakMap !== "function") return null;
100
+ var cacheBabelInterop = new WeakMap();
101
+ var cacheNodeInterop = new WeakMap();
102
+ return (_getRequireWildcardCache = function(nodeInterop) {
103
+ return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
104
+ })(nodeInterop);
105
+ }
106
+ function _interopRequireWildcard(obj, nodeInterop) {
107
+ if (!nodeInterop && obj && obj.__esModule) {
108
+ return obj;
109
+ }
110
+ if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
111
+ return {
112
+ default: obj
113
+ };
114
+ }
115
+ var cache = _getRequireWildcardCache(nodeInterop);
116
+ if (cache && cache.has(obj)) {
117
+ return cache.get(obj);
118
+ }
119
+ var newObj = {};
120
+ var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
121
+ for(var key in obj){
122
+ if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
123
+ var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
124
+ if (desc && (desc.get || desc.set)) {
125
+ Object.defineProperty(newObj, key, desc);
126
+ } else {
127
+ newObj[key] = obj[key];
128
+ }
129
+ }
130
+ }
131
+ newObj.default = obj;
132
+ if (cache) {
133
+ cache.set(obj, newObj);
134
+ }
135
+ return newObj;
136
+ }
137
+ const DEVICE_CTL_EXISTS_PATH = _path().default.join((0, _getUserState().getExpoHomeDirectory)(), "devicectl-exists");
138
+ const debug = require("debug")("expo:devicectl");
139
+ async function devicectlAsync(args, options) {
140
+ try {
141
+ return await (0, _xcrun.xcrunAsync)([
142
+ "devicectl",
143
+ ...args
144
+ ], options);
145
+ } catch (error) {
146
+ if (error instanceof _errors.CommandError) {
147
+ throw error;
148
+ }
149
+ if ("stderr" in error) {
150
+ const errorCodes = getDeviceCtlErrorCodes(error.stderr);
151
+ if (errorCodes.includes("Locked")) {
152
+ throw new _errors.CommandError("APPLE_DEVICE_LOCKED", "Device is locked, unlock and try again.");
153
+ }
154
+ }
155
+ throw error;
156
+ }
157
+ }
158
+ async function getConnectedAppleDevicesAsync() {
159
+ var ref, ref1;
160
+ if (!hasDevicectlEverBeenInstalled()) {
161
+ debug("devicectl not found, skipping remote Apple devices.");
162
+ return [];
163
+ }
164
+ const tmpPath = _tempy().default.file();
165
+ const devices = await devicectlAsync([
166
+ "list",
167
+ "devices",
168
+ "--json-output",
169
+ tmpPath,
170
+ // Give two seconds before timing out: between 5 and 9223372036854775807
171
+ "--timeout",
172
+ "5",
173
+ ]);
174
+ debug(devices.stdout);
175
+ const devicesJson = await _jsonFile().default.readAsync(tmpPath);
176
+ if (((ref = devicesJson) == null ? void 0 : (ref1 = ref.info) == null ? void 0 : ref1.jsonVersion) !== 2) {
177
+ _log.warn("Unexpected devicectl JSON version output from devicectl. Connecting to physical Apple devices may not work as expected.");
178
+ }
179
+ assertDevicesJson(devicesJson);
180
+ return devicesJson.result.devices;
181
+ }
182
+ function assertDevicesJson(results) {
183
+ var ref;
184
+ (0, _nodeAssert().default)(results != null && "result" in results && Array.isArray(results == null ? void 0 : (ref = results.result) == null ? void 0 : ref.devices), "Malformed JSON output from devicectl: " + JSON.stringify(results, null, 2));
185
+ }
186
+ async function installAppWithDeviceCtlAsync(uuid, bundleIdOrAppPath, onProgress) {
187
+ // 𝝠 xcrun devicectl device install app --device 00001110-001111110110101A /Users/evanbacon/Library/Developer/Xcode/DerivedData/Router-hgbqaxzhrhkiftfweydvhgttadvn/Build/Products/Debug-iphoneos/Router.app --verbose
188
+ return new Promise((resolve, reject)=>{
189
+ const args = [
190
+ "devicectl",
191
+ "device",
192
+ "install",
193
+ "app",
194
+ "--device",
195
+ uuid,
196
+ bundleIdOrAppPath,
197
+ ];
198
+ const childProcess = (0, _childProcess().spawn)("xcrun", args);
199
+ debug("xcrun " + args.join(" "));
200
+ let currentProgress = 0;
201
+ let hasStarted = false;
202
+ function updateProgress(progress) {
203
+ hasStarted = true;
204
+ if (progress <= currentProgress) {
205
+ return;
206
+ }
207
+ currentProgress = progress;
208
+ onProgress({
209
+ progress,
210
+ isComplete: progress === 100,
211
+ status: "Installing"
212
+ });
213
+ }
214
+ childProcess.stdout.on("data", (data)=>{
215
+ // Sometimes more than one chunk comes at a time, here we split by system newline,
216
+ // then trim and filter.
217
+ const strings = data.toString().split(_os().EOL).map((value)=>value.trim());
218
+ strings.forEach((str)=>{
219
+ // Match the progress percentage:
220
+ // - '34%... 35%...' -> 34
221
+ // - '31%...' -> 31
222
+ // - 'Complete!' -> 100
223
+ const match = str.match(/(\d+)%\.\.\./);
224
+ if (match) {
225
+ updateProgress(parseInt(match[1], 10));
226
+ } else if (hasStarted) {
227
+ updateProgress(100);
228
+ }
229
+ });
230
+ debug("[stdout]:", strings);
231
+ });
232
+ childProcess.on("close", (code)=>{
233
+ debug("[close]: " + code);
234
+ if (code === 0) {
235
+ resolve();
236
+ } else {
237
+ const stderr = childProcess.stderr.read();
238
+ const err = new Error(stderr);
239
+ err.code = code;
240
+ detach(err);
241
+ }
242
+ });
243
+ const detach = async (err)=>{
244
+ off == null ? void 0 : off();
245
+ if (childProcess) {
246
+ return new Promise((resolve)=>{
247
+ childProcess == null ? void 0 : childProcess.on("close", resolve);
248
+ childProcess == null ? void 0 : childProcess.kill();
249
+ // childProcess = null;
250
+ reject(err != null ? err : new _errors.CommandError("detached"));
251
+ });
252
+ }
253
+ };
254
+ const off = (0, _exit.installExitHooks)(()=>detach());
255
+ });
256
+ }
257
+ async function launchAppWithDeviceCtl(deviceId, bundleId) {
258
+ try {
259
+ await devicectlAsync([
260
+ "device",
261
+ "process",
262
+ "launch",
263
+ "--device",
264
+ deviceId,
265
+ bundleId
266
+ ]);
267
+ } catch (error) {
268
+ if (error instanceof _errors.CommandError) {
269
+ throw error;
270
+ }
271
+ throw new _errors.CommandError(`There was an error launching app: ${error}`);
272
+ }
273
+ }
274
+ /** Find all error codes from the output log */ function getDeviceCtlErrorCodes(log) {
275
+ return [
276
+ ...log.matchAll(/BSErrorCodeDescription\s+=\s+(.*)$/gim)
277
+ ].map(([_line, code])=>code);
278
+ }
279
+ let hasEverBeenInstalled;
280
+ function hasDevicectlEverBeenInstalled() {
281
+ if (hasEverBeenInstalled) return hasEverBeenInstalled;
282
+ // It doesn't appear possible for devicectl to ever be uninstalled. We can just check once and store this result forever
283
+ // to prevent cold boots of devicectl from slowing down all invocations of `expo run ios`
284
+ if (_fs().default.existsSync(DEVICE_CTL_EXISTS_PATH)) {
285
+ hasEverBeenInstalled = true;
286
+ return true;
287
+ }
288
+ const isInstalled = isDevicectlInstalled();
289
+ if (isInstalled) {
290
+ _fs().default.writeFileSync(DEVICE_CTL_EXISTS_PATH, "1");
291
+ }
292
+ hasEverBeenInstalled = isInstalled;
293
+ return isInstalled;
294
+ }
295
+ function isDevicectlInstalled() {
296
+ try {
297
+ (0, _childProcess().execSync)("xcrun devicectl --version", {
298
+ stdio: "ignore"
299
+ });
300
+ return true;
301
+ } catch {
302
+ return false;
303
+ }
304
+ }
305
+ async function installAndLaunchAppAsync(props) {
306
+ debug("Running on device:", props);
307
+ const { bundle , bundleIdentifier , udid , deviceName } = props;
308
+ let indicator;
309
+ try {
310
+ if (!indicator) {
311
+ indicator = (0, _ora.ora)(`Connecting to: ${props.deviceName}`).start();
312
+ }
313
+ await installAppWithDeviceCtlAsync(udid, bundle, ({ status , isComplete , progress })=>{
314
+ if (!indicator) {
315
+ indicator = (0, _ora.ora)(status).start();
316
+ }
317
+ indicator.text = `${_chalk().default.bold(status)} ${progress}%`;
318
+ if (isComplete) {
319
+ indicator.succeed();
320
+ }
321
+ });
322
+ } catch (error) {
323
+ if (indicator) {
324
+ indicator.fail();
325
+ }
326
+ throw error;
327
+ }
328
+ async function launchAppOptionally() {
329
+ try {
330
+ await launchAppWithDeviceCtl(udid, bundleIdentifier);
331
+ } catch (error) {
332
+ if (indicator) {
333
+ indicator.fail();
334
+ }
335
+ if (error.code === "APPLE_DEVICE_LOCKED") {
336
+ var ref;
337
+ // Get the app name from the binary path.
338
+ const appName = (ref = _path().default.basename(bundle).split(".")[0]) != null ? ref : "app";
339
+ if ((0, _interactive.isInteractive)() && await (0, _prompts.confirmAsync)({
340
+ message: `Cannot launch ${appName} because the device is locked. Unlock ${deviceName} to continue...`,
341
+ initial: true
342
+ })) {
343
+ return launchAppOptionally();
344
+ }
345
+ throw new _errors.CommandError(`Cannot launch ${appName} on ${deviceName} because the device is locked.`);
346
+ }
347
+ throw error;
348
+ }
349
+ }
350
+ await launchAppOptionally();
351
+ }
352
+
353
+ //# sourceMappingURL=devicectl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../src/start/platforms/ios/devicectl.ts"],"sourcesContent":["/**\n * Copyright © 2024 650 Industries.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport { getExpoHomeDirectory } from '@expo/config/build/getUserState';\nimport JsonFile from '@expo/json-file';\nimport { SpawnOptions, SpawnResult } from '@expo/spawn-async';\nimport chalk from 'chalk';\nimport { spawn, execSync } from 'child_process';\nimport fs from 'fs';\nimport assert from 'node:assert';\nimport { Ora } from 'ora';\nimport { EOL } from 'os';\nimport path from 'path';\nimport tempy from 'tempy';\n\nimport { xcrunAsync } from './xcrun';\nimport * as Log from '../../../log';\nimport { CommandError } from '../../../utils/errors';\nimport { installExitHooks } from '../../../utils/exit';\nimport { isInteractive } from '../../../utils/interactive';\nimport { ora } from '../../../utils/ora';\nimport { confirmAsync } from '../../../utils/prompts';\n\nconst DEVICE_CTL_EXISTS_PATH = path.join(getExpoHomeDirectory(), 'devicectl-exists');\n\nconst debug = require('debug')('expo:devicectl') as typeof console.log;\n\n// eslint-disable-next-line @typescript-eslint/ban-types\ntype AnyEnum<T extends string = string> = T | (string & {});\n\ntype DeviceCtlDevice = {\n capabilities: DeviceCtlDeviceCapability[];\n connectionProperties: DeviceCtlConnectionProperties;\n deviceProperties: DeviceCtlDeviceProperties;\n hardwareProperties: DeviceCtlHardwareProperties;\n /** \"A1A1AAA1-0011-1AA1-11A1-10A1111AA11A\" */\n identifier: string;\n visibilityClass: AnyEnum<'default'>;\n};\n\ntype DeviceCtlHardwareProperties = {\n cpuType: DeviceCtlCpuType;\n deviceType: AnyEnum<'iPhone'>;\n /** 1114404411111111 */\n ecid: number;\n /** \"D74AP\" */\n hardwareModel: string;\n /** 512000000000 */\n internalStorageCapacity: number;\n /** true */\n isProductionFused: boolean;\n /** \"iPhone 14 Pro Max\" */\n marketingName: string;\n /** \"iOS\" */\n platform: string;\n /** \"iPhone15,3\" */\n productType: AnyEnum<'iPhone13,4' | 'iPhone15,3'>;\n reality: AnyEnum<'physical'>;\n /** \"X2X1CC1XXX\" */\n serialNumber: string;\n supportedCPUTypes: DeviceCtlCpuType[];\n /** [1] */\n supportedDeviceFamilies: number[];\n thinningProductType: AnyEnum<'iPhone15,3'>;\n /** \"00001110-001111110110101A\" */\n udid: string;\n};\n\ntype DeviceCtlDeviceProperties = {\n /** true */\n bootedFromSnapshot: boolean;\n /** \"com.apple.os.update-AD0CF111ACFF11A11111A76A3D1262AE42A3F56F305AF5AE1135393A7A14A7D1\" */\n bootedSnapshotName: string;\n /** false */\n ddiServicesAvailable: boolean;\n\n developerModeStatus: AnyEnum<'enabled'>;\n /** false */\n hasInternalOSBuild: boolean;\n /** \"Evan's phone\" */\n name: string;\n /** \"21E236\" */\n osBuildUpdate: string;\n /** \"17.4.1\" */\n osVersionNumber: string;\n /** false */\n rootFileSystemIsWritable: boolean;\n};\n\ntype DeviceCtlDeviceCapability =\n | {\n name: AnyEnum;\n featureIdentifier: AnyEnum;\n }\n | {\n featureIdentifier: 'com.apple.coredevice.feature.connectdevice';\n name: 'Connect to Device';\n }\n | {\n featureIdentifier: 'com.apple.coredevice.feature.unpairdevice';\n name: 'Unpair Device';\n }\n | {\n featureIdentifier: 'com.apple.coredevice.feature.acquireusageassertion';\n name: 'Acquire Usage Assertion';\n };\n\ntype DeviceCtlConnectionProperties = {\n authenticationType: AnyEnum<'manualPairing'>;\n isMobileDeviceOnly: boolean;\n /** \"2024-04-20T22:50:04.244Z\" */\n lastConnectionDate: string;\n pairingState: AnyEnum<'paired'>;\n /** [\"00001111-001111110110101A.coredevice.local\", \"A1A1AAA1-0011-1AA1-11A1-10A1111AA11A.coredevice.local\"] */\n potentialHostnames: string[];\n transportType: AnyEnum<'localNetwork' | 'wired'>;\n tunnelState: AnyEnum<'disconnected'>;\n tunnelTransportProtocol: AnyEnum<'tcp'>;\n};\n\ntype DeviceCtlCpuType = {\n name: AnyEnum<'arm64e' | 'arm64' | 'arm64_32'>;\n subType: number;\n /** 16777228 */\n type: number;\n};\n\n/** Run a `devicectl` command. */\nexport async function devicectlAsync(\n args: (string | undefined)[],\n options?: SpawnOptions\n): Promise<SpawnResult> {\n try {\n return await xcrunAsync(['devicectl', ...args], options);\n } catch (error: any) {\n if (error instanceof CommandError) {\n throw error;\n }\n if ('stderr' in error) {\n const errorCodes = getDeviceCtlErrorCodes(error.stderr);\n if (errorCodes.includes('Locked')) {\n throw new CommandError('APPLE_DEVICE_LOCKED', 'Device is locked, unlock and try again.');\n }\n }\n throw error;\n }\n}\n\nexport async function getConnectedAppleDevicesAsync() {\n if (!hasDevicectlEverBeenInstalled()) {\n debug('devicectl not found, skipping remote Apple devices.');\n return [];\n }\n\n const tmpPath = tempy.file();\n const devices = await devicectlAsync([\n 'list',\n 'devices',\n '--json-output',\n tmpPath,\n // Give two seconds before timing out: between 5 and 9223372036854775807\n '--timeout',\n '5',\n ]);\n debug(devices.stdout);\n const devicesJson = await JsonFile.readAsync(tmpPath);\n\n if ((devicesJson as any)?.info?.jsonVersion !== 2) {\n Log.warn(\n 'Unexpected devicectl JSON version output from devicectl. Connecting to physical Apple devices may not work as expected.'\n );\n }\n\n assertDevicesJson(devicesJson);\n\n return devicesJson.result.devices as DeviceCtlDevice[];\n}\n\nfunction assertDevicesJson(\n results: any\n): asserts results is { result: { devices: DeviceCtlDevice[] } } {\n assert(\n results != null && 'result' in results && Array.isArray(results?.result?.devices),\n 'Malformed JSON output from devicectl: ' + JSON.stringify(results, null, 2)\n );\n}\n\nasync function installAppWithDeviceCtlAsync(\n uuid: string,\n bundleIdOrAppPath: string,\n onProgress: (event: { status: string; isComplete: boolean; progress: number }) => void\n): Promise<void> {\n // 𝝠 xcrun devicectl device install app --device 00001110-001111110110101A /Users/evanbacon/Library/Developer/Xcode/DerivedData/Router-hgbqaxzhrhkiftfweydvhgttadvn/Build/Products/Debug-iphoneos/Router.app --verbose\n return new Promise((resolve, reject) => {\n const args: string[] = [\n 'devicectl',\n 'device',\n 'install',\n 'app',\n '--device',\n uuid,\n bundleIdOrAppPath,\n ];\n const childProcess = spawn('xcrun', args);\n debug('xcrun ' + args.join(' '));\n\n let currentProgress = 0;\n let hasStarted = false;\n\n function updateProgress(progress: number) {\n hasStarted = true;\n if (progress <= currentProgress) {\n return;\n }\n currentProgress = progress;\n onProgress({\n progress,\n isComplete: progress === 100,\n status: 'Installing',\n });\n }\n\n childProcess.stdout.on('data', (data: Buffer) => {\n // Sometimes more than one chunk comes at a time, here we split by system newline,\n // then trim and filter.\n const strings = data\n .toString()\n .split(EOL)\n .map((value) => value.trim());\n\n strings.forEach((str) => {\n // Match the progress percentage:\n // - '34%... 35%...' -> 34\n // - '31%...' -> 31\n // - 'Complete!' -> 100\n\n const match = str.match(/(\\d+)%\\.\\.\\./);\n if (match) {\n updateProgress(parseInt(match[1], 10));\n } else if (hasStarted) {\n updateProgress(100);\n }\n });\n\n debug('[stdout]:', strings);\n });\n\n childProcess.on('close', (code) => {\n debug('[close]: ' + code);\n if (code === 0) {\n resolve();\n } else {\n const stderr = childProcess.stderr.read();\n const err = new Error(stderr);\n (err as any).code = code;\n detach(err);\n }\n });\n\n const detach = async (err?: Error) => {\n off?.();\n if (childProcess) {\n return new Promise<void>((resolve) => {\n childProcess?.on('close', resolve);\n childProcess?.kill();\n // childProcess = null;\n reject(err ?? new CommandError('detached'));\n });\n }\n };\n\n const off = installExitHooks(() => detach());\n });\n}\n\nexport async function launchAppWithDeviceCtl(deviceId: string, bundleId: string) {\n try {\n await devicectlAsync(['device', 'process', 'launch', '--device', deviceId, bundleId]);\n } catch (error: any) {\n if (error instanceof CommandError) {\n throw error;\n }\n\n throw new CommandError(`There was an error launching app: ${error}`);\n }\n}\n\n/** Find all error codes from the output log */\nfunction getDeviceCtlErrorCodes(log: string): string[] {\n return [...log.matchAll(/BSErrorCodeDescription\\s+=\\s+(.*)$/gim)].map(([_line, code]) => code);\n}\n\nlet hasEverBeenInstalled: boolean | undefined;\n\nexport function hasDevicectlEverBeenInstalled() {\n if (hasEverBeenInstalled) return hasEverBeenInstalled;\n // It doesn't appear possible for devicectl to ever be uninstalled. We can just check once and store this result forever\n // to prevent cold boots of devicectl from slowing down all invocations of `expo run ios`\n if (fs.existsSync(DEVICE_CTL_EXISTS_PATH)) {\n hasEverBeenInstalled = true;\n return true;\n }\n\n const isInstalled = isDevicectlInstalled();\n\n if (isInstalled) {\n fs.writeFileSync(DEVICE_CTL_EXISTS_PATH, '1');\n }\n hasEverBeenInstalled = isInstalled;\n return isInstalled;\n}\n\nfunction isDevicectlInstalled() {\n try {\n execSync('xcrun devicectl --version', { stdio: 'ignore' });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Wraps the apple device method for installing and running an app,\n * adds indicator and retry loop for when the device is locked.\n */\nexport async function installAndLaunchAppAsync(props: {\n bundle: string;\n bundleIdentifier: string;\n udid: string;\n deviceName: string;\n}): Promise<void> {\n debug('Running on device:', props);\n const { bundle, bundleIdentifier, udid, deviceName } = props;\n let indicator: Ora | undefined;\n\n try {\n if (!indicator) {\n indicator = ora(`Connecting to: ${props.deviceName}`).start();\n }\n\n await installAppWithDeviceCtlAsync(\n udid,\n bundle,\n ({\n status,\n isComplete,\n progress,\n }: {\n status: string;\n isComplete: boolean;\n progress: number;\n }) => {\n if (!indicator) {\n indicator = ora(status).start();\n }\n indicator.text = `${chalk.bold(status)} ${progress}%`;\n if (isComplete) {\n indicator.succeed();\n }\n }\n );\n } catch (error: any) {\n if (indicator) {\n indicator.fail();\n }\n throw error;\n }\n\n async function launchAppOptionally() {\n try {\n await launchAppWithDeviceCtl(udid, bundleIdentifier);\n } catch (error: any) {\n if (indicator) {\n indicator.fail();\n }\n if (error.code === 'APPLE_DEVICE_LOCKED') {\n // Get the app name from the binary path.\n const appName = path.basename(bundle).split('.')[0] ?? 'app';\n if (\n isInteractive() &&\n (await confirmAsync({\n message: `Cannot launch ${appName} because the device is locked. Unlock ${deviceName} to continue...`,\n initial: true,\n }))\n ) {\n return launchAppOptionally();\n }\n throw new CommandError(\n `Cannot launch ${appName} on ${deviceName} because the device is locked.`\n );\n }\n throw error;\n }\n }\n\n await launchAppOptionally();\n}\n"],"names":["devicectlAsync","getConnectedAppleDevicesAsync","launchAppWithDeviceCtl","hasDevicectlEverBeenInstalled","installAndLaunchAppAsync","DEVICE_CTL_EXISTS_PATH","path","join","getExpoHomeDirectory","debug","require","args","options","xcrunAsync","error","CommandError","errorCodes","getDeviceCtlErrorCodes","stderr","includes","tmpPath","tempy","file","devices","stdout","devicesJson","JsonFile","readAsync","info","jsonVersion","Log","warn","assertDevicesJson","result","results","assert","Array","isArray","JSON","stringify","installAppWithDeviceCtlAsync","uuid","bundleIdOrAppPath","onProgress","Promise","resolve","reject","childProcess","spawn","currentProgress","hasStarted","updateProgress","progress","isComplete","status","on","data","strings","toString","split","EOL","map","value","trim","forEach","str","match","parseInt","code","read","err","Error","detach","off","kill","installExitHooks","deviceId","bundleId","log","matchAll","_line","hasEverBeenInstalled","fs","existsSync","isInstalled","isDevicectlInstalled","writeFileSync","execSync","stdio","props","bundle","bundleIdentifier","udid","deviceName","indicator","ora","start","text","chalk","bold","succeed","fail","launchAppOptionally","appName","basename","isInteractive","confirmAsync","message","initial"],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "AtlasPrerequisite", {
6
+ enumerable: true,
7
+ get: ()=>AtlasPrerequisite
8
+ });
9
+ const _prerequisite = require("../../../doctor/Prerequisite");
10
+ const _ensureDependenciesAsync = require("../../../doctor/dependencies/ensureDependenciesAsync");
11
+ class AtlasPrerequisite extends _prerequisite.ProjectPrerequisite {
12
+ async assertImplementation({ exp } = {}) {
13
+ await this.ensureAtlasInstalled({
14
+ exp
15
+ });
16
+ return true;
17
+ }
18
+ async bootstrapAsync({ exp } = {}) {
19
+ await this.ensureAtlasInstalled({
20
+ exp,
21
+ skipPrompt: true,
22
+ isProjectMutable: true
23
+ });
24
+ }
25
+ async ensureAtlasInstalled(options = {}) {
26
+ try {
27
+ return await (0, _ensureDependenciesAsync.ensureDependenciesAsync)(this.projectRoot, {
28
+ ...options,
29
+ installMessage: "Expo Atlas is required to gather bundle information, but it is not installed in this project.",
30
+ warningMessage: "Expo Atlas is not installed in this project, unable to gather bundle information.",
31
+ requiredPackages: [
32
+ {
33
+ version: "^0.1.1",
34
+ pkg: "expo-atlas",
35
+ file: "expo-atlas/package.json",
36
+ dev: true
37
+ },
38
+ ]
39
+ });
40
+ } catch (error) {
41
+ this.resetAssertion({});
42
+ throw error;
43
+ }
44
+ }
45
+ }
46
+
47
+ //# sourceMappingURL=AtlasPrerequisite.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../src/start/server/metro/debugging/AtlasPrerequisite.ts"],"sourcesContent":["import { ProjectPrerequisite } from '../../../doctor/Prerequisite';\nimport {\n type EnsureDependenciesOptions,\n ensureDependenciesAsync,\n} from '../../../doctor/dependencies/ensureDependenciesAsync';\n\nexport class AtlasPrerequisite extends ProjectPrerequisite<\n boolean,\n Pick<EnsureDependenciesOptions, 'exp'>\n> {\n async assertImplementation({ exp }: Pick<EnsureDependenciesOptions, 'exp'> = {}) {\n await this.ensureAtlasInstalled({ exp });\n return true;\n }\n\n async bootstrapAsync({ exp }: Pick<EnsureDependenciesOptions, 'exp'> = {}) {\n await this.ensureAtlasInstalled({ exp, skipPrompt: true, isProjectMutable: true });\n }\n\n private async ensureAtlasInstalled(options: Partial<EnsureDependenciesOptions> = {}) {\n try {\n return await ensureDependenciesAsync(this.projectRoot, {\n ...options,\n installMessage:\n 'Expo Atlas is required to gather bundle information, but it is not installed in this project.',\n warningMessage:\n 'Expo Atlas is not installed in this project, unable to gather bundle information.',\n requiredPackages: [\n { version: '^0.1.1', pkg: 'expo-atlas', file: 'expo-atlas/package.json', dev: true },\n ],\n });\n } catch (error) {\n this.resetAssertion({});\n throw error;\n }\n }\n}\n"],"names":["AtlasPrerequisite","ProjectPrerequisite","assertImplementation","exp","ensureAtlasInstalled","bootstrapAsync","skipPrompt","isProjectMutable","options","ensureDependenciesAsync","projectRoot","installMessage","warningMessage","requiredPackages","version","pkg","file","dev","error","resetAssertion"],"mappings":"AAAA;;;;+BAMaA,mBAAiB;;aAAjBA,iBAAiB;;8BANM,8BAA8B;yCAI3D,sDAAsD;AAEtD,MAAMA,iBAAiB,SAASC,aAAmB,oBAAA;UAIlDC,oBAAoB,CAAC,EAAEC,GAAG,CAAA,EAA0C,GAAG,EAAE,EAAE;QAC/E,MAAM,IAAI,CAACC,oBAAoB,CAAC;YAAED,GAAG;SAAE,CAAC,CAAC;QACzC,OAAO,IAAI,CAAC;IACd;UAEME,cAAc,CAAC,EAAEF,GAAG,CAAA,EAA0C,GAAG,EAAE,EAAE;QACzE,MAAM,IAAI,CAACC,oBAAoB,CAAC;YAAED,GAAG;YAAEG,UAAU,EAAE,IAAI;YAAEC,gBAAgB,EAAE,IAAI;SAAE,CAAC,CAAC;IACrF;UAEcH,oBAAoB,CAACI,OAA2C,GAAG,EAAE,EAAE;QACnF,IAAI;YACF,OAAO,MAAMC,IAAAA,wBAAuB,wBAAA,EAAC,IAAI,CAACC,WAAW,EAAE;gBACrD,GAAGF,OAAO;gBACVG,cAAc,EACZ,+FAA+F;gBACjGC,cAAc,EACZ,mFAAmF;gBACrFC,gBAAgB,EAAE;oBAChB;wBAAEC,OAAO,EAAE,QAAQ;wBAAEC,GAAG,EAAE,YAAY;wBAAEC,IAAI,EAAE,yBAAyB;wBAAEC,GAAG,EAAE,IAAI;qBAAE;iBACrF;aACF,CAAC,CAAC;QACL,EAAE,OAAOC,KAAK,EAAE;YACd,IAAI,CAACC,cAAc,CAAC,EAAE,CAAC,CAAC;YACxB,MAAMD,KAAK,CAAC;QACd,CAAC;IACH;CACD"}
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "attachAtlasAsync", {
6
+ enumerable: true,
7
+ get: ()=>attachAtlasAsync
8
+ });
9
+ const _atlasPrerequisite = require("./AtlasPrerequisite");
10
+ const _env = require("../../../../utils/env");
11
+ const debug = require("debug")("expo:metro:debugging:attachAtlas");
12
+ async function attachAtlasAsync({ exp , isExporting , projectRoot , middleware , metroConfig }) {
13
+ if (!_env.env.EXPO_UNSTABLE_ATLAS) {
14
+ return;
15
+ }
16
+ debug("Atlas is enabled, initializing for this project...");
17
+ await new _atlasPrerequisite.AtlasPrerequisite(projectRoot).bootstrapAsync({
18
+ exp
19
+ });
20
+ // Exporting only sets up Metro, without attaching middleware
21
+ if (isExporting) {
22
+ const atlas = importAtlasForExport(projectRoot);
23
+ if (!atlas) {
24
+ return debug("Atlas is not installed in the project, skipping initialization");
25
+ }
26
+ atlas.withExpoAtlas(metroConfig);
27
+ debug("Attached Atlas to Metro config for exporting");
28
+ return;
29
+ }
30
+ // Running in development mode requires middleware to be attached
31
+ if (!isExporting && !middleware) {
32
+ throw new Error("Expected middleware to be provided for Atlas when running in development mode");
33
+ } else if (!isExporting && middleware) {
34
+ const atlas1 = importAtlasForDev(projectRoot);
35
+ if (!atlas1) {
36
+ return debug("Atlas is not installed in the project, skipping initialization");
37
+ }
38
+ const instance = atlas1.createExpoAtlasMiddleware(metroConfig);
39
+ middleware.use("/_expo/atlas", instance.middleware);
40
+ debug("Attached Atlas middleware for development on: /_expo/atlas");
41
+ return instance;
42
+ }
43
+ }
44
+ function importAtlasForDev(projectRoot) {
45
+ try {
46
+ return require(require.resolve("expo-atlas/cli", {
47
+ paths: [
48
+ projectRoot
49
+ ]
50
+ }));
51
+ } catch (error) {
52
+ debug("Failed to load Atlas from project:", error);
53
+ return null;
54
+ }
55
+ }
56
+ function importAtlasForExport(projectRoot) {
57
+ try {
58
+ return require(require.resolve("expo-atlas/metro", {
59
+ paths: [
60
+ projectRoot
61
+ ]
62
+ }));
63
+ } catch (error) {
64
+ debug("Failed to load Atlas from project:", error);
65
+ return null;
66
+ }
67
+ }
68
+
69
+ //# sourceMappingURL=attachAtlas.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../src/start/server/metro/debugging/attachAtlas.ts"],"sourcesContent":["import type { Server as ConnectServer } from 'connect';\nimport type { ConfigT as MetroConfig } from 'metro-config';\n\nimport { AtlasPrerequisite } from './AtlasPrerequisite';\nimport { env } from '../../../../utils/env';\nimport { type EnsureDependenciesOptions } from '../../../doctor/dependencies/ensureDependenciesAsync';\n\nconst debug = require('debug')('expo:metro:debugging:attachAtlas') as typeof console.log;\n\ntype AttachAtlasOptions = Pick<EnsureDependenciesOptions, 'exp'> & {\n isExporting: boolean;\n projectRoot: string;\n middleware?: ConnectServer;\n metroConfig: MetroConfig;\n};\n\nexport async function attachAtlasAsync({\n exp,\n isExporting,\n projectRoot,\n middleware,\n metroConfig,\n}: AttachAtlasOptions): Promise<void | ReturnType<\n typeof import('expo-atlas/cli').createExpoAtlasMiddleware\n>> {\n if (!env.EXPO_UNSTABLE_ATLAS) {\n return;\n }\n\n debug('Atlas is enabled, initializing for this project...');\n\n await new AtlasPrerequisite(projectRoot).bootstrapAsync({ exp });\n\n // Exporting only sets up Metro, without attaching middleware\n if (isExporting) {\n const atlas = importAtlasForExport(projectRoot);\n if (!atlas) {\n return debug('Atlas is not installed in the project, skipping initialization');\n }\n\n atlas.withExpoAtlas(metroConfig);\n debug('Attached Atlas to Metro config for exporting');\n return;\n }\n\n // Running in development mode requires middleware to be attached\n if (!isExporting && !middleware) {\n throw new Error(\n 'Expected middleware to be provided for Atlas when running in development mode'\n );\n } else if (!isExporting && middleware) {\n const atlas = importAtlasForDev(projectRoot);\n if (!atlas) {\n return debug('Atlas is not installed in the project, skipping initialization');\n }\n\n const instance = atlas.createExpoAtlasMiddleware(metroConfig);\n middleware.use('/_expo/atlas', instance.middleware);\n debug('Attached Atlas middleware for development on: /_expo/atlas');\n return instance;\n }\n}\n\nfunction importAtlasForDev(projectRoot: string): null | typeof import('expo-atlas/cli') {\n try {\n return require(require.resolve('expo-atlas/cli', { paths: [projectRoot] }));\n } catch (error: any) {\n debug('Failed to load Atlas from project:', error);\n return null;\n }\n}\n\nfunction importAtlasForExport(projectRoot: string): null | typeof import('expo-atlas/metro') {\n try {\n return require(require.resolve('expo-atlas/metro', { paths: [projectRoot] }));\n } catch (error: any) {\n debug('Failed to load Atlas from project:', error);\n return null;\n }\n}\n"],"names":["attachAtlasAsync","debug","require","exp","isExporting","projectRoot","middleware","metroConfig","env","EXPO_UNSTABLE_ATLAS","AtlasPrerequisite","bootstrapAsync","atlas","importAtlasForExport","withExpoAtlas","Error","importAtlasForDev","instance","createExpoAtlasMiddleware","use","resolve","paths","error"],"mappings":"AAAA;;;;+BAgBsBA,kBAAgB;;aAAhBA,gBAAgB;;mCAbJ,qBAAqB;qBACnC,uBAAuB;AAG3C,MAAMC,KAAK,GAAGC,OAAO,CAAC,OAAO,CAAC,CAAC,kCAAkC,CAAC,AAAsB,AAAC;AASlF,eAAeF,gBAAgB,CAAC,EACrCG,GAAG,CAAA,EACHC,WAAW,CAAA,EACXC,WAAW,CAAA,EACXC,UAAU,CAAA,EACVC,WAAW,CAAA,EACQ,EAElB;IACD,IAAI,CAACC,IAAG,IAAA,CAACC,mBAAmB,EAAE;QAC5B,OAAO;IACT,CAAC;IAEDR,KAAK,CAAC,oDAAoD,CAAC,CAAC;IAE5D,MAAM,IAAIS,kBAAiB,kBAAA,CAACL,WAAW,CAAC,CAACM,cAAc,CAAC;QAAER,GAAG;KAAE,CAAC,CAAC;IAEjE,6DAA6D;IAC7D,IAAIC,WAAW,EAAE;QACf,MAAMQ,KAAK,GAAGC,oBAAoB,CAACR,WAAW,CAAC,AAAC;QAChD,IAAI,CAACO,KAAK,EAAE;YACV,OAAOX,KAAK,CAAC,gEAAgE,CAAC,CAAC;QACjF,CAAC;QAEDW,KAAK,CAACE,aAAa,CAACP,WAAW,CAAC,CAAC;QACjCN,KAAK,CAAC,8CAA8C,CAAC,CAAC;QACtD,OAAO;IACT,CAAC;IAED,iEAAiE;IACjE,IAAI,CAACG,WAAW,IAAI,CAACE,UAAU,EAAE;QAC/B,MAAM,IAAIS,KAAK,CACb,+EAA+E,CAChF,CAAC;IACJ,OAAO,IAAI,CAACX,WAAW,IAAIE,UAAU,EAAE;QACrC,MAAMM,MAAK,GAAGI,iBAAiB,CAACX,WAAW,CAAC,AAAC;QAC7C,IAAI,CAACO,MAAK,EAAE;YACV,OAAOX,KAAK,CAAC,gEAAgE,CAAC,CAAC;QACjF,CAAC;QAED,MAAMgB,QAAQ,GAAGL,MAAK,CAACM,yBAAyB,CAACX,WAAW,CAAC,AAAC;QAC9DD,UAAU,CAACa,GAAG,CAAC,cAAc,EAAEF,QAAQ,CAACX,UAAU,CAAC,CAAC;QACpDL,KAAK,CAAC,4DAA4D,CAAC,CAAC;QACpE,OAAOgB,QAAQ,CAAC;IAClB,CAAC;AACH,CAAC;AAED,SAASD,iBAAiB,CAACX,WAAmB,EAA0C;IACtF,IAAI;QACF,OAAOH,OAAO,CAACA,OAAO,CAACkB,OAAO,CAAC,gBAAgB,EAAE;YAAEC,KAAK,EAAE;gBAAChB,WAAW;aAAC;SAAE,CAAC,CAAC,CAAC;IAC9E,EAAE,OAAOiB,KAAK,EAAO;QACnBrB,KAAK,CAAC,oCAAoC,EAAEqB,KAAK,CAAC,CAAC;QACnD,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAST,oBAAoB,CAACR,WAAmB,EAA4C;IAC3F,IAAI;QACF,OAAOH,OAAO,CAACA,OAAO,CAACkB,OAAO,CAAC,kBAAkB,EAAE;YAAEC,KAAK,EAAE;gBAAChB,WAAW;aAAC;SAAE,CAAC,CAAC,CAAC;IAChF,EAAE,OAAOiB,KAAK,EAAO;QACnBrB,KAAK,CAAC,oCAAoC,EAAEqB,KAAK,CAAC,CAAC;QACnD,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
@@ -70,6 +70,7 @@ function _url() {
70
70
  return data;
71
71
  }
72
72
  const _metroTerminalReporter = require("./MetroTerminalReporter");
73
+ const _attachAtlas = require("./debugging/attachAtlas");
73
74
  const _createDebugMiddleware = require("./debugging/createDebugMiddleware");
74
75
  const _runServerFork = require("./runServer-fork");
75
76
  const _withMetroMultiPlatform = require("./withMetroMultiPlatform");
@@ -223,6 +224,14 @@ async function instantiateMetroAsync(metroBundler, options, { isExporting }) {
223
224
  const { debugMiddleware , debugWebsocketEndpoints } = (0, _createDebugMiddleware.createDebugMiddleware)(metroBundler);
224
225
  (0, _mutations.prependMiddleware)(middleware, debugMiddleware);
225
226
  middleware.use("/_expo/debugger", (0, _createJsInspectorMiddleware.createJsInspectorMiddleware)());
227
+ // Attach Expo Atlas if enabled
228
+ const atlas = await (0, _attachAtlas.attachAtlasAsync)({
229
+ isExporting,
230
+ exp,
231
+ projectRoot,
232
+ middleware,
233
+ metroConfig
234
+ });
226
235
  const { server , metro } = await (0, _runServerFork.runServer)(metroBundler, metroConfig, {
227
236
  // @ts-expect-error: Inconsistent `websocketEndpoints` type between metro and @react-native-community/cli-server-api
228
237
  websocketEndpoints: {
@@ -231,6 +240,8 @@ async function instantiateMetroAsync(metroBundler, options, { isExporting }) {
231
240
  },
232
241
  watch: !isExporting && isWatchEnabled()
233
242
  });
243
+ // If Atlas is enabled, and can register to Metro, attach it to listen for changes
244
+ atlas == null ? void 0 : atlas.registerMetro(metro);
234
245
  (0, _mutations.prependMiddleware)(middleware, (req, res, next)=>{
235
246
  // If the URL is a Metro asset request, then we need to skip all other middleware to prevent
236
247
  // the community CLI's serve-static from hosting `/assets/index.html` in place of all assets if it exists.