eas-cli 18.9.1 → 18.11.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 (72) hide show
  1. package/README.md +230 -95
  2. package/build/build/runBuildAndSubmit.d.ts +3 -1
  3. package/build/build/runBuildAndSubmit.js +12 -4
  4. package/build/build/utils/repository.js +15 -3
  5. package/build/build/validateLockfile.d.ts +1 -0
  6. package/build/build/validateLockfile.js +37 -0
  7. package/build/commandUtils/buildFlags.d.ts +1 -0
  8. package/build/commandUtils/buildFlags.js +18 -0
  9. package/build/commandUtils/convex.d.ts +12 -0
  10. package/build/commandUtils/convex.js +77 -0
  11. package/build/commands/build/dev.d.ts +1 -0
  12. package/build/commands/build/dev.js +12 -2
  13. package/build/commands/build/resign.js +0 -1
  14. package/build/commands/build/run.d.ts +1 -0
  15. package/build/commands/build/run.js +12 -3
  16. package/build/commands/integrations/convex/connect.d.ts +24 -0
  17. package/build/commands/integrations/convex/connect.js +266 -0
  18. package/build/commands/integrations/convex/dashboard.d.ts +9 -0
  19. package/build/commands/integrations/convex/dashboard.js +42 -0
  20. package/build/commands/integrations/convex/project/delete.d.ts +13 -0
  21. package/build/commands/integrations/convex/project/delete.js +65 -0
  22. package/build/commands/integrations/convex/project.d.ts +9 -0
  23. package/build/commands/integrations/convex/project.js +28 -0
  24. package/build/commands/integrations/convex/team/delete.d.ts +17 -0
  25. package/build/commands/integrations/convex/team/delete.js +93 -0
  26. package/build/commands/integrations/convex/team/invite.d.ts +19 -0
  27. package/build/commands/integrations/convex/team/invite.js +113 -0
  28. package/build/commands/integrations/convex/team.d.ts +9 -0
  29. package/build/commands/integrations/convex/team.js +35 -0
  30. package/build/commands/observe/events.js +12 -24
  31. package/build/commands/observe/logs.d.ts +29 -0
  32. package/build/commands/observe/logs.js +163 -0
  33. package/build/commands/observe/metrics.js +11 -19
  34. package/build/commands/observe/versions.js +11 -19
  35. package/build/commands/simulator/start.js +84 -5
  36. package/build/commands/simulator/stop.js +1 -1
  37. package/build/fingerprint/cli.js +1 -0
  38. package/build/graphql/generated.d.ts +421 -7
  39. package/build/graphql/generated.js +16 -3
  40. package/build/graphql/mutations/ConvexMutation.d.ts +10 -0
  41. package/build/graphql/mutations/ConvexMutation.js +89 -0
  42. package/build/graphql/mutations/DeviceRunSessionMutation.d.ts +2 -2
  43. package/build/graphql/mutations/DeviceRunSessionMutation.js +4 -4
  44. package/build/graphql/queries/ConvexQuery.d.ts +6 -0
  45. package/build/graphql/queries/ConvexQuery.js +49 -0
  46. package/build/graphql/queries/ObserveQuery.d.ts +21 -1
  47. package/build/graphql/queries/ObserveQuery.js +80 -0
  48. package/build/graphql/types/ConvexTeamConnection.d.ts +11 -0
  49. package/build/graphql/types/ConvexTeamConnection.js +43 -0
  50. package/build/graphql/types/Observe.d.ts +1 -0
  51. package/build/graphql/types/Observe.js +26 -1
  52. package/build/observe/fetchCustomEvents.d.ts +19 -0
  53. package/build/observe/fetchCustomEvents.js +21 -0
  54. package/build/observe/formatCustomEvents.d.ts +70 -0
  55. package/build/observe/formatCustomEvents.js +140 -0
  56. package/build/observe/formatEvents.js +5 -34
  57. package/build/observe/formatMetrics.js +2 -7
  58. package/build/observe/formatUtils.d.ts +27 -0
  59. package/build/observe/formatUtils.js +64 -0
  60. package/build/observe/formatVersions.js +2 -9
  61. package/build/observe/platforms.d.ts +21 -0
  62. package/build/observe/platforms.js +48 -0
  63. package/build/observe/resolveProjectContext.d.ts +22 -0
  64. package/build/observe/resolveProjectContext.js +21 -0
  65. package/build/run/ios/run.d.ts +2 -1
  66. package/build/run/ios/run.js +6 -2
  67. package/build/run/ios/simulator.d.ts +4 -1
  68. package/build/run/ios/simulator.js +14 -2
  69. package/build/run/run.d.ts +2 -1
  70. package/build/run/run.js +2 -2
  71. package/oclif.manifest.json +3984 -3243
  72. package/package.json +4 -4
@@ -7,6 +7,7 @@ import { DynamicConfigContextFn } from '../commandUtils/context/DynamicProjectCo
7
7
  import { ExpoGraphqlClient } from '../commandUtils/context/contextUtils/createGraphqlClient';
8
8
  import { BuildFragment } from '../graphql/generated';
9
9
  import { RequestedPlatform } from '../platform';
10
+ import { SimulatorRunTarget } from '../run/ios/run';
10
11
  import { Actor } from '../user/User';
11
12
  import { ProfileData } from '../utils/profiles';
12
13
  import { Client } from '../vcs/vcs';
@@ -26,6 +27,7 @@ export interface BuildFlags {
26
27
  freezeCredentials: boolean;
27
28
  isVerboseLoggingEnabled?: boolean;
28
29
  whatToTest?: string;
30
+ simulator?: SimulatorRunTarget;
29
31
  }
30
32
  export declare function runBuildAndSubmitAsync({ graphqlClient, analytics, vcsClient, projectDir, flags, actor, getDynamicPrivateProjectConfigAsync, downloadSimBuildAutoConfirm, envOverride, }: {
31
33
  graphqlClient: ExpoGraphqlClient;
@@ -41,4 +43,4 @@ export declare function runBuildAndSubmitAsync({ graphqlClient, analytics, vcsCl
41
43
  buildIds: string[];
42
44
  buildProfiles?: ProfileData<'build'>[];
43
45
  }>;
44
- export declare function downloadAndRunAsync(build: BuildFragment): Promise<void>;
46
+ export declare function downloadAndRunAsync(build: BuildFragment, simulator?: SimulatorRunTarget): Promise<void>;
@@ -17,6 +17,7 @@ const createContext_1 = require("./createContext");
17
17
  const evaluateConfigWithEnvVarsAsync_1 = require("./evaluateConfigWithEnvVarsAsync");
18
18
  const build_3 = require("./ios/build");
19
19
  const local_1 = require("./local");
20
+ const validateLockfile_1 = require("./validateLockfile");
20
21
  const devClient_1 = require("./utils/devClient");
21
22
  const printBuildInfo_1 = require("./utils/printBuildInfo");
22
23
  const repository_1 = require("./utils/repository");
@@ -46,6 +47,7 @@ const profiles_1 = require("../utils/profiles");
46
47
  const checkForOverages_1 = require("../utils/usage/checkForOverages");
47
48
  let metroConfigValidated = false;
48
49
  let sdkVersionChecked = false;
50
+ let lockfileChecked = false;
49
51
  let hasWarnedAboutUsageOverages = false;
50
52
  async function runBuildAndSubmitAsync({ graphqlClient, analytics, vcsClient, projectDir, flags, actor, getDynamicPrivateProjectConfigAsync, downloadSimBuildAutoConfirm, envOverride, }) {
51
53
  await vcsClient.ensureRepoExistsAsync();
@@ -245,6 +247,12 @@ async function prepareAndStartBuildAsync({ projectDir, flags, moreBuilds, buildP
245
247
  whatToTest: flags.whatToTest,
246
248
  env,
247
249
  });
250
+ if (!lockfileChecked && !flags.localBuildOptions.localBuildMode) {
251
+ if (!process.env.EAS_BUILD_SKIP_LOCKFILE_CHECK) {
252
+ await (0, validateLockfile_1.ensureLockfileExistsAsync)(projectDir);
253
+ }
254
+ lockfileChecked = true;
255
+ }
248
256
  if (!hasWarnedAboutUsageOverages && !flags.localBuildOptions.localBuildMode) {
249
257
  hasWarnedAboutUsageOverages = true;
250
258
  log_1.default.newLine();
@@ -358,17 +366,17 @@ function exitWithNonZeroCodeIfSomeBuildsFailed(maybeBuilds) {
358
366
  process.exit(1);
359
367
  }
360
368
  }
361
- async function downloadAndRunAsync(build) {
369
+ async function downloadAndRunAsync(build, simulator) {
362
370
  (0, assert_1.default)(build.artifacts?.applicationArchiveUrl);
363
371
  const cachedAppPath = (0, run_1.getEasBuildRunCachedAppPath)(build.project.id, build.id, build.platform);
364
372
  if (await (0, fs_extra_1.pathExists)(cachedAppPath)) {
365
373
  log_1.default.newLine();
366
374
  log_1.default.log(`Using cached app...`);
367
- await (0, run_1.runAsync)(cachedAppPath, build.platform);
375
+ await (0, run_1.runAsync)(cachedAppPath, build.platform, simulator);
368
376
  return;
369
377
  }
370
378
  const buildPath = await (0, download_1.downloadAndMaybeExtractAppAsync)(build.artifacts.applicationArchiveUrl, build.platform, cachedAppPath);
371
- await (0, run_1.runAsync)(buildPath, build.platform);
379
+ await (0, run_1.runAsync)(buildPath, build.platform, simulator);
372
380
  }
373
381
  async function maybeDownloadAndRunSimulatorBuildsAsync(builds, flags, autoConfirm) {
374
382
  const simBuilds = builds.filter(filter_1.truthy).filter(utils_1.isRunnableOnSimulatorOrEmulator);
@@ -381,7 +389,7 @@ async function maybeDownloadAndRunSimulatorBuildsAsync(builds, flags, autoConfir
381
389
  message: `Install and run the ${simBuild.platform === generated_1.AppPlatform.Android ? 'Android' : 'iOS'} build on ${simBuild.platform === generated_1.AppPlatform.Android ? 'an emulator' : 'a simulator'}?`,
382
390
  }));
383
391
  if (confirm) {
384
- await downloadAndRunAsync(simBuild);
392
+ await downloadAndRunAsync(simBuild, flags.simulator);
385
393
  }
386
394
  }
387
395
  }
@@ -108,9 +108,21 @@ async function makeProjectTarballAsync(vcsClient) {
108
108
  (0, timer_1.startTimer)(compressTimerLabel);
109
109
  try {
110
110
  await vcsClient.makeShallowCopyAsync(shallowClonePath);
111
- await tar.create({ cwd: shallowClonePath, file: tarPath, prefix: 'project', gzip: true }, [
112
- '.',
113
- ]);
111
+ await tar.create({
112
+ cwd: shallowClonePath,
113
+ file: tarPath,
114
+ prefix: 'project',
115
+ gzip: true,
116
+ portable: true,
117
+ onWriteEntry(entry) {
118
+ // Read-only directories may have files inside them. This causes trouble on tar extraction.
119
+ // Hence, we're forcing the owner write bit on directories in Windows
120
+ // to avoid this issue.
121
+ if (entry.type === 'Directory' && entry.stat) {
122
+ entry.stat.mode |= 0o200;
123
+ }
124
+ },
125
+ }, ['.']);
114
126
  }
115
127
  catch (err) {
116
128
  clearTimeout(timer);
@@ -0,0 +1 @@
1
+ export declare function ensureLockfileExistsAsync(projectDir: string): Promise<void>;
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ensureLockfileExistsAsync = ensureLockfileExistsAsync;
4
+ const tslib_1 = require("tslib");
5
+ const package_manager_1 = require("@expo/package-manager");
6
+ const fs_extra_1 = require("fs-extra");
7
+ const path_1 = tslib_1.__importDefault(require("path"));
8
+ const LOCKFILE_NAMES = [
9
+ package_manager_1.NPM_LOCK_FILE,
10
+ package_manager_1.YARN_LOCK_FILE,
11
+ package_manager_1.PNPM_LOCK_FILE,
12
+ package_manager_1.BUN_LOCK_FILE,
13
+ package_manager_1.BUN_TEXT_LOCK_FILE,
14
+ ];
15
+ async function hasLockfileAsync(dir) {
16
+ for (const lockfile of LOCKFILE_NAMES) {
17
+ if (await (0, fs_extra_1.pathExists)(path_1.default.join(dir, lockfile))) {
18
+ return true;
19
+ }
20
+ }
21
+ return false;
22
+ }
23
+ async function ensureLockfileExistsAsync(projectDir) {
24
+ if (await hasLockfileAsync(projectDir)) {
25
+ return;
26
+ }
27
+ const workspaceRoot = (0, package_manager_1.resolveWorkspaceRoot)(projectDir);
28
+ if (workspaceRoot && workspaceRoot !== projectDir) {
29
+ if (await hasLockfileAsync(workspaceRoot)) {
30
+ return;
31
+ }
32
+ }
33
+ throw new Error(`No lockfile found in the project directory.\n` +
34
+ `A lockfile is required to ensure deterministic dependency installation in EAS.\n` +
35
+ `Run your package manager's install command (e.g. "npm install") to generate one.\n` +
36
+ `To skip this check, run this command with EAS_BUILD_SKIP_LOCKFILE_CHECK=1.`);
37
+ }
@@ -0,0 +1 @@
1
+ export declare function preprocessBuildCommandArgs(argv: string[]): string[];
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.preprocessBuildCommandArgs = preprocessBuildCommandArgs;
4
+ function preprocessBuildCommandArgs(argv) {
5
+ return withOptionalSimulatorValue(argv);
6
+ }
7
+ // oclif does not support string flags with optional values. We want "--simulator"
8
+ // to prompt for a simulator, while still supporting "--simulator <name-or-udid>".
9
+ // Insert an empty string value for the bare flag before oclif parses argv.
10
+ function withOptionalSimulatorValue(argv) {
11
+ const simulatorFlagIndex = argv.indexOf('--simulator');
12
+ const simulatorValue = argv[simulatorFlagIndex + 1];
13
+ if (simulatorFlagIndex === -1 ||
14
+ (simulatorValue !== undefined && !simulatorValue.startsWith('-'))) {
15
+ return argv;
16
+ }
17
+ return [...argv.slice(0, simulatorFlagIndex + 1), '', ...argv.slice(simulatorFlagIndex + 1)];
18
+ }
@@ -0,0 +1,12 @@
1
+ import { ConvexProjectData, ConvexTeamConnectionData } from '../graphql/types/ConvexTeamConnection';
2
+ export declare function formatConvexInviteTimestamp(timestamp: string): string;
3
+ export declare function getConvexTeamDashboardUrl(connection: ConvexTeamConnectionData): string;
4
+ export declare function getConvexProjectDashboardUrl(project: ConvexProjectData): string;
5
+ export declare function formatConvexTeam(connection: ConvexTeamConnectionData): string;
6
+ export declare function formatConvexTeamConnection(connection: ConvexTeamConnectionData): string;
7
+ export declare function formatConvexProject(project: ConvexProjectData): string;
8
+ export declare function logNoConvexTeams(accountName: string): void;
9
+ export declare function logNoConvexProject(projectName: string): void;
10
+ export declare function confirmRecentConvexInviteAsync(connection: ConvexTeamConnectionData, { nonInteractive }: {
11
+ nonInteractive: boolean;
12
+ }): Promise<boolean>;
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.formatConvexInviteTimestamp = formatConvexInviteTimestamp;
4
+ exports.getConvexTeamDashboardUrl = getConvexTeamDashboardUrl;
5
+ exports.getConvexProjectDashboardUrl = getConvexProjectDashboardUrl;
6
+ exports.formatConvexTeam = formatConvexTeam;
7
+ exports.formatConvexTeamConnection = formatConvexTeamConnection;
8
+ exports.formatConvexProject = formatConvexProject;
9
+ exports.logNoConvexTeams = logNoConvexTeams;
10
+ exports.logNoConvexProject = logNoConvexProject;
11
+ exports.confirmRecentConvexInviteAsync = confirmRecentConvexInviteAsync;
12
+ const tslib_1 = require("tslib");
13
+ const chalk_1 = tslib_1.__importDefault(require("chalk"));
14
+ const dateformat_1 = tslib_1.__importDefault(require("dateformat"));
15
+ const log_1 = tslib_1.__importStar(require("../log"));
16
+ const prompts_1 = require("../prompts");
17
+ const CONVEX_DASHBOARD_HOST = 'https://dashboard.convex.dev';
18
+ const RECENT_INVITE_THRESHOLD_MS = 60 * 60 * 1000;
19
+ function formatConvexInviteTimestamp(timestamp) {
20
+ return (0, dateformat_1.default)(timestamp, 'mmm dd HH:MM:ss');
21
+ }
22
+ function getConvexTeamDashboardUrl(connection) {
23
+ return `${CONVEX_DASHBOARD_HOST}/t/${encodeURIComponent(connection.convexTeamSlug)}`;
24
+ }
25
+ function getConvexProjectDashboardUrl(project) {
26
+ return `${getConvexTeamDashboardUrl(project.convexTeamConnection)}/${encodeURIComponent(project.convexProjectSlug)}`;
27
+ }
28
+ function formatConvexTeam(connection) {
29
+ return `${connection.convexTeamName} / ${connection.convexTeamSlug}`;
30
+ }
31
+ function formatConvexTeamConnection(connection) {
32
+ const lines = [
33
+ `${chalk_1.default.bold('Team')}: ${formatConvexTeam(connection)}`,
34
+ `${chalk_1.default.bold('Dashboard')}: ${(0, log_1.link)(getConvexTeamDashboardUrl(connection), { dim: false })}`,
35
+ `${chalk_1.default.bold('Claimed')}: ${connection.hasBeenClaimed ? 'Yes' : 'No'}`,
36
+ ];
37
+ if (connection.invitedEmail) {
38
+ lines.push(`${chalk_1.default.bold('Invited email')}: ${connection.invitedEmail}`);
39
+ }
40
+ if (connection.invitedAt) {
41
+ lines.push(`${chalk_1.default.bold('Invited at')}: ${formatConvexInviteTimestamp(connection.invitedAt)}`);
42
+ }
43
+ return lines.join('\n');
44
+ }
45
+ function formatConvexProject(project) {
46
+ return [
47
+ `${chalk_1.default.bold('Name')}: ${project.convexProjectName}`,
48
+ `${chalk_1.default.bold('Slug')}: ${project.convexProjectSlug}`,
49
+ `${chalk_1.default.bold('Identifier')}: ${project.convexProjectIdentifier}`,
50
+ `${chalk_1.default.bold('Team')}: ${formatConvexTeam(project.convexTeamConnection)}`,
51
+ `${chalk_1.default.bold('Dashboard')}: ${(0, log_1.link)(getConvexProjectDashboardUrl(project), { dim: false })}`,
52
+ ].join('\n');
53
+ }
54
+ function logNoConvexTeams(accountName) {
55
+ log_1.default.warn(`No Convex team is linked to account ${chalk_1.default.bold(accountName)} on EAS.`);
56
+ }
57
+ function logNoConvexProject(projectName) {
58
+ log_1.default.warn(`No Convex project is linked to Expo app ${chalk_1.default.bold(projectName)} on EAS.`);
59
+ }
60
+ async function confirmRecentConvexInviteAsync(connection, { nonInteractive }) {
61
+ const invitedAt = connection.invitedAt ? new Date(connection.invitedAt) : null;
62
+ if (!invitedAt || Number.isNaN(invitedAt.getTime())) {
63
+ return true;
64
+ }
65
+ const timeSinceInviteMs = Date.now() - invitedAt.getTime();
66
+ if (timeSinceInviteMs >= RECENT_INVITE_THRESHOLD_MS) {
67
+ return true;
68
+ }
69
+ const previousInvite = `A Convex team invite was already sent${connection.invitedEmail ? ` to ${connection.invitedEmail}` : ''} at ${formatConvexInviteTimestamp(connection.invitedAt)}.`;
70
+ if (nonInteractive) {
71
+ log_1.default.warn(`${previousInvite} Sending another invite because this command is running in non-interactive mode.`);
72
+ return true;
73
+ }
74
+ return await (0, prompts_1.confirmAsync)({
75
+ message: `${previousInvite} Are you sure you want to send another invite?`,
76
+ });
77
+ }
@@ -8,6 +8,7 @@ export default class BuildDev extends EasCommand {
8
8
  profile: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
9
9
  'skip-build-if-not-found': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
10
10
  'skip-bundler': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
11
+ simulator: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
11
12
  };
12
13
  static contextDefinition: {
13
14
  projectId: import("../../commandUtils/context/ProjectIdContextField").ProjectIdContextField;
@@ -10,6 +10,7 @@ const evaluateConfigWithEnvVarsAsync_1 = require("../../build/evaluateConfigWith
10
10
  const runBuildAndSubmit_1 = require("../../build/runBuildAndSubmit");
11
11
  const repository_1 = require("../../build/utils/repository");
12
12
  const EasCommand_1 = tslib_1.__importDefault(require("../../commandUtils/EasCommand"));
13
+ const buildFlags_1 = require("../../commandUtils/buildFlags");
13
14
  const cli_1 = require("../../fingerprint/cli");
14
15
  const generated_1 = require("../../graphql/generated");
15
16
  const BuildQuery_1 = require("../../graphql/queries/BuildQuery");
@@ -42,6 +43,10 @@ class BuildDev extends EasCommand_1.default {
42
43
  description: 'Install and run the development build without starting the bundler server.',
43
44
  default: false,
44
45
  }),
46
+ simulator: core_1.Flags.string({
47
+ description: 'iOS simulator name or UDID to install and run the development build on. If no value is provided, you will be prompted to select a simulator.',
48
+ multiple: false,
49
+ }),
45
50
  };
46
51
  static contextDefinition = {
47
52
  ...this.ContextOptions.LoggedIn,
@@ -52,7 +57,7 @@ class BuildDev extends EasCommand_1.default {
52
57
  ...this.ContextOptions.ProjectId,
53
58
  };
54
59
  async runAsync() {
55
- const { flags } = await this.parse(BuildDev);
60
+ const { flags } = await this.parse(BuildDev, (0, buildFlags_1.preprocessBuildCommandArgs)(this.argv));
56
61
  const { loggedIn: { actor, graphqlClient }, getDynamicPrivateProjectConfigAsync, projectDir, analytics, vcsClient, projectId, } = await this.getContextAsync(BuildDev, {
57
62
  nonInteractive: false,
58
63
  withServerSideEnvironment: null,
@@ -61,6 +66,10 @@ class BuildDev extends EasCommand_1.default {
61
66
  if (process.platform !== 'darwin' && platform === eas_build_job_1.Platform.IOS) {
62
67
  core_1.Errors.error('Running iOS builds in simulator is only supported on macOS.', { exit: 1 });
63
68
  }
69
+ if (flags.simulator && platform !== eas_build_job_1.Platform.IOS) {
70
+ core_1.Errors.error('The --simulator flag can only be used with --platform ios.', { exit: 1 });
71
+ }
72
+ const simulator = flags.simulator === '' ? true : flags.simulator;
64
73
  await vcsClient.ensureRepoExistsAsync();
65
74
  await (0, repository_1.ensureRepoIsCleanAsync)(vcsClient, flags.nonInteractive);
66
75
  await (0, configure_1.ensureProjectConfiguredAsync)({
@@ -103,7 +112,7 @@ class BuildDev extends EasCommand_1.default {
103
112
  const build = builds[0];
104
113
  log_1.default.succeed(`🎯 Found successful build with matching fingerprint on EAS servers. Running it...`);
105
114
  if (build.artifacts?.applicationArchiveUrl) {
106
- await (0, runBuildAndSubmit_1.downloadAndRunAsync)(build);
115
+ await (0, runBuildAndSubmit_1.downloadAndRunAsync)(build, simulator);
107
116
  if (!flags['skip-bundler']) {
108
117
  await this.startDevServerAsync({ projectDir, platform });
109
118
  }
@@ -143,6 +152,7 @@ class BuildDev extends EasCommand_1.default {
143
152
  autoSubmit: false,
144
153
  localBuildOptions: {},
145
154
  profile: flags.profile ?? DEFAULT_EAS_BUILD_RUN_PROFILE_NAME,
155
+ simulator,
146
156
  },
147
157
  actor,
148
158
  getDynamicPrivateProjectConfigAsync,
@@ -143,7 +143,6 @@ class BuildResign extends EasCommand_1.default {
143
143
  },
144
144
  },
145
145
  secrets: (0, prepareJob_1.prepareCredentialsToResign)(credentialsResult.credentials),
146
- builderEnvironment: { image: 'default' },
147
146
  };
148
147
  const newBuild = await BuildMutation_1.BuildMutation.retryIosBuildAsync(graphqlClient, {
149
148
  buildId: build.id,
@@ -10,6 +10,7 @@ export default class Run extends EasCommand {
10
10
  id: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
11
11
  platform: import("@oclif/core/lib/interfaces").OptionFlag<"android" | "ios" | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
12
12
  profile: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
13
+ simulator: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
13
14
  };
14
15
  static contextDefinition: {
15
16
  vcsClient: import("../../commandUtils/context/VcsClientContextField").default;
@@ -6,6 +6,7 @@ const assert_1 = tslib_1.__importDefault(require("assert"));
6
6
  const fs_extra_1 = require("fs-extra");
7
7
  const queries_1 = require("../../build/queries");
8
8
  const EasCommand_1 = tslib_1.__importDefault(require("../../commandUtils/EasCommand"));
9
+ const buildFlags_1 = require("../../commandUtils/buildFlags");
9
10
  const pagination_1 = require("../../commandUtils/pagination");
10
11
  const generated_1 = require("../../graphql/generated");
11
12
  const BuildQuery_1 = require("../../graphql/queries/BuildQuery");
@@ -44,6 +45,10 @@ class Run extends EasCommand_1.default {
44
45
  description: 'Name of the build profile used to create the build to run. When specified, only builds created with the specified build profile will be queried.',
45
46
  helpValue: 'PROFILE_NAME',
46
47
  }),
48
+ simulator: core_1.Flags.string({
49
+ description: 'iOS simulator name or UDID to install and run the build on. If no value is provided, you will be prompted to select a simulator.',
50
+ multiple: false,
51
+ }),
47
52
  ...pagination_1.EasPaginatedQueryFlags,
48
53
  };
49
54
  static contextDefinition = {
@@ -52,23 +57,26 @@ class Run extends EasCommand_1.default {
52
57
  ...this.ContextOptions.Vcs,
53
58
  };
54
59
  async runAsync() {
55
- const { flags: rawFlags } = await this.parse(Run);
60
+ const { flags: rawFlags } = await this.parse(Run, (0, buildFlags_1.preprocessBuildCommandArgs)(this.argv));
56
61
  const flags = await this.sanitizeFlagsAsync(rawFlags);
57
62
  const queryOptions = (0, pagination_1.getPaginatedQueryOptions)(flags);
58
63
  const { loggedIn: { graphqlClient }, projectId, } = await this.getContextAsync(Run, {
59
64
  nonInteractive: false,
60
65
  });
61
66
  const simulatorBuildPath = await getPathToSimulatorBuildAppAsync(graphqlClient, projectId, flags, queryOptions);
62
- await (0, run_1.runAsync)(simulatorBuildPath, flags.selectedPlatform);
67
+ await (0, run_1.runAsync)(simulatorBuildPath, flags.selectedPlatform, flags.simulator);
63
68
  }
64
69
  async sanitizeFlagsAsync(flags) {
65
- const { platform, limit, offset, profile, ...runArchiveFlags } = flags;
70
+ const { platform, limit, offset, profile, simulator, ...runArchiveFlags } = flags;
66
71
  const selectedPlatform = await resolvePlatformAsync(platform);
67
72
  if (platform === 'ios' && process.platform !== 'darwin') {
68
73
  core_1.Errors.error('You can only use an iOS simulator to run apps on macOS devices', {
69
74
  exit: 1,
70
75
  });
71
76
  }
77
+ if (simulator && selectedPlatform !== generated_1.AppPlatform.Ios) {
78
+ core_1.Errors.error('The --simulator flag can only be used with --platform ios.', { exit: 1 });
79
+ }
72
80
  if (runArchiveFlags.path &&
73
81
  !((runArchiveFlags.path.endsWith('.tar.gz') ||
74
82
  runArchiveFlags.path.endsWith('.app') ||
@@ -87,6 +95,7 @@ class Run extends EasCommand_1.default {
87
95
  limit,
88
96
  offset,
89
97
  profile,
98
+ simulator: simulator === '' ? true : simulator,
90
99
  };
91
100
  }
92
101
  }
@@ -0,0 +1,24 @@
1
+ import EasCommand from '../../../commandUtils/EasCommand';
2
+ export default class IntegrationsConvexConnect extends EasCommand {
3
+ static description: string;
4
+ static contextDefinition: {
5
+ loggedIn: import("../../../commandUtils/context/LoggedInContextField").default;
6
+ privateProjectConfig: import("../../../commandUtils/context/PrivateProjectConfigContextField").PrivateProjectConfigContextField;
7
+ };
8
+ static flags: {
9
+ region: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
10
+ 'team-name': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
11
+ 'project-name': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
12
+ 'non-interactive': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
13
+ };
14
+ runAsync(): Promise<void>;
15
+ private resolveRegionAsync;
16
+ private resolveTeamNameAsync;
17
+ private resolveProjectNameAsync;
18
+ private selectConnectionAsync;
19
+ private getActorEmail;
20
+ private sendTeamInviteAsync;
21
+ private installConvexPackageAsync;
22
+ private writeEnvLocalAsync;
23
+ private mergeEnvContent;
24
+ }