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.
- package/README.md +50 -47
- package/build/build/android/build.js +1 -1
- package/build/build/build.js +4 -4
- package/build/build/utils/printBuildInfo.js +2 -2
- package/build/build/utils/repository.js +4 -4
- package/build/commands/branch/create.js +1 -1
- package/build/commands/branch/delete.js +1 -1
- package/build/commands/branch/rename.js +2 -2
- package/build/commands/channel/create.js +1 -1
- package/build/commands/channel/delete.js +1 -1
- package/build/commands/channel/edit.js +3 -3
- package/build/commands/channel/rollout.js +3 -3
- package/build/commands/channel/view.js +1 -1
- package/build/commands/credentials.d.ts +3 -0
- package/build/commands/credentials.js +6 -1
- package/build/commands/project/init.js +3 -1
- package/build/commands/secret/list.js +1 -1
- package/build/commands/update/index.js +4 -4
- package/build/commands/update/list.js +1 -1
- package/build/credentials/android/actions/RemoveKeystore.js +1 -1
- package/build/credentials/errors.js +1 -1
- package/build/credentials/ios/actions/DistributionCertificateUtils.js +2 -2
- package/build/credentials/ios/actions/SetUpAdhocProvisioningProfile.js +1 -1
- package/build/credentials/ios/actions/SetUpInternalProvisioningProfile.js +2 -2
- package/build/credentials/ios/actions/SetUpProvisioningProfile.js +1 -1
- package/build/credentials/ios/actions/SetUpSubmissionCredentials.js +1 -1
- package/build/credentials/ios/appstore/contractMessages.js +1 -1
- package/build/credentials/ios/appstore/ensureAppExists.js +3 -3
- package/build/credentials/ios/appstore/pushKey.js +2 -2
- package/build/credentials/manager/SelectIosDistributionTypeGraphqlFromBuildProfile.js +1 -1
- package/build/credentials/manager/SelectPlatform.d.ts +2 -0
- package/build/credentials/manager/SelectPlatform.js +7 -12
- package/build/credentials/utils/promptForCredentials.js +1 -1
- package/build/devices/manager.js +1 -1
- package/build/graphql/client.js +1 -1
- package/build/metadata/errors.js +2 -2
- package/build/project/metroConfig.js +1 -1
- package/build/project/projectUtils.d.ts +16 -2
- package/build/project/projectUtils.js +39 -22
- package/build/submit/utils/errors.js +9 -9
- package/build/update/utils.js +1 -1
- package/oclif.manifest.json +1 -1
- 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
|
|
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.
|
|
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("
|
|
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.
|
|
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: `
|
|
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: `
|
|
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.
|
|
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: '
|
|
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('
|
|
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.
|
|
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
|
-
|
|
100
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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(`
|
|
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}".
|
|
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}),
|
|
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}.
|
|
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
|
-
'\
|
|
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
|
-
|
|
15
|
-
|
|
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.
|
|
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,24 +1,19 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.SelectPlatform = void 0;
|
|
4
|
-
const
|
|
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
|
|
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
|
-
|
|
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.
|
package/build/devices/manager.js
CHANGED
|
@@ -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,
|
|
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) {
|
package/build/graphql/client.js
CHANGED
|
@@ -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
|
|
50
|
+
log_1.default.error(`We've encountered a transient error. Try again shortly.`);
|
|
51
51
|
}
|
|
52
52
|
throw error;
|
|
53
53
|
}
|
package/build/metadata/errors.js
CHANGED
|
@@ -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('
|
|
79
|
-
log_1.default.log('If this issue persists,
|
|
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
|
-
'
|
|
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
|
-
|
|
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<
|
|
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.
|
|
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('
|
|
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
|
-
|
|
75
|
-
|
|
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.
|
|
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
|
|
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('
|
|
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
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
//
|
|
121
|
-
|
|
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
|
|
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).
|
|
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.
|
|
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.
|
|
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
|
-
'
|
|
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
|
-
"
|
|
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.
|
|
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.
|
|
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
|
-
'
|
|
60
|
-
[SubmissionErrorCode.UPLOAD_TAKING_TOO_LONG_ERROR]: 'Submission has reached the timeout limit.
|
|
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 &&
|
package/build/update/utils.js
CHANGED
|
@@ -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')}.
|
|
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) {
|