eas-cli 2.5.0 → 2.6.0

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.
Files changed (120) hide show
  1. package/README.md +89 -49
  2. package/build/branch/queries.js +3 -22
  3. package/build/build/queries.d.ts +11 -1
  4. package/build/build/queries.js +39 -1
  5. package/build/channel/queries.js +5 -8
  6. package/build/channel/utils.js +22 -22
  7. package/build/commandUtils/context/LoggedInContextField.d.ts +3 -0
  8. package/build/commandUtils/context/LoggedInContextField.js +9 -1
  9. package/build/commandUtils/context/MaybeLoggedInContextField.d.ts +3 -0
  10. package/build/commandUtils/context/MaybeLoggedInContextField.js +9 -1
  11. package/build/commandUtils/context/contextUtils/createGraphqlClient.d.ts +2 -2
  12. package/build/commandUtils/gating/FeatureGateEnvOverrides.d.ts +7 -0
  13. package/build/commandUtils/gating/FeatureGateEnvOverrides.js +35 -0
  14. package/build/commandUtils/gating/FeatureGateKey.d.ts +4 -0
  15. package/build/commandUtils/gating/FeatureGateKey.js +11 -0
  16. package/build/commandUtils/gating/FeatureGateTestOverrides.d.ts +5 -0
  17. package/build/commandUtils/gating/FeatureGateTestOverrides.js +17 -0
  18. package/build/commandUtils/gating/FeatureGating.d.ts +16 -0
  19. package/build/commandUtils/gating/FeatureGating.js +55 -0
  20. package/build/commandUtils/pagination.d.ts +4 -3
  21. package/build/commands/branch/list.d.ts +1 -1
  22. package/build/commands/branch/view.d.ts +1 -1
  23. package/build/commands/build/configure.d.ts +1 -1
  24. package/build/commands/build/index.d.ts +2 -2
  25. package/build/commands/build/list.d.ts +4 -4
  26. package/build/commands/build/list.js +2 -15
  27. package/build/commands/build/run.d.ts +21 -0
  28. package/build/commands/build/run.js +149 -0
  29. package/build/commands/build/version/set.d.ts +1 -1
  30. package/build/commands/build/version/sync.d.ts +1 -1
  31. package/build/commands/channel/list.d.ts +1 -1
  32. package/build/commands/channel/view.d.ts +1 -1
  33. package/build/commands/config.d.ts +1 -1
  34. package/build/commands/credentials.d.ts +1 -1
  35. package/build/commands/device/list.d.ts +1 -1
  36. package/build/commands/metadata/lint.d.ts +12 -0
  37. package/build/commands/metadata/lint.js +72 -0
  38. package/build/commands/metadata/pull.js +20 -9
  39. package/build/commands/metadata/push.js +20 -9
  40. package/build/commands/secret/create.d.ts +1 -1
  41. package/build/commands/secret/list.js +12 -17
  42. package/build/commands/submit.d.ts +1 -1
  43. package/build/commands/update/configure.js +2 -0
  44. package/build/commands/update/list.d.ts +1 -1
  45. package/build/commands/webhook/create.d.ts +1 -1
  46. package/build/commands/webhook/list.d.ts +1 -1
  47. package/build/commands/webhook/update.d.ts +1 -1
  48. package/build/devices/actions/create/inputMethod.js +2 -15
  49. package/build/devices/utils/formatDevice.d.ts +2 -0
  50. package/build/devices/utils/formatDevice.js +32 -7
  51. package/build/env.d.ts +8 -0
  52. package/build/env.js +8 -0
  53. package/build/graphql/generated.d.ts +74 -6
  54. package/build/graphql/generated.js +10 -2
  55. package/build/graphql/mutations/KeystoreGenerationUrlMutation.js +1 -1
  56. package/build/graphql/queries/UserQuery.js +2 -2
  57. package/build/graphql/types/Build.js +1 -0
  58. package/build/metadata/apple/rules/index.d.ts +1 -0
  59. package/build/metadata/apple/rules/index.js +6 -0
  60. package/build/metadata/apple/rules/infoKeywordLength.d.ts +6 -0
  61. package/build/metadata/apple/rules/infoKeywordLength.js +35 -0
  62. package/build/metadata/apple/rules/infoRestrictedWords.d.ts +6 -0
  63. package/build/metadata/apple/rules/infoRestrictedWords.js +57 -0
  64. package/build/metadata/apple/tasks/index.d.ts +1 -2
  65. package/build/metadata/apple/tasks/index.js +1 -1
  66. package/build/metadata/auth.d.ts +21 -0
  67. package/build/metadata/auth.js +33 -0
  68. package/build/metadata/config/issue.d.ts +21 -0
  69. package/build/metadata/config/issue.js +9 -0
  70. package/build/metadata/config/resolve.d.ts +27 -0
  71. package/build/metadata/{config.js → config/resolve.js} +24 -25
  72. package/build/metadata/config/schema.d.ts +7 -0
  73. package/build/metadata/config/schema.js +2 -0
  74. package/build/metadata/config/validate.d.ts +3 -0
  75. package/build/metadata/config/validate.js +47 -0
  76. package/build/metadata/download.d.ts +11 -2
  77. package/build/metadata/download.js +14 -9
  78. package/build/metadata/errors.d.ts +3 -3
  79. package/build/metadata/errors.js +3 -1
  80. package/build/metadata/upload.d.ts +11 -2
  81. package/build/metadata/upload.js +16 -11
  82. package/build/metadata/utils/ajv.d.ts +10 -0
  83. package/build/metadata/utils/ajv.js +30 -0
  84. package/build/metadata/utils/telemetry.js +6 -6
  85. package/build/project/publish.js +8 -14
  86. package/build/run/android/run.d.ts +1 -0
  87. package/build/run/android/run.js +9 -0
  88. package/build/run/ios/run.d.ts +1 -0
  89. package/build/run/ios/run.js +31 -0
  90. package/build/run/ios/simctl.d.ts +2 -0
  91. package/build/run/ios/simctl.js +8 -0
  92. package/build/run/ios/simulator.d.ts +21 -0
  93. package/build/run/ios/simulator.js +161 -0
  94. package/build/run/ios/systemRequirements.d.ts +1 -0
  95. package/build/run/ios/systemRequirements.js +82 -0
  96. package/build/run/ios/xcode.d.ts +4 -0
  97. package/build/run/ios/xcode.js +41 -0
  98. package/build/run/ios/xcrun.d.ts +4 -0
  99. package/build/run/ios/xcrun.js +68 -0
  100. package/build/run/run.d.ts +8 -0
  101. package/build/run/run.js +15 -0
  102. package/build/submit/utils/summary.d.ts +1 -1
  103. package/build/update/queries.js +30 -39
  104. package/build/update/utils.d.ts +8 -1
  105. package/build/update/utils.js +35 -1
  106. package/build/utils/buildDistribution.d.ts +3 -0
  107. package/build/utils/buildDistribution.js +20 -0
  108. package/build/utils/download.d.ts +2 -0
  109. package/build/utils/download.js +114 -0
  110. package/build/utils/expoCli.d.ts +0 -1
  111. package/build/utils/expoCli.js +1 -8
  112. package/build/utils/expodash/filter.d.ts +2 -0
  113. package/build/utils/expodash/filter.js +8 -0
  114. package/build/utils/formatFields.d.ts +3 -2
  115. package/oclif.manifest.json +1 -1
  116. package/package.json +32 -30
  117. package/schema/metadata-0.json +1 -1
  118. package/build/metadata/config.d.ts +0 -41
  119. package/build/metadata/context.d.ts +0 -50
  120. package/build/metadata/context.js +0 -47
@@ -0,0 +1,161 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getSimulatorAppIdAsync = exports.installAppAsync = exports.ensureSimulatorAppOpenedAsync = exports.launchAppAsync = exports.openSimulatorAppAsync = exports.ensureSimulatorBootedAsync = exports.getAvaliableIosSimulatorsListAsync = exports.getFirstBootedIosSimulatorAsync = exports.selectSimulatorAsync = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const osascript = tslib_1.__importStar(require("@expo/osascript"));
6
+ const spawn_async_1 = tslib_1.__importDefault(require("@expo/spawn-async"));
7
+ const log_1 = tslib_1.__importDefault(require("../../log"));
8
+ const prompts_1 = require("../../prompts");
9
+ const promise_1 = require("../../utils/promise");
10
+ const simctl_1 = require("./simctl");
11
+ async function selectSimulatorAsync() {
12
+ const bootedSimulator = await getFirstBootedIosSimulatorAsync();
13
+ if (bootedSimulator) {
14
+ return bootedSimulator;
15
+ }
16
+ const simulators = await getAvaliableIosSimulatorsListAsync();
17
+ log_1.default.newLine();
18
+ const { selectedSimulator } = await (0, prompts_1.promptAsync)({
19
+ type: 'select',
20
+ message: `Select a simulator to run your app on`,
21
+ name: 'selectedSimulator',
22
+ choices: simulators.map(simulator => ({
23
+ title: `ios ${simulator.osVersion} ${simulator.name}`,
24
+ value: simulator,
25
+ })),
26
+ });
27
+ return selectedSimulator;
28
+ }
29
+ exports.selectSimulatorAsync = selectSimulatorAsync;
30
+ async function getFirstBootedIosSimulatorAsync() {
31
+ const bootedSimulators = await getAvaliableIosSimulatorsListAsync('booted');
32
+ if (bootedSimulators.length > 0) {
33
+ return bootedSimulators[0];
34
+ }
35
+ return undefined;
36
+ }
37
+ exports.getFirstBootedIosSimulatorAsync = getFirstBootedIosSimulatorAsync;
38
+ async function getAvaliableIosSimulatorsListAsync(query) {
39
+ const { stdout } = query
40
+ ? await (0, simctl_1.simctlAsync)(['list', 'devices', '--json', query])
41
+ : await (0, simctl_1.simctlAsync)(['list', 'devices', '--json']);
42
+ const info = parseSimControlJsonResults(stdout);
43
+ const iosSimulators = [];
44
+ for (const runtime of Object.keys(info.devices)) {
45
+ // Given a string like 'com.apple.CoreSimulator.SimRuntime.tvOS-13-4'
46
+ const runtimeSuffix = runtime.split('com.apple.CoreSimulator.SimRuntime.').pop();
47
+ if (!runtimeSuffix) {
48
+ continue;
49
+ }
50
+ // Create an array [tvOS, 13, 4]
51
+ const [osType, ...osVersionComponents] = runtimeSuffix.split('-');
52
+ if (osType === 'iOS') {
53
+ // Join the end components [13, 4] -> '13.4'
54
+ const osVersion = osVersionComponents.join('.');
55
+ const sims = info.devices[runtime];
56
+ for (const device of sims) {
57
+ if (device.isAvailable) {
58
+ iosSimulators.push({
59
+ ...device,
60
+ runtime,
61
+ osVersion,
62
+ windowName: `${device.name} (${osVersion})`,
63
+ osType: 'iOS',
64
+ state: device.state,
65
+ lastBootedAt: device.lastBootedAt ? new Date(device.lastBootedAt) : undefined,
66
+ });
67
+ }
68
+ }
69
+ }
70
+ }
71
+ return iosSimulators;
72
+ }
73
+ exports.getAvaliableIosSimulatorsListAsync = getAvaliableIosSimulatorsListAsync;
74
+ function parseSimControlJsonResults(input) {
75
+ try {
76
+ return JSON.parse(input);
77
+ }
78
+ catch (error) {
79
+ // Nov 15, 2020: Observed this can happen when opening the simulator and the simulator prompts the user to update the xcode command line tools.
80
+ // Unexpected token I in JSON at position 0
81
+ if (error.message.includes('Unexpected token')) {
82
+ log_1.default.error(`Apple's simctl returned malformed JSON:\n${input}`);
83
+ }
84
+ throw error;
85
+ }
86
+ }
87
+ async function ensureSimulatorBootedAsync(simulator) {
88
+ if (simulator.state === 'Booted') {
89
+ return;
90
+ }
91
+ await (0, simctl_1.simctlAsync)(['boot', simulator.udid]);
92
+ }
93
+ exports.ensureSimulatorBootedAsync = ensureSimulatorBootedAsync;
94
+ async function openSimulatorAppAsync(simulatorUdid) {
95
+ const args = ['-a', 'Simulator'];
96
+ if (simulatorUdid) {
97
+ // This has no effect if the app is already running.
98
+ args.push('--args', '-CurrentDeviceUDID', simulatorUdid);
99
+ }
100
+ await (0, spawn_async_1.default)('open', args);
101
+ }
102
+ exports.openSimulatorAppAsync = openSimulatorAppAsync;
103
+ async function launchAppAsync(simulatorUdid, bundleIdentifier) {
104
+ log_1.default.newLine();
105
+ log_1.default.log('Launching your app...');
106
+ await (0, simctl_1.simctlAsync)(['launch', simulatorUdid, bundleIdentifier]);
107
+ log_1.default.succeed('Successfully launched your app!');
108
+ }
109
+ exports.launchAppAsync = launchAppAsync;
110
+ // I think the app can be open while no simulators are booted.
111
+ async function waitForSimulatorAppToStartAsync(maxWaitTimeMs, intervalMs) {
112
+ log_1.default.newLine();
113
+ log_1.default.log('Waiting for Simulator app to start...');
114
+ const startTime = Date.now();
115
+ while (Date.now() - startTime < maxWaitTimeMs) {
116
+ if (await isSimulatorAppRunningAsync()) {
117
+ return;
118
+ }
119
+ await (0, promise_1.sleepAsync)(Math.min(intervalMs, Math.max(maxWaitTimeMs - (Date.now() - startTime), 0)));
120
+ }
121
+ throw new Error('Timed out waiting for the iOS simulator to start.');
122
+ }
123
+ async function isSimulatorAppRunningAsync() {
124
+ try {
125
+ const result = await osascript.execAsync('tell app "System Events" to count processes whose name is "Simulator"');
126
+ if (result.trim() === '0') {
127
+ return false;
128
+ }
129
+ }
130
+ catch (error) {
131
+ if (error.message.includes('Application isn’t running')) {
132
+ return false;
133
+ }
134
+ throw error;
135
+ }
136
+ return true;
137
+ }
138
+ async function ensureSimulatorAppOpenedAsync(simulatorUuid) {
139
+ if (await isSimulatorAppRunningAsync()) {
140
+ return;
141
+ }
142
+ await openSimulatorAppAsync(simulatorUuid);
143
+ await waitForSimulatorAppToStartAsync(60 * 1000, 1000);
144
+ }
145
+ exports.ensureSimulatorAppOpenedAsync = ensureSimulatorAppOpenedAsync;
146
+ async function installAppAsync(deviceId, filePath) {
147
+ log_1.default.newLine();
148
+ log_1.default.log('Installing your app on the simulator...');
149
+ await (0, simctl_1.simctlAsync)(['install', deviceId, filePath]);
150
+ log_1.default.succeed('Successfully installed your app on the simulator!');
151
+ }
152
+ exports.installAppAsync = installAppAsync;
153
+ async function getSimulatorAppIdAsync() {
154
+ try {
155
+ return (await osascript.execAsync('id of app "Simulator"')).trim();
156
+ }
157
+ catch {
158
+ return undefined;
159
+ }
160
+ }
161
+ exports.getSimulatorAppIdAsync = getSimulatorAppIdAsync;
@@ -0,0 +1 @@
1
+ export declare function validateSystemRequirementsAsync(): Promise<void>;
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.validateSystemRequirementsAsync = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const spawn_async_1 = tslib_1.__importDefault(require("@expo/spawn-async"));
6
+ const chalk_1 = tslib_1.__importDefault(require("chalk"));
7
+ const semver_1 = tslib_1.__importDefault(require("semver"));
8
+ const log_1 = tslib_1.__importDefault(require("../../log"));
9
+ const prompts_1 = require("../../prompts");
10
+ const simulator_1 = require("./simulator");
11
+ const xcode = tslib_1.__importStar(require("./xcode"));
12
+ const xcrun_1 = require("./xcrun");
13
+ function assertPlatform() {
14
+ if (process.platform !== 'darwin') {
15
+ log_1.default.error('iOS simulator apps can only be run on macOS devices.');
16
+ throw Error('iOS simulator apps can only be run on macOS devices.');
17
+ }
18
+ }
19
+ async function assertCorrectXcodeVersionInstalledAsync() {
20
+ const xcodeVersion = await xcode.getXcodeVersionAsync();
21
+ if (!xcodeVersion) {
22
+ const { goToAppStore } = await (0, prompts_1.promptAsync)({
23
+ type: 'select',
24
+ message: 'Xcode needs to be installed, would you like to continue to the App Store?',
25
+ name: 'goToAppStore',
26
+ choices: [
27
+ { title: 'Yes', value: true },
28
+ { title: 'No', value: false },
29
+ ],
30
+ });
31
+ if (goToAppStore) {
32
+ await xcode.openAppStoreAsync(xcode.APP_STORE_ID);
33
+ }
34
+ throw Error('Please try again once Xcode is installed');
35
+ }
36
+ if (semver_1.default.lt(xcodeVersion, xcode.MIN_XCODE_VERSION)) {
37
+ throw Error(`Xcode version ${chalk_1.default.bold(xcodeVersion)} is too old. Please upgrade to version ${chalk_1.default.bold(xcode.MIN_XCODE_VERSION)} or higher.`);
38
+ }
39
+ }
40
+ async function ensureXcrunInstalledAsync() {
41
+ if (!(0, xcrun_1.isXcrunInstalledAsync)()) {
42
+ const { installXcrun } = await (0, prompts_1.promptAsync)({
43
+ type: 'select',
44
+ message: 'Xcode Command Line Tools need to be installed, continue?',
45
+ name: 'installXcrun',
46
+ choices: [
47
+ { title: 'Yes', value: true },
48
+ { title: 'No', value: false },
49
+ ],
50
+ });
51
+ if (installXcrun) {
52
+ await (0, xcrun_1.installXcrunAsync)();
53
+ return;
54
+ }
55
+ throw Error('Please try again once Xcode Command Line Tools are installed');
56
+ }
57
+ }
58
+ async function assertSimulatorAppInstalledAsync() {
59
+ const simulatorAppId = await (0, simulator_1.getSimulatorAppIdAsync)();
60
+ if (!simulatorAppId) {
61
+ throw new Error(`Can't determine id of Simulator app; the Simulator is most likely not installed on this machine. Run 'sudo xcode-select -s /Applications/Xcode.app'`);
62
+ }
63
+ if (simulatorAppId !== 'com.apple.iphonesimulator' &&
64
+ simulatorAppId !== 'com.apple.CoreSimulator.SimulatorTrampoline') {
65
+ throw new Error(`Simulator is installed but is identified as '${simulatorAppId}', can't recognize what that is`);
66
+ }
67
+ try {
68
+ // make sure we can run simctl
69
+ await (0, spawn_async_1.default)('xcrun', ['simctl', 'help']);
70
+ }
71
+ catch (error) {
72
+ log_1.default.warn(`Unable to run simctl:\n${error.toString()}`);
73
+ throw new Error('xcrun is not configured correctly. Ensure `sudo xcode-select --reset` works before running this command again.');
74
+ }
75
+ }
76
+ async function validateSystemRequirementsAsync() {
77
+ assertPlatform();
78
+ await assertCorrectXcodeVersionInstalledAsync();
79
+ await ensureXcrunInstalledAsync();
80
+ await assertSimulatorAppInstalledAsync();
81
+ }
82
+ exports.validateSystemRequirementsAsync = validateSystemRequirementsAsync;
@@ -0,0 +1,4 @@
1
+ export declare const MIN_XCODE_VERSION = "9.4.0";
2
+ export declare const APP_STORE_ID = "497799835";
3
+ export declare function getXcodeVersionAsync(): Promise<string | undefined>;
4
+ export declare function openAppStoreAsync(appId: string): Promise<void>;
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.openAppStoreAsync = exports.getXcodeVersionAsync = exports.APP_STORE_ID = exports.MIN_XCODE_VERSION = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const spawn_async_1 = tslib_1.__importDefault(require("@expo/spawn-async"));
6
+ const chalk_1 = tslib_1.__importDefault(require("chalk"));
7
+ const semver_1 = tslib_1.__importDefault(require("semver"));
8
+ const log_1 = tslib_1.__importDefault(require("../../log"));
9
+ // Based on the RN docs (Aug 2020).
10
+ exports.MIN_XCODE_VERSION = '9.4.0';
11
+ exports.APP_STORE_ID = '497799835';
12
+ async function getXcodeVersionAsync() {
13
+ var _a;
14
+ try {
15
+ const { stdout } = await (0, spawn_async_1.default)('xcodebuild', ['-version']);
16
+ const version = (_a = stdout.match(/Xcode (\d+\.\d+)/)) === null || _a === void 0 ? void 0 : _a[1];
17
+ const semverFormattedVersion = `${version}.0`;
18
+ if (!semver_1.default.valid(semverFormattedVersion)) {
19
+ log_1.default.warn(`Xcode version ${chalk_1.default.bold(version)} is in unknown format. Expected format is ${chalk_1.default.bold('12.0')}.`);
20
+ return undefined;
21
+ }
22
+ return semverFormattedVersion;
23
+ }
24
+ catch {
25
+ // not installed
26
+ return undefined;
27
+ }
28
+ }
29
+ exports.getXcodeVersionAsync = getXcodeVersionAsync;
30
+ async function openAppStoreAsync(appId) {
31
+ const link = getAppStoreLink(appId);
32
+ await (0, spawn_async_1.default)(`open`, [link]);
33
+ }
34
+ exports.openAppStoreAsync = openAppStoreAsync;
35
+ function getAppStoreLink(appId) {
36
+ if (process.platform === 'darwin') {
37
+ // TODO: Is there ever a case where the macappstore isn't available on mac?
38
+ return `macappstore://itunes.apple.com/app/id${appId}`;
39
+ }
40
+ return `https://apps.apple.com/us/app/id${appId}`;
41
+ }
@@ -0,0 +1,4 @@
1
+ import { SpawnOptions, SpawnResult } from '@expo/spawn-async';
2
+ export declare function xcrunAsync(args: string[], options?: SpawnOptions): Promise<SpawnResult>;
3
+ export declare function isXcrunInstalledAsync(): Promise<boolean>;
4
+ export declare function installXcrunAsync(): Promise<void>;
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.installXcrunAsync = exports.isXcrunInstalledAsync = exports.xcrunAsync = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const spawn_async_1 = tslib_1.__importDefault(require("@expo/spawn-async"));
6
+ const chalk_1 = tslib_1.__importDefault(require("chalk"));
7
+ const log_1 = tslib_1.__importDefault(require("../../log"));
8
+ const promise_1 = require("../../utils/promise");
9
+ async function xcrunAsync(args, options) {
10
+ try {
11
+ return await (0, spawn_async_1.default)('xcrun', args, options);
12
+ }
13
+ catch (e) {
14
+ throwXcrunError(e);
15
+ }
16
+ }
17
+ exports.xcrunAsync = xcrunAsync;
18
+ function throwXcrunError(e) {
19
+ var _a;
20
+ if (isLicenseOutOfDate(e.stdout) || isLicenseOutOfDate(e.stderr)) {
21
+ throw new Error('Xcode license is not accepted. Please run `sudo xcodebuild -license`.');
22
+ }
23
+ else if ((_a = e.stderr) === null || _a === void 0 ? void 0 : _a.includes('not a developer tool or in PATH')) {
24
+ throw new Error(`You may need to run ${chalk_1.default.bold('sudo xcode-select -s /Applications/Xcode.app')} and try again.`);
25
+ }
26
+ if (Array.isArray(e.output)) {
27
+ e.message += '\n' + e.output.join('\n').trim();
28
+ }
29
+ else if (e.stderr) {
30
+ e.message += '\n' + e.stderr;
31
+ }
32
+ throw new Error(`Some other error occurred while running xcrun command.
33
+ ${e.message}`);
34
+ }
35
+ function isLicenseOutOfDate(text) {
36
+ if (!text) {
37
+ return false;
38
+ }
39
+ const lower = text.toLowerCase();
40
+ return lower.includes('xcode') && lower.includes('license');
41
+ }
42
+ async function isXcrunInstalledAsync() {
43
+ try {
44
+ await (0, spawn_async_1.default)('xcrun', ['--version']);
45
+ return true;
46
+ }
47
+ catch {
48
+ return false;
49
+ }
50
+ }
51
+ exports.isXcrunInstalledAsync = isXcrunInstalledAsync;
52
+ async function installXcrunAsync() {
53
+ await (0, spawn_async_1.default)('xcode-select', ['--install']);
54
+ await waitForXcrunInstallToFinishAsync(60 * 1000, 1000);
55
+ }
56
+ exports.installXcrunAsync = installXcrunAsync;
57
+ async function waitForXcrunInstallToFinishAsync(maxWaitTimeMs, intervalMs) {
58
+ log_1.default.newLine();
59
+ log_1.default.log('Waiting for Xcode Command Line Tools install to finish...');
60
+ const startTime = Date.now();
61
+ while (Date.now() - startTime < maxWaitTimeMs) {
62
+ if (await isXcrunInstalledAsync()) {
63
+ return;
64
+ }
65
+ await (0, promise_1.sleepAsync)(Math.min(intervalMs, Math.max(maxWaitTimeMs - (Date.now() - startTime), 0)));
66
+ }
67
+ throw new Error('Timed out waiting for Xcode Command Line Tools install to finish');
68
+ }
@@ -0,0 +1,8 @@
1
+ import { AppPlatform } from '../graphql/generated';
2
+ export interface RunArchiveFlags {
3
+ latest?: boolean;
4
+ id?: string;
5
+ path?: string;
6
+ url?: string;
7
+ }
8
+ export declare function runAsync(simulatorBuildPath: string, selectedPlatform: AppPlatform): Promise<void>;
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runAsync = void 0;
4
+ const generated_1 = require("../graphql/generated");
5
+ const run_1 = require("./android/run");
6
+ const run_2 = require("./ios/run");
7
+ async function runAsync(simulatorBuildPath, selectedPlatform) {
8
+ if (selectedPlatform === generated_1.AppPlatform.Ios) {
9
+ await (0, run_2.runAppOnIosSimulatorAsync)(simulatorBuildPath);
10
+ }
11
+ else {
12
+ await (0, run_1.runAppOnAndroidEmulatorAsync)(simulatorBuildPath);
13
+ }
14
+ }
15
+ exports.runAsync = runAsync;
@@ -5,4 +5,4 @@ export interface ArchiveSourceSummaryFields {
5
5
  formattedBuild?: string;
6
6
  }
7
7
  export declare function formatArchiveSourceSummary({ source, build }: Archive): ArchiveSourceSummaryFields;
8
- export declare function printSummary<T>(summary: T, keyMap: Record<keyof T, string>): void;
8
+ export declare function printSummary<T extends object>(summary: T, keyMap: Record<keyof T, string>): void;
@@ -4,7 +4,6 @@ exports.selectUpdateGroupOnBranchAsync = exports.listAndRenderUpdateGroupsOnBran
4
4
  const tslib_1 = require("tslib");
5
5
  const assert_1 = tslib_1.__importDefault(require("assert"));
6
6
  const chalk_1 = tslib_1.__importDefault(require("chalk"));
7
- const cli_table3_1 = tslib_1.__importDefault(require("cli-table3"));
8
7
  const UpdateQuery_1 = require("../graphql/queries/UpdateQuery");
9
8
  const log_1 = tslib_1.__importDefault(require("../log"));
10
9
  const formatFields_1 = tslib_1.__importDefault(require("../utils/formatFields"));
@@ -21,7 +20,7 @@ async function listAndRenderUpdateGroupsOnAppAsync(graphqlClient, { projectId, p
21
20
  offset: paginatedQueryOptions.offset,
22
21
  appId: projectId,
23
22
  });
24
- renderUpdateGroupsOnAppAsTable(updateGroups, paginatedQueryOptions);
23
+ renderUpdateGroupsOnApp({ updateGroups, paginatedQueryOptions });
25
24
  }
26
25
  else {
27
26
  await (0, queries_1.paginatedQueryWithConfirmPromptAsync)({
@@ -30,7 +29,7 @@ async function listAndRenderUpdateGroupsOnAppAsync(graphqlClient, { projectId, p
30
29
  queryToPerform: (limit, offset) => queryUpdateGroupsOnAppAsync(graphqlClient, { limit, offset, appId: projectId }),
31
30
  promptOptions: {
32
31
  title: 'Load more update groups?',
33
- renderListItems: updateGroups => renderUpdateGroupsOnAppAsTable(updateGroups, paginatedQueryOptions),
32
+ renderListItems: updateGroups => renderUpdateGroupsOnApp({ updateGroups, paginatedQueryOptions }),
34
33
  },
35
34
  });
36
35
  }
@@ -45,7 +44,7 @@ async function listAndRenderUpdateGroupsOnBranchAsync(graphqlClient, { projectId
45
44
  appId: projectId,
46
45
  branchName,
47
46
  });
48
- renderUpdateGroupsOnBranchAsTable({ updateGroups, branchName, paginatedQueryOptions });
47
+ renderUpdateGroupsOnBranch({ updateGroups, branchName, paginatedQueryOptions });
49
48
  }
50
49
  else {
51
50
  await (0, queries_1.paginatedQueryWithConfirmPromptAsync)({
@@ -59,7 +58,7 @@ async function listAndRenderUpdateGroupsOnBranchAsync(graphqlClient, { projectId
59
58
  }),
60
59
  promptOptions: {
61
60
  title: 'Load more update groups?',
62
- renderListItems: updateGroups => renderUpdateGroupsOnBranchAsTable({ updateGroups, branchName, paginatedQueryOptions }),
61
+ renderListItems: updateGroups => renderUpdateGroupsOnBranch({ updateGroups, branchName, paginatedQueryOptions }),
63
62
  },
64
63
  });
65
64
  }
@@ -97,52 +96,44 @@ async function queryUpdateGroupsOnBranchAsync(graphqlClient, args) {
97
96
  async function queryUpdateGroupsOnAppAsync(graphqlClient, args) {
98
97
  return await UpdateQuery_1.UpdateQuery.viewUpdateGroupsOnAppAsync(graphqlClient, args);
99
98
  }
100
- function renderUpdateGroupsOnBranchAsTable({ updateGroups, branchName, paginatedQueryOptions: { json }, }) {
99
+ function renderUpdateGroupsOnBranch({ branchName, updateGroups, paginatedQueryOptions: { json }, }) {
101
100
  var _a, _b;
101
+ // Ensure all updates are from the same branch
102
102
  const branchNames = updateGroups.flatMap(updateGroup => updateGroup.map(update => update.branch.name));
103
103
  (0, assert_1.default)(branchNames.every(name => name === branchName), 'Each update must belong to the same branch.');
104
+ const updateGroupDescriptions = (0, utils_1.getUpdateGroupDescriptionsWithBranch)(updateGroups);
104
105
  const branch = {
105
106
  name: branchName,
106
107
  id: (_b = (_a = updateGroups[0]) === null || _a === void 0 ? void 0 : _a[0].branch.id) !== null && _b !== void 0 ? _b : 'N/A',
107
108
  };
108
- const updateGroupDescriptions = (0, utils_1.getUpdateGroupDescriptions)(updateGroups);
109
109
  if (json) {
110
- (0, json_1.printJsonOnlyOutput)({ ...branch, currentPage: updateGroupDescriptions });
111
- }
112
- else {
113
- const updateGroupsTable = new cli_table3_1.default({
114
- head: utils_1.UPDATE_COLUMNS,
115
- wordWrap: true,
116
- });
117
- updateGroupDescriptions.forEach(({ message, runtimeVersion, group, platforms }) => {
118
- updateGroupsTable.push([message, runtimeVersion, group, platforms]);
119
- });
120
- log_1.default.addNewLineIfNone();
121
- log_1.default.log(chalk_1.default.bold('Branch:'));
122
- log_1.default.log((0, formatFields_1.default)([
123
- { label: 'Name', value: branch.name },
124
- { label: 'ID', value: branch.id },
125
- ]));
126
- log_1.default.addNewLineIfNone();
127
- log_1.default.log(updateGroupsTable.toString());
110
+ return (0, json_1.printJsonOnlyOutput)({ ...branch, currentPage: updateGroupDescriptions });
128
111
  }
112
+ log_1.default.addNewLineIfNone();
113
+ log_1.default.log(chalk_1.default.bold('Branch:'));
114
+ log_1.default.log((0, formatFields_1.default)([
115
+ { label: 'Name', value: branch.name },
116
+ { label: 'ID', value: branch.id },
117
+ ]));
118
+ log_1.default.newLine();
119
+ log_1.default.log(chalk_1.default.bold('Recent update groups:'));
120
+ log_1.default.newLine();
121
+ log_1.default.log(updateGroupDescriptions
122
+ .map(description => (0, utils_1.formatUpdateGroup)(description))
123
+ .join(`\n\n${chalk_1.default.dim('———')}\n\n`));
129
124
  }
130
- function renderUpdateGroupsOnAppAsTable(updateGroups, { json }) {
125
+ function renderUpdateGroupsOnApp({ updateGroups, paginatedQueryOptions: { json }, }) {
131
126
  const updateGroupDescriptions = (0, utils_1.getUpdateGroupDescriptionsWithBranch)(updateGroups);
132
127
  if (json) {
133
128
  (0, json_1.printJsonOnlyOutput)({ currentPage: updateGroupDescriptions });
134
129
  }
135
- else {
136
- const updateGroupsTable = new cli_table3_1.default({
137
- head: utils_1.UPDATE_COLUMNS_WITH_BRANCH,
138
- wordWrap: true,
139
- });
140
- updateGroupDescriptions.forEach(({ branch, message, runtimeVersion, group, platforms }) => {
141
- updateGroupsTable.push([branch, message, runtimeVersion, group, platforms]);
142
- });
143
- log_1.default.addNewLineIfNone();
144
- log_1.default.log(chalk_1.default.bold('Recent update groups:'));
145
- log_1.default.addNewLineIfNone();
146
- log_1.default.log(updateGroupsTable.toString());
147
- }
130
+ log_1.default.addNewLineIfNone();
131
+ log_1.default.log(chalk_1.default.bold('Recent update groups:'));
132
+ log_1.default.newLine();
133
+ log_1.default.log(updateGroupDescriptions
134
+ .map(({ branch, ...update }) => (0, utils_1.formatBranch)({
135
+ branch,
136
+ update,
137
+ }))
138
+ .join(`\n\n${chalk_1.default.dim('———')}\n\n`));
148
139
  }
@@ -1,5 +1,5 @@
1
1
  import { ExpoConfig } from '@expo/config';
2
- import { Maybe, Robot, Update, UpdateFragment, User } from '../graphql/generated';
2
+ import { Maybe, Robot, Update, UpdateBranchFragment, UpdateFragment, User } from '../graphql/generated';
3
3
  import { RequestedPlatform } from '../platform';
4
4
  import { ProfileData } from '../utils/profiles';
5
5
  export declare type FormatUpdateParameter = Pick<Update, 'id' | 'createdAt' | 'message'> & {
@@ -17,12 +17,18 @@ export declare type FormattedUpdateGroupDescription = {
17
17
  platforms: string;
18
18
  runtimeVersion: string;
19
19
  };
20
+ export declare type FormattedBranchDescription = {
21
+ branch: string;
22
+ branchRolloutPercentage?: number;
23
+ update?: FormattedUpdateGroupDescription;
24
+ };
20
25
  export declare type FormattedUpdateGroupDescriptionWithBranch = FormattedUpdateGroupDescription & {
21
26
  branch: string;
22
27
  };
23
28
  export declare const UPDATE_COLUMNS: string[];
24
29
  export declare const UPDATE_COLUMNS_WITH_BRANCH: string[];
25
30
  export declare function formatUpdateGroup(update: FormattedUpdateGroupDescription): string;
31
+ export declare function formatBranch({ branch, branchRolloutPercentage, update, }: FormattedBranchDescription): string;
26
32
  export declare function getPlatformsForGroup({ group, updates, }: {
27
33
  group: string | undefined;
28
34
  updates: {
@@ -40,5 +46,6 @@ export declare function ensureValidVersions(exp: ExpoConfig, platform: Requested
40
46
  export declare function formatUpdateTitle(update: UpdateFragment): string;
41
47
  export declare function getUpdateGroupDescriptions(updateGroups: UpdateFragment[][]): FormattedUpdateGroupDescription[];
42
48
  export declare function getUpdateGroupDescriptionsWithBranch(updateGroups: UpdateFragment[][]): FormattedUpdateGroupDescriptionWithBranch[];
49
+ export declare function getBranchDescription(branch: UpdateBranchFragment): FormattedBranchDescription;
43
50
  export declare function checkEASUpdateURLIsSetAsync(exp: ExpoConfig, projectId: string): Promise<boolean>;
44
51
  export declare function validateBuildProfileConfigMatchesProjectConfigAsync(exp: ExpoConfig, buildProfile: ProfileData<'build'>, projectId: string, nonInteractive: boolean): Promise<void>;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.validateBuildProfileConfigMatchesProjectConfigAsync = exports.checkEASUpdateURLIsSetAsync = exports.getUpdateGroupDescriptionsWithBranch = exports.getUpdateGroupDescriptions = exports.formatUpdateTitle = exports.ensureValidVersions = exports.formatUpdateMessage = exports.truncateString = exports.formatPlatformForUpdateGroup = exports.getPlatformsForGroup = exports.formatUpdateGroup = exports.UPDATE_COLUMNS_WITH_BRANCH = exports.UPDATE_COLUMNS = void 0;
3
+ exports.validateBuildProfileConfigMatchesProjectConfigAsync = exports.checkEASUpdateURLIsSetAsync = exports.getBranchDescription = exports.getUpdateGroupDescriptionsWithBranch = exports.getUpdateGroupDescriptions = exports.formatUpdateTitle = exports.ensureValidVersions = exports.formatUpdateMessage = exports.truncateString = exports.formatPlatformForUpdateGroup = exports.getPlatformsForGroup = exports.formatBranch = exports.formatUpdateGroup = exports.UPDATE_COLUMNS_WITH_BRANCH = exports.UPDATE_COLUMNS = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const timeago_js_1 = require("@expo/timeago.js");
6
6
  const chalk_1 = tslib_1.__importDefault(require("chalk"));
@@ -28,6 +28,21 @@ function formatUpdateGroup(update) {
28
28
  ]);
29
29
  }
30
30
  exports.formatUpdateGroup = formatUpdateGroup;
31
+ function formatBranch({ branch, branchRolloutPercentage, update, }) {
32
+ var _a, _b, _c, _d;
33
+ const rolloutField = branchRolloutPercentage
34
+ ? [{ label: 'Rollout', value: `${branchRolloutPercentage}%` }]
35
+ : [];
36
+ return (0, formatFields_1.default)([
37
+ { label: 'Branch', value: branch },
38
+ ...rolloutField,
39
+ { label: 'Platforms', value: (_a = update === null || update === void 0 ? void 0 : update.platforms) !== null && _a !== void 0 ? _a : 'N/A' },
40
+ { label: 'Runtime Version', value: (_b = update === null || update === void 0 ? void 0 : update.runtimeVersion) !== null && _b !== void 0 ? _b : 'N/A' },
41
+ { label: 'Message', value: (_c = update === null || update === void 0 ? void 0 : update.message) !== null && _c !== void 0 ? _c : 'N/A' },
42
+ { label: 'Group ID', value: (_d = update === null || update === void 0 ? void 0 : update.group) !== null && _d !== void 0 ? _d : 'N/A' },
43
+ ]);
44
+ }
45
+ exports.formatBranch = formatBranch;
31
46
  function getPlatformsForGroup({ group, updates = [], }) {
32
47
  const groupedUpdates = (0, groupBy_1.default)(updates, update => update.group);
33
48
  return formatPlatformForUpdateGroup(group ? groupedUpdates[group] : undefined);
@@ -110,6 +125,25 @@ function getUpdateGroupDescriptionsWithBranch(updateGroups) {
110
125
  }));
111
126
  }
112
127
  exports.getUpdateGroupDescriptionsWithBranch = getUpdateGroupDescriptionsWithBranch;
128
+ function getBranchDescription(branch) {
129
+ if (branch.updates.length === 0) {
130
+ return { branch: branch.name };
131
+ }
132
+ const latestUpdate = branch.updates[0];
133
+ return {
134
+ branch: branch.name,
135
+ update: {
136
+ message: formatUpdateMessage(latestUpdate),
137
+ runtimeVersion: latestUpdate.runtimeVersion,
138
+ group: latestUpdate.group,
139
+ platforms: getPlatformsForGroup({
140
+ group: latestUpdate.group,
141
+ updates: branch.updates,
142
+ }),
143
+ },
144
+ };
145
+ }
146
+ exports.getBranchDescription = getBranchDescription;
113
147
  async function checkEASUpdateURLIsSetAsync(exp, projectId) {
114
148
  var _a;
115
149
  const configuredURL = (_a = exp.updates) === null || _a === void 0 ? void 0 : _a.url;
@@ -0,0 +1,3 @@
1
+ import { BuildDistributionType } from '../build/types';
2
+ import { DistributionType } from '../graphql/generated';
3
+ export declare const buildDistributionTypeToGraphQLDistributionType: (buildDistribution?: BuildDistributionType) => DistributionType | undefined;
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildDistributionTypeToGraphQLDistributionType = void 0;
4
+ const types_1 = require("../build/types");
5
+ const generated_1 = require("../graphql/generated");
6
+ const buildDistributionTypeToGraphQLDistributionType = (buildDistribution) => {
7
+ if (buildDistribution === types_1.BuildDistributionType.STORE) {
8
+ return generated_1.DistributionType.Store;
9
+ }
10
+ else if (buildDistribution === types_1.BuildDistributionType.INTERNAL) {
11
+ return generated_1.DistributionType.Internal;
12
+ }
13
+ else if (buildDistribution === types_1.BuildDistributionType.SIMULATOR) {
14
+ return generated_1.DistributionType.Simulator;
15
+ }
16
+ else {
17
+ return undefined;
18
+ }
19
+ };
20
+ exports.buildDistributionTypeToGraphQLDistributionType = buildDistributionTypeToGraphQLDistributionType;
@@ -0,0 +1,2 @@
1
+ export declare function downloadAndExtractAppAsync(url: string, applicationExtension: string): Promise<string>;
2
+ export declare function extractAppFromLocalArchiveAsync(appArchivePath: string, applicationExtension: string): Promise<string>;