eas-cli 1.0.0 → 1.1.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 (43) hide show
  1. package/README.md +50 -47
  2. package/build/build/android/build.js +1 -1
  3. package/build/build/build.js +4 -4
  4. package/build/build/utils/printBuildInfo.js +2 -2
  5. package/build/build/utils/repository.js +4 -4
  6. package/build/commands/branch/create.js +1 -1
  7. package/build/commands/branch/delete.js +1 -1
  8. package/build/commands/branch/rename.js +2 -2
  9. package/build/commands/channel/create.js +1 -1
  10. package/build/commands/channel/delete.js +1 -1
  11. package/build/commands/channel/edit.js +3 -3
  12. package/build/commands/channel/rollout.js +3 -3
  13. package/build/commands/channel/view.js +1 -1
  14. package/build/commands/credentials.d.ts +3 -0
  15. package/build/commands/credentials.js +6 -1
  16. package/build/commands/project/init.js +3 -1
  17. package/build/commands/secret/list.js +1 -1
  18. package/build/commands/update/index.js +4 -4
  19. package/build/commands/update/list.js +1 -1
  20. package/build/credentials/android/actions/RemoveKeystore.js +1 -1
  21. package/build/credentials/errors.js +1 -1
  22. package/build/credentials/ios/actions/DistributionCertificateUtils.js +2 -2
  23. package/build/credentials/ios/actions/SetUpAdhocProvisioningProfile.js +1 -1
  24. package/build/credentials/ios/actions/SetUpInternalProvisioningProfile.js +2 -2
  25. package/build/credentials/ios/actions/SetUpProvisioningProfile.js +1 -1
  26. package/build/credentials/ios/actions/SetUpSubmissionCredentials.js +1 -1
  27. package/build/credentials/ios/appstore/contractMessages.js +1 -1
  28. package/build/credentials/ios/appstore/ensureAppExists.js +3 -3
  29. package/build/credentials/ios/appstore/pushKey.js +2 -2
  30. package/build/credentials/manager/SelectIosDistributionTypeGraphqlFromBuildProfile.js +1 -1
  31. package/build/credentials/manager/SelectPlatform.d.ts +2 -0
  32. package/build/credentials/manager/SelectPlatform.js +7 -12
  33. package/build/credentials/utils/promptForCredentials.js +1 -1
  34. package/build/devices/manager.js +1 -1
  35. package/build/graphql/client.js +1 -1
  36. package/build/metadata/errors.js +2 -2
  37. package/build/project/metroConfig.js +1 -1
  38. package/build/project/projectUtils.d.ts +16 -2
  39. package/build/project/projectUtils.js +39 -22
  40. package/build/submit/utils/errors.js +9 -9
  41. package/build/update/utils.js +1 -1
  42. package/oclif.manifest.json +1 -1
  43. package/package.json +2 -5
@@ -1,12 +1,17 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const tslib_1 = require("tslib");
4
+ const core_1 = require("@oclif/core");
4
5
  const EasCommand_1 = tslib_1.__importDefault(require("../commandUtils/EasCommand"));
5
6
  const SelectPlatform_1 = require("../credentials/manager/SelectPlatform");
6
7
  class Credentials extends EasCommand_1.default {
7
8
  async runAsync() {
8
- await new SelectPlatform_1.SelectPlatform().runAsync();
9
+ const { flags } = await this.parse(Credentials);
10
+ await new SelectPlatform_1.SelectPlatform(flags.platform).runAsync();
9
11
  }
10
12
  }
11
13
  exports.default = Credentials;
12
14
  Credentials.description = 'manage credentials';
15
+ Credentials.flags = {
16
+ platform: core_1.Flags.enum({ char: 'p', options: ['android', 'ios'] }),
17
+ };
@@ -15,7 +15,9 @@ class ProjectInit extends EasCommand_1.default {
15
15
  log_1.default.error(`app.json is already linked to project with ID: ${chalk_1.default.bold((_d = (_c = exp.extra) === null || _c === void 0 ? void 0 : _c.eas) === null || _d === void 0 ? void 0 : _d.projectId)}`);
16
16
  return;
17
17
  }
18
- await (0, projectUtils_1.setProjectIdAsync)(projectDir);
18
+ const projectId = await (0, projectUtils_1.fetchProjectIdFromServerAsync)(exp);
19
+ await (0, projectUtils_1.saveProjectIdToAppConfigAsync)(projectDir, projectId);
20
+ log_1.default.withTick(`Linked app.json to project with ID ${chalk_1.default.bold(projectId)}`);
19
21
  }
20
22
  }
21
23
  exports.default = ProjectInit;
@@ -16,7 +16,7 @@ class EnvironmentSecretList extends EasCommand_1.default {
16
16
  const projectId = await (0, projectUtils_1.getProjectIdAsync)(exp);
17
17
  const projectAccountName = await (0, projectUtils_1.getProjectAccountNameAsync)(exp);
18
18
  if (!projectDir) {
19
- throw new Error("Please run this command inside your project's directory");
19
+ throw new Error("Run this command inside your project's directory");
20
20
  }
21
21
  const secrets = await EnvironmentSecretsQuery_1.EnvironmentSecretsQuery.allAsync(projectAccountName, projectId);
22
22
  const table = new cli_table3_1.default({
@@ -153,7 +153,7 @@ class UpdatePublish extends EasCommand_1.default {
153
153
  ({ name: branchName } = await (0, prompts_1.promptAsync)({
154
154
  type: 'text',
155
155
  name: 'name',
156
- message: 'No branches found. Creating a new one. Please name the new branch:',
156
+ message: 'No branches found. Provide a branch name:',
157
157
  initial: (await (0, vcs_1.getVcsClient)().getBranchNameAsync()) ||
158
158
  `branch-${Math.random().toString(36).substr(2, 4)}`,
159
159
  validate: value => (value ? true : validationMessage),
@@ -229,7 +229,7 @@ class UpdatePublish extends EasCommand_1.default {
229
229
  ({ publishMessage: message } = await (0, prompts_1.promptAsync)({
230
230
  type: 'text',
231
231
  name: 'publishMessage',
232
- message: `Please enter an update message.`,
232
+ message: `Provide an update message.`,
233
233
  initial: `Republish "${oldMessage}" - group: ${group}`,
234
234
  validate: (value) => (value ? true : validationMessage),
235
235
  }));
@@ -250,7 +250,7 @@ class UpdatePublish extends EasCommand_1.default {
250
250
  ({ publishMessage: message } = await (0, prompts_1.promptAsync)({
251
251
  type: 'text',
252
252
  name: 'publishMessage',
253
- message: `Please enter an update message.`,
253
+ message: `Provide an update message.`,
254
254
  initial: (_c = (await (0, vcs_1.getVcsClient)().getLastCommitMessageAsync())) === null || _c === void 0 ? void 0 : _c.trim(),
255
255
  validate: (value) => (value ? true : validationMessage),
256
256
  }));
@@ -529,7 +529,7 @@ async function checkEASUpdateURLIsSetAsync(exp) {
529
529
  const projectId = await (0, projectUtils_1.getProjectIdAsync)(exp);
530
530
  const expectedURL = (0, api_1.getEASUpdateURL)(projectId);
531
531
  if (configuredURL !== expectedURL) {
532
- throw new Error(`The update URL is incorrectly configured for EAS Update. Please set updates.url to ${expectedURL} in your app.json.`);
532
+ throw new Error(`The update URL is incorrectly configured for EAS Update. Set updates.url to ${expectedURL} in your ${chalk_1.default.bold('app.json')}.`);
533
533
  }
534
534
  }
535
535
  const truncatePublishUpdateMessage = (originalMessage) => {
@@ -47,7 +47,7 @@ class BranchView extends EasCommand_1.default {
47
47
  ({ name: branchInteractive } = await (0, prompts_1.promptAsync)({
48
48
  type: 'text',
49
49
  name: 'name',
50
- message: 'Please enter the name of the branch whose updates you wish to view:',
50
+ message: 'Provide the name of the branch whose updates you wish to view:',
51
51
  initial: (_a = (await (0, vcs_1.getVcsClient)().getBranchNameAsync())) !== null && _a !== void 0 ? _a : undefined,
52
52
  validate: (value) => (value ? true : validationMessage),
53
53
  }));
@@ -35,7 +35,7 @@ class RemoveKeystore {
35
35
  log_1.default.newLine();
36
36
  log_1.default.warn(`Clearing your Android build credentials from our build servers is a ${chalk_1.default.bold('PERMANENT and IRREVERSIBLE action.')}`);
37
37
  log_1.default.warn(chalk_1.default.bold('Android Keystore must be identical to the one previously used to submit your app to the Google Play Store.'));
38
- log_1.default.warn('Please read https://docs.expo.dev/distribution/building-standalone-apps/#if-you-choose-to-build-for-android for more info before proceeding.');
38
+ log_1.default.warn('Read https://docs.expo.dev/distribution/building-standalone-apps/#if-you-choose-to-build-for-android for more info before proceeding.');
39
39
  log_1.default.newLine();
40
40
  log_1.default.warn(chalk_1.default.bold('Your Keystore will be backed up to your current directory if you continue.'));
41
41
  log_1.default.newLine();
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.UnsupportedCredentialsChoiceError = exports.MissingCredentialsError = exports.MissingCredentialsNonInteractiveError = void 0;
4
4
  class MissingCredentialsNonInteractiveError extends Error {
5
5
  constructor(message) {
6
- super(message !== null && message !== void 0 ? message : 'Credentials are not set up. Please run this command again in interactive mode.');
6
+ super(message !== null && message !== void 0 ? message : 'Credentials are not set up. Run this command again in interactive mode.');
7
7
  }
8
8
  }
9
9
  exports.MissingCredentialsNonInteractiveError = MissingCredentialsNonInteractiveError;
@@ -96,8 +96,8 @@ async function selectValidDistributionCertificateAsync(ctx, appLookupParams) {
96
96
  exports.selectValidDistributionCertificateAsync = selectValidDistributionCertificateAsync;
97
97
  const APPLE_DIST_CERTS_TOO_MANY_GENERATED_ERROR = `
98
98
  You can have only ${chalk_1.default.underline('three')} Apple Distribution Certificates generated on your Apple Developer account.
99
- Please revoke the old ones or reuse existing from your other apps.
100
- Please remember that Apple Distribution Certificates are not application specific!
99
+ Revoke the old ones or reuse existing from your other apps.
100
+ Remember that Apple Distribution Certificates are not application specific!
101
101
  `;
102
102
  async function provideOrGenerateDistributionCertificateAsync(ctx) {
103
103
  if (!ctx.nonInteractive) {
@@ -34,7 +34,7 @@ class SetUpAdhocProvisioningProfile {
34
34
  return (0, nullthrows_1.default)(await (0, BuildCredentialsUtils_1.getBuildCredentialsAsync)(ctx, this.app, generated_1.IosDistributionType.AdHoc));
35
35
  }
36
36
  else {
37
- throw new errors_1.MissingCredentialsNonInteractiveError('Provisioning profile is not configured correctly. Please run this command again in interactive mode.');
37
+ throw new errors_1.MissingCredentialsNonInteractiveError('Provisioning profile is not configured correctly. Run this command again in interactive mode.');
38
38
  }
39
39
  }
40
40
  const currentBuildCredentials = await (0, BuildCredentialsUtils_1.getBuildCredentialsAsync)(ctx, this.app, generated_1.IosDistributionType.AdHoc);
@@ -59,7 +59,7 @@ class SetUpInternalProvisioningProfile {
59
59
  }
60
60
  else {
61
61
  if (adhocBuildCredentialsExist && enterpriseBuildCredentialsExist) {
62
- throw new Error(`You're in non-interactive mode. You have set up both adhoc and universal distribution credentials. Please set the 'enterpriseProvisioning' property (to 'adhoc' or 'universal') in eas.json to choose the credentials to use.`);
62
+ throw new Error(`You're in non-interactive mode. You have set up both adhoc and universal distribution credentials. Set the 'enterpriseProvisioning' property (to 'adhoc' or 'universal') in eas.json to choose the credentials to use.`);
63
63
  }
64
64
  else if (adhocBuildCredentialsExist) {
65
65
  return await this.setupAdhocProvisioningProfileAsync(ctx);
@@ -68,7 +68,7 @@ class SetUpInternalProvisioningProfile {
68
68
  return await this.setupUniversalProvisioningProfileAsync(ctx);
69
69
  }
70
70
  else {
71
- throw new Error(`You're in non-interactive mode. EAS CLI couldn't find any credentials suitable for internal distribution. Please run again in interactive mode.`);
71
+ throw new Error(`You're in non-interactive mode. EAS CLI couldn't find any credentials suitable for internal distribution. Run this command again in interactive mode.`);
72
72
  }
73
73
  }
74
74
  }
@@ -48,7 +48,7 @@ class SetUpProvisioningProfile {
48
48
  return (0, nullthrows_1.default)(await (0, BuildCredentialsUtils_1.getBuildCredentialsAsync)(ctx, this.app, this.distributionType));
49
49
  }
50
50
  if (ctx.nonInteractive) {
51
- throw new errors_1.MissingCredentialsNonInteractiveError('Provisioning profile is not configured correctly. Please run this command again in interactive mode.');
51
+ throw new errors_1.MissingCredentialsNonInteractiveError('Provisioning profile is not configured correctly. Run this command again in interactive mode.');
52
52
  }
53
53
  const currentProfile = await (0, BuildCredentialsUtils_1.getProvisioningProfileAsync)(ctx, this.app, this.distributionType);
54
54
  if (!currentProfile) {
@@ -38,7 +38,7 @@ class SetUpSubmissionCredentials {
38
38
  }
39
39
  async promptForAppSpecificPasswordAsync() {
40
40
  log_1.default.addNewLineIfNone();
41
- log_1.default.log(`Please enter your Apple app-specific password.`);
41
+ log_1.default.log(`Enter your Apple app-specific password.`);
42
42
  log_1.default.log((0, log_1.learnMore)('https://expo.fyi/apple-app-specific-password'));
43
43
  log_1.default.warn((0, wrap_ansi_1.default)(`This option will be deprecated soon. You will still be able to provide your password with the ${chalk_1.default.bold('EXPO_APPLE_APP_SPECIFIC_PASSWORD')} environment variable.`, process.stdout.columns || 80));
44
44
  const { appSpecificPassword } = await (0, prompts_1.promptAsync)({
@@ -59,7 +59,7 @@ async function getRequiredContractMessagesAsync(context) {
59
59
  // There is a small chance that this could result in a false positive if the messages are extraneous, so we'll also
60
60
  // prompt the user to open an issue so we can address the new contract state if it ever appears.
61
61
  // TODO: Maybe a silent analytic would be better
62
- log_1.default.error(`\nUnexpected Apple developer contract status "${status}". Please open an issue on https://github.com/expo/eas-cli`);
62
+ log_1.default.error(`\nUnexpected Apple developer contract status "${status}". Open an issue on https://github.com/expo/eas-cli`);
63
63
  log_1.default.newLine();
64
64
  return { messages: (_b = (await getContractMessagesAsync(context))) !== null && _b !== void 0 ? _b : [], isFatal: false };
65
65
  }
@@ -36,7 +36,7 @@ async function ensureBundleIdExistsWithNameAsync(authCtx, { name, bundleIdentifi
36
36
  }
37
37
  catch (err) {
38
38
  if (err.message.match(/An App ID with Identifier '(.*)' is not available/)) {
39
- spinner.fail(`The bundle identifier ${chalk_1.default.bold(bundleIdentifier)} is not available to team "${authCtx.team.name}" (${authCtx.team.id}), please change it in your app config and try again.`);
39
+ spinner.fail(`The bundle identifier ${chalk_1.default.bold(bundleIdentifier)} is not available to team "${authCtx.team.name}" (${authCtx.team.id}), change it in your app config and try again.`);
40
40
  }
41
41
  else {
42
42
  spinner.fail(`Failed to register bundle identifier ${chalk_1.default.dim(bundleIdentifier)}`);
@@ -123,11 +123,11 @@ async function ensureAppExistsAsync(userAuthCtx, { name, language, companyName,
123
123
  }
124
124
  catch (error) {
125
125
  if (error.message.match(/An App ID with Identifier '(.*)' is not available/)) {
126
- throw new Error(`\nThe bundle identifier "${bundleIdentifier}" is not available to provider "${(_a = userAuthCtx.authState) === null || _a === void 0 ? void 0 : _a.session.provider.name}. Please change it in your app config and try again.\n`);
126
+ throw new Error(`\nThe bundle identifier "${bundleIdentifier}" is not available to provider "${(_a = userAuthCtx.authState) === null || _a === void 0 ? void 0 : _a.session.provider.name}. Change it in your app config and try again.\n`);
127
127
  }
128
128
  spinner.fail(`Failed to create App Store app ${chalk_1.default.dim(name)}`);
129
129
  error.message +=
130
- '\nPlease visit https://appstoreconnect.apple.com and resolve any warnings, then try again.';
130
+ '\nVisit https://appstoreconnect.apple.com and resolve any warnings, then try again.';
131
131
  throw error;
132
132
  }
133
133
  }
@@ -11,8 +11,8 @@ const authenticate_1 = require("./authenticate");
11
11
  const { MaxKeysCreatedError } = apple_utils_1.Keys;
12
12
  exports.APPLE_KEYS_TOO_MANY_GENERATED_ERROR = `
13
13
  You can have only ${chalk_1.default.underline('two')} Apple Keys generated on your Apple Developer account.
14
- Please revoke the old ones or reuse existing from your other apps.
15
- Please remember that Apple Keys are not application specific!
14
+ Revoke the old ones or reuse existing from your other apps.
15
+ Remember that Apple Keys are not application specific!
16
16
  `;
17
17
  /**
18
18
  * List all existing push keys on Apple servers.
@@ -39,7 +39,7 @@ class SelectIosDistributionTypeGraphqlFromBuildProfile {
39
39
  return generated_1.IosDistributionType.AdHoc;
40
40
  }
41
41
  if (ctx.nonInteractive) {
42
- throw new Error('Unable to determine type of internal distribution. Please run this command in interactive mode.');
42
+ throw new Error('Unable to determine type of internal distribution. Run this command in interactive mode.');
43
43
  }
44
44
  // ask the user as a last resort
45
45
  const { iosDistributionTypeGraphql } = await (0, prompts_1.promptAsync)({
@@ -1,3 +1,5 @@
1
1
  export declare class SelectPlatform {
2
+ private readonly flagPlatform?;
3
+ constructor(flagPlatform?: string | undefined);
2
4
  runAsync(): Promise<void>;
3
5
  }
@@ -1,24 +1,19 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SelectPlatform = void 0;
4
- const prompts_1 = require("../../prompts");
4
+ const platform_1 = require("../../platform");
5
5
  const ManageAndroid_1 = require("./ManageAndroid");
6
6
  const ManageIos_1 = require("./ManageIos");
7
7
  class SelectPlatform {
8
+ constructor(flagPlatform) {
9
+ this.flagPlatform = flagPlatform;
10
+ }
8
11
  async runAsync() {
9
- const { platform } = await (0, prompts_1.promptAsync)({
10
- type: 'select',
11
- name: 'platform',
12
- message: 'Select platform',
13
- choices: [
14
- { value: 'android', title: 'Android' },
15
- { value: 'ios', title: 'iOS' },
16
- ],
17
- });
12
+ const platform = await (0, platform_1.selectPlatformAsync)(this.flagPlatform);
18
13
  if (platform === 'ios') {
19
- return await new ManageIos_1.ManageIos(new SelectPlatform(), process.cwd()).runAsync();
14
+ return await new ManageIos_1.ManageIos(new SelectPlatform(platform), process.cwd()).runAsync();
20
15
  }
21
- return await new ManageAndroid_1.ManageAndroid(new SelectPlatform(), process.cwd()).runAsync();
16
+ return await new ManageAndroid_1.ManageAndroid(new SelectPlatform(platform), process.cwd()).runAsync();
22
17
  }
23
18
  }
24
19
  exports.SelectPlatform = SelectPlatform;
@@ -14,7 +14,7 @@ const EXPERT_PROMPT = () => {
14
14
  }
15
15
  log_1.default.warn(`
16
16
  In this mode, we won't be able to make sure that your credentials are valid.
17
- Please double check that you're uploading valid files for your app otherwise you may encounter strange errors!
17
+ Double check that you're uploading valid files for your app otherwise you may encounter strange errors!
18
18
  When building for IOS make sure you've created your App ID on the Apple Developer Portal, that your App ID
19
19
  is in app.json as \`bundleIdentifier\`, and that the provisioning profile you
20
20
  upload matches that Team ID and App ID.
@@ -17,7 +17,7 @@ Internal distribution means that you won't need upload your app archive to App S
17
17
  Your app archive (.ipa) will be installable on your equipment as long as you sign your application with an adhoc provisiong profile.
18
18
  The provisioning profile needs to contain the UDIDs (unique identifiers) of your iPhones and iPads.
19
19
 
20
- First of all, please choose the Expo account under which you want to register your devices.
20
+ First of all, choose the Expo account under which you want to register your devices.
21
21
  Later, authenticate with Apple and choose your desired Apple Team (if your Apple ID has access to multiple teams).`;
22
22
  class DeviceManager {
23
23
  constructor(ctx) {
@@ -47,7 +47,7 @@ async function withErrorHandlingAsync(promise) {
47
47
  const { data, error } = await promise;
48
48
  if (error) {
49
49
  if (error.graphQLErrors.some(e => { var _a; return (_a = e === null || e === void 0 ? void 0 : e.extensions) === null || _a === void 0 ? void 0 : _a.isTransient; })) {
50
- log_1.default.error(`We've encountered a transient error, please try again shortly.`);
50
+ log_1.default.error(`We've encountered a transient error. Try again shortly.`);
51
51
  }
52
52
  throw error;
53
53
  }
@@ -75,8 +75,8 @@ function handleMetadataError(error) {
75
75
  log_1.default.error(error.errors.map(err => err.message).join('\n\n'));
76
76
  }
77
77
  log_1.default.newLine();
78
- log_1.default.log('Please check the logs for any configuration issues.');
79
- log_1.default.log('If this issue persists, please open a new issue at:');
78
+ log_1.default.log('Check the logs for any configuration issues.');
79
+ log_1.default.log('If this issue persists, open a new issue at:');
80
80
  // TODO: add execution ID to the issue template link
81
81
  log_1.default.log((0, log_1.link)('https://github.com/expo/eas-cli'));
82
82
  return;
@@ -42,7 +42,7 @@ function importMetroConfigFromProject(projectDir) {
42
42
  if (!resolvedPath) {
43
43
  throw new MetroConfigPackageMissingError('Missing package "metro-config" in the project. ' +
44
44
  'This usually means `react-native` is not installed. ' +
45
- 'Please verify that dependencies in package.json include "react-native" ' +
45
+ 'Verify that dependencies in package.json include "react-native" ' +
46
46
  'and run `yarn` or `npm install`.');
47
47
  }
48
48
  return require(resolvedPath);
@@ -8,9 +8,23 @@ export declare function findProjectRootAsync({ cwd, defaultToProcessCwd, }?: {
8
8
  cwd?: string;
9
9
  defaultToProcessCwd?: boolean;
10
10
  }): Promise<string>;
11
- export declare function setProjectIdAsync(projectDir: string, options?: {
11
+ /**
12
+ * Save an EAS project ID to the appropriate field in the app config.
13
+ */
14
+ export declare function saveProjectIdToAppConfigAsync(projectDir: string, projectId: string, options?: {
12
15
  env?: Env;
13
- }): Promise<ExpoConfig | undefined>;
16
+ }): Promise<void>;
17
+ /**
18
+ * Use the owner/slug to identify an EAS project on the server.
19
+ *
20
+ * @returns the EAS project ID from the server
21
+ */
22
+ export declare function fetchProjectIdFromServerAsync(exp: ExpoConfig): Promise<string>;
23
+ /**
24
+ * Get the EAS project ID from the app config. If the project ID is not set in the config.
25
+ * use the owner/slug to identify an EAS project on the server, and attempt to save the
26
+ * EAS project ID to the appropriate field in the app config.
27
+ */
14
28
  export declare function getProjectIdAsync(exp: ExpoConfig, options?: {
15
29
  env?: Env;
16
30
  }, findProjectRootOptions?: {
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.installExpoUpdatesAsync = exports.validateAppVersionRuntimePolicySupportAsync = exports.isExpoUpdatesInstalledOrAvailable = exports.isExpoUpdatesInstalled = exports.promptToCreateProjectIfNotExistsAsync = exports.getProjectConfigDescription = exports.getProjectFullNameAsync = exports.getProjectIdAsync = exports.setProjectIdAsync = exports.findProjectRootAsync = exports.getProjectAccountNameAsync = exports.getUsername = exports.getProjectAccountName = void 0;
3
+ exports.installExpoUpdatesAsync = exports.validateAppVersionRuntimePolicySupportAsync = exports.isExpoUpdatesInstalledOrAvailable = exports.isExpoUpdatesInstalled = exports.promptToCreateProjectIfNotExistsAsync = exports.getProjectConfigDescription = exports.getProjectFullNameAsync = exports.getProjectIdAsync = exports.fetchProjectIdFromServerAsync = exports.saveProjectIdToAppConfigAsync = exports.findProjectRootAsync = exports.getProjectAccountNameAsync = exports.getUsername = exports.getProjectAccountName = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const config_1 = require("@expo/config");
6
6
  const chalk_1 = tslib_1.__importDefault(require("chalk"));
@@ -52,7 +52,7 @@ async function findProjectRootAsync({ cwd, defaultToProcessCwd = false, } = {})
52
52
  const projectRootDir = await (0, pkg_dir_1.default)(cwd);
53
53
  if (!projectRootDir) {
54
54
  if (!defaultToProcessCwd) {
55
- throw new Error('Please run this command inside a project directory.');
55
+ throw new Error('Run this command inside a project directory.');
56
56
  }
57
57
  else {
58
58
  return process.cwd();
@@ -71,15 +71,12 @@ async function findProjectRootAsync({ cwd, defaultToProcessCwd = false, } = {})
71
71
  }
72
72
  }
73
73
  exports.findProjectRootAsync = findProjectRootAsync;
74
- async function setProjectIdAsync(projectDir, options = {}) {
75
- var _a, _b;
74
+ /**
75
+ * Save an EAS project ID to the appropriate field in the app config.
76
+ */
77
+ async function saveProjectIdToAppConfigAsync(projectDir, projectId, options = {}) {
78
+ var _a;
76
79
  const exp = (0, expoConfig_1.getExpoConfig)(projectDir, options);
77
- const privacy = toAppPrivacy(exp.privacy);
78
- const projectId = await (0, ensureProjectExists_1.ensureProjectExistsAsync)({
79
- accountName: getProjectAccountName(exp, await (0, actions_1.ensureLoggedInAsync)()),
80
- projectName: exp.slug,
81
- privacy,
82
- });
83
80
  const result = await (0, config_1.modifyConfigAsync)(projectDir, {
84
81
  extra: { ...exp.extra, eas: { ...(_a = exp.extra) === null || _a === void 0 ? void 0 : _a.eas, projectId } },
85
82
  });
@@ -99,28 +96,48 @@ async function setProjectIdAsync(projectDir, options = {}) {
99
96
  default:
100
97
  throw new Error('Unexpected result type from modifyConfigAsync');
101
98
  }
102
- log_1.default.withTick(`Linked app.json to project with ID ${chalk_1.default.bold(projectId)}`);
103
- return (_b = result.config) === null || _b === void 0 ? void 0 : _b.expo;
104
99
  }
105
- exports.setProjectIdAsync = setProjectIdAsync;
100
+ exports.saveProjectIdToAppConfigAsync = saveProjectIdToAppConfigAsync;
101
+ /**
102
+ * Use the owner/slug to identify an EAS project on the server.
103
+ *
104
+ * @returns the EAS project ID from the server
105
+ */
106
+ async function fetchProjectIdFromServerAsync(exp) {
107
+ const privacy = toAppPrivacy(exp.privacy);
108
+ return await (0, ensureProjectExists_1.ensureProjectExistsAsync)({
109
+ accountName: getProjectAccountName(exp, await (0, actions_1.ensureLoggedInAsync)()),
110
+ projectName: exp.slug,
111
+ privacy,
112
+ });
113
+ }
114
+ exports.fetchProjectIdFromServerAsync = fetchProjectIdFromServerAsync;
115
+ /**
116
+ * Get the EAS project ID from the app config. If the project ID is not set in the config.
117
+ * use the owner/slug to identify an EAS project on the server, and attempt to save the
118
+ * EAS project ID to the appropriate field in the app config.
119
+ */
106
120
  async function getProjectIdAsync(exp, options = {}, findProjectRootOptions = {}) {
107
- var _a, _b, _c, _d;
121
+ var _a, _b;
108
122
  const localProjectId = (_b = (_a = exp.extra) === null || _a === void 0 ? void 0 : _a.eas) === null || _b === void 0 ? void 0 : _b.projectId;
109
123
  if (localProjectId) {
110
124
  return localProjectId;
111
125
  }
112
- // Set the project ID if it is missing.
113
126
  const projectDir = await findProjectRootAsync(findProjectRootOptions);
114
127
  if (!projectDir) {
115
- throw new Error('Please run this command inside a project directory.');
128
+ throw new Error('Run this command inside a project directory.');
129
+ }
130
+ const projectId = await fetchProjectIdFromServerAsync(exp);
131
+ try {
132
+ await saveProjectIdToAppConfigAsync(projectDir, projectId, options);
116
133
  }
117
- const newExp = await setProjectIdAsync(projectDir, options);
118
- const newLocalProjectId = (_d = (_c = newExp === null || newExp === void 0 ? void 0 : newExp.extra) === null || _c === void 0 ? void 0 : _c.eas) === null || _d === void 0 ? void 0 : _d.projectId;
119
- if (!newLocalProjectId) {
120
- // throw if we still can't locate the projectId
121
- throw new Error('Could not retrieve project ID from app.json');
134
+ catch (e) {
135
+ // saveProjectIdToAppConfigAsync already printed out a set of detailed errors and
136
+ // instructions on how to fix it. To mimic throwing the error but not halting
137
+ // execution, just warn here with the error message.
138
+ log_1.default.warn(e.message);
122
139
  }
123
- return newLocalProjectId;
140
+ return projectId;
124
141
  }
125
142
  exports.getProjectIdAsync = getProjectIdAsync;
126
143
  const toAppPrivacy = (privacy) => {
@@ -24,12 +24,12 @@ var SubmissionErrorCode;
24
24
  SubmissionErrorCode["IOS_INVALID_PROVISIONING_PROFILE_SIGNATURE"] = "SUBMISSION_SERVICE_IOS_INVALID_PROVISIONING_PROFILE_SIGNATURE";
25
25
  })(SubmissionErrorCode || (SubmissionErrorCode = {}));
26
26
  const SubmissionErrorMessages = {
27
- [SubmissionErrorCode.ARCHIVE_DOWNLOAD_NOT_FOUND_ERROR]: "Failed to download the archive file (Response code: 404 Not Found). Please make sure the URL you've provided is correct.",
27
+ [SubmissionErrorCode.ARCHIVE_DOWNLOAD_NOT_FOUND_ERROR]: "Failed to download the archive file (Response code: 404 Not Found). Make sure the URL you've provided is correct.",
28
28
  [SubmissionErrorCode.ARCHIVE_DOWNLOAD_FORBIDDEN_ERROR]: 'Failed to download the archive file (Response code: 403 Forbidden). This is most probably caused by trying to upload an expired build artifact. All EAS build artifacts expire after 30 days.',
29
29
  [SubmissionErrorCode.ARCHIVE_EXTRACT_CORRUPT_ARCHIVE_ERROR]: 'The compressed archive is corrupt, in an unsupported format, or contains an invalid application format. Supported files include .apk, .aab, and .ipa files and one of these files compressed into a .tar.gz archive.',
30
30
  [SubmissionErrorCode.ARCHIVE_EXTRACT_NO_FILES_FOUND_ERROR]: "EAS Submit couldn't find a valid build artifact within provided compressed archive.\n" +
31
31
  'If you provide a tar.gz archive, it should contain at least one .apk/.aab/.ipa file, depending on the submission platform.',
32
- [SubmissionErrorCode.ANDROID_UNKNOWN_ERROR]: "We couldn't figure out what went wrong. Please see logs to learn more.",
32
+ [SubmissionErrorCode.ANDROID_UNKNOWN_ERROR]: "We couldn't figure out what went wrong. See logs to learn more.",
33
33
  [SubmissionErrorCode.ANDROID_FIRST_UPLOAD_ERROR]: "You haven't submitted this app to Google Play Store yet. The first submission of the app needs to be performed manually.\n" +
34
34
  `${(0, log_1.learnMore)('https://expo.fyi/first-android-submission')}.`,
35
35
  [SubmissionErrorCode.ANDROID_OLD_VERSION_CODE_ERROR]: "You've already submitted this version of the app.\n" +
@@ -42,22 +42,22 @@ const SubmissionErrorMessages = {
42
42
  'Versions are identified by Build Numbers (expo.ios.buildNumber in app.json).\n' +
43
43
  "If you're submitting an Expo project built with EAS Build, increment the build number in app.json and build the project again.\n" +
44
44
  `${(0, log_1.learnMore)('https://expo.fyi/bumping-ios-build-number')}.`,
45
- [SubmissionErrorCode.IOS_UNKNOWN_ERROR]: "We couldn't figure out what went wrong. Please see logs to learn more.",
45
+ [SubmissionErrorCode.IOS_UNKNOWN_ERROR]: "We couldn't figure out what went wrong. See logs to learn more.",
46
46
  [SubmissionErrorCode.IOS_MISSING_APP_ICON]: 'Your iOS app icon is missing or is an invalid format. The icon must be a 1024x1024 PNG image with no transparency.\n' +
47
- 'Please check your icon image and icon configuration in app.json.\n' +
47
+ 'Check your icon image and icon configuration in app.json.\n' +
48
48
  `${(0, log_1.learnMore)('https://docs.expo.dev/guides/app-icons/')}`,
49
49
  [SubmissionErrorCode.IOS_INVALID_SIGNATURE]: 'Your app signature seems to be invalid.\n' +
50
- "Please check your iOS Distribution Certificate and your app's Provisioning Profile.\n" +
50
+ "Check your iOS Distribution Certificate and your app's Provisioning Profile.\n" +
51
51
  `${(0, log_1.learnMore)('https://docs.expo.dev/distribution/app-signing')}`,
52
- [SubmissionErrorCode.IOS_INCORRECT_CREDENTIALS]: 'Your Apple ID or app-specific password is incorrect. Please verify that you entered them correctly and try again.',
52
+ [SubmissionErrorCode.IOS_INCORRECT_CREDENTIALS]: 'Your Apple ID or app-specific password is incorrect. Verify that you entered them correctly and try again.',
53
53
  [SubmissionErrorCode.IOS_IPAD_INVALID_ORIENTATION]: "Your app doesn't support iPad multitasking and has to require full screen.\n" +
54
54
  "If you're submitting a managed Expo project, set the `expo.ios.requireFullScreen` to true in app.json and build the project again.\n" +
55
55
  `${(0, log_1.learnMore)('https://expo.fyi/ipad-requires-fullscreen')}`,
56
- [SubmissionErrorCode.IOS_APPLE_MAINTENANCE]: 'It looks like Apple servers are undergoing an unscheduled maintenance. Please try again later.',
56
+ [SubmissionErrorCode.IOS_APPLE_MAINTENANCE]: 'It looks like Apple servers are undergoing an unscheduled maintenance. Try again later.',
57
57
  [SubmissionErrorCode.IOS_INVALID_PROVISIONING_PROFILE_SIGNATURE]: 'Invalid Provisioning Profile Signature (ITMS-90165)\n' +
58
58
  "Some of Apple's certificates have expired.\n" +
59
- 'Please delete your Provisioning Profile from your account. Then rebuild the app interactively to generate a new one, and try submitting it to the App Store again.',
60
- [SubmissionErrorCode.UPLOAD_TAKING_TOO_LONG_ERROR]: 'Submission has reached the timeout limit. Please try again.',
59
+ 'Delete your Provisioning Profile from your account. Then rebuild the app interactively to generate a new one, and try submitting it to the App Store again.',
60
+ [SubmissionErrorCode.UPLOAD_TAKING_TOO_LONG_ERROR]: 'Submission has reached the timeout limit. Try again.',
61
61
  };
62
62
  function printSubmissionError(error) {
63
63
  if (error.errorCode &&
@@ -52,7 +52,7 @@ function formatUpdate(update) {
52
52
  exports.formatUpdate = formatUpdate;
53
53
  function ensureValidVersions(exp, platform) {
54
54
  var _a, _b;
55
- const error = new Error(`Couldn't find either ${chalk_1.default.bold('runtimeVersion')} or ${chalk_1.default.bold('sdkVersion')} to configure ${chalk_1.default.bold('expo-updates')}. Please specify at least one of these properties under the ${chalk_1.default.bold('expo')} key in ${chalk_1.default.bold('app.json')}. ${(0, log_1.learnMore)('https://docs.expo.dev/eas-update/runtime-versions/')}`);
55
+ const error = new Error(`Couldn't find either ${chalk_1.default.bold('runtimeVersion')} or ${chalk_1.default.bold('sdkVersion')} to configure ${chalk_1.default.bold('expo-updates')}. Specify at least one of these properties under the ${chalk_1.default.bold('expo')} key in ${chalk_1.default.bold('app.json')}. ${(0, log_1.learnMore)('https://docs.expo.dev/eas-update/runtime-versions/')}`);
56
56
  if ([platform_1.RequestedPlatform.Android, platform_1.RequestedPlatform.All].includes(platform) &&
57
57
  !(((_a = exp.android) === null || _a === void 0 ? void 0 : _a.runtimeVersion) || exp.runtimeVersion) &&
58
58
  !exp.sdkVersion) {