eas-cli 18.0.3 → 18.0.5
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 +92 -90
- package/build/commandUtils/flags.js +1 -1
- package/build/commands/go.d.ts +22 -0
- package/build/commands/go.js +463 -0
- package/build/commands/update/configure.js +5 -0
- package/build/commands/update/index.js +10 -5
- package/build/credentials/context.d.ts +2 -0
- package/build/credentials/context.js +2 -0
- package/build/credentials/ios/actions/AscApiKeyUtils.js +4 -0
- package/build/credentials/ios/actions/PushKeyUtils.js +1 -1
- package/build/credentials/ios/actions/SetUpAscApiKey.js +9 -3
- package/build/credentials/ios/actions/SetUpDistributionCertificate.js +4 -3
- package/build/credentials/ios/actions/SetUpProvisioningProfile.js +1 -1
- package/build/credentials/ios/actions/SetUpPushKey.js +8 -3
- package/build/graphql/mutations/WorkflowRunMutation.d.ts +7 -1
- package/build/graphql/mutations/WorkflowRunMutation.js +19 -0
- package/build/log.d.ts +6 -0
- package/build/log.js +8 -0
- package/build/update/utils.d.ts +4 -0
- package/build/update/utils.js +13 -0
- package/build/user/expoBrowserAuthFlowLauncher.js +13 -70
- package/oclif.manifest.json +40 -3
- package/package.json +2 -2
|
@@ -73,7 +73,7 @@ class SetUpProvisioningProfile {
|
|
|
73
73
|
return await this.assignNewAndDeleteOldProfileAsync(ctx, distCert, currentProfile);
|
|
74
74
|
}
|
|
75
75
|
const isNonInteractiveOrUserDidConfirmAsync = async () => {
|
|
76
|
-
if (ctx.nonInteractive) {
|
|
76
|
+
if (ctx.nonInteractive || ctx.autoAcceptCredentialReuse) {
|
|
77
77
|
return true;
|
|
78
78
|
}
|
|
79
79
|
return await (0, prompts_1.confirmAsync)({
|
|
@@ -46,15 +46,20 @@ class SetUpPushKey {
|
|
|
46
46
|
: [];
|
|
47
47
|
if (validPushKeys.length > 0) {
|
|
48
48
|
const autoselectedPushKey = validPushKeys[0];
|
|
49
|
-
const useAutoselected =
|
|
50
|
-
|
|
51
|
-
|
|
49
|
+
const useAutoselected = ctx.autoAcceptCredentialReuse ||
|
|
50
|
+
(await (0, prompts_1.confirmAsync)({
|
|
51
|
+
message: `Reuse this Push Key?\n${(0, PushKeyUtils_1.formatPushKey)(autoselectedPushKey, validPushKeys.map(pushKey => pushKey.keyIdentifier))}`,
|
|
52
|
+
}));
|
|
52
53
|
if (useAutoselected) {
|
|
53
54
|
log_1.default.log(`Using push key with ID ${autoselectedPushKey.keyIdentifier}`);
|
|
54
55
|
return autoselectedPushKey;
|
|
55
56
|
}
|
|
56
57
|
}
|
|
57
58
|
}
|
|
59
|
+
// When auto-accepting and no valid push key was found, generate a new one without prompting
|
|
60
|
+
if (ctx.autoAcceptCredentialReuse) {
|
|
61
|
+
return await new CreatePushKey_1.CreatePushKey(this.app.account).runAsync(ctx);
|
|
62
|
+
}
|
|
58
63
|
const { action } = await (0, prompts_1.promptAsync)({
|
|
59
64
|
type: 'select',
|
|
60
65
|
name: 'action',
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ExpoGraphqlClient } from '../../commandUtils/context/contextUtils/createGraphqlClient';
|
|
2
|
-
import { WorkflowRevisionInput, WorkflowRunInput } from '../generated';
|
|
2
|
+
import { WorkflowProjectSourceInput, WorkflowRevisionInput, WorkflowRunInput } from '../generated';
|
|
3
3
|
export declare namespace WorkflowRunMutation {
|
|
4
4
|
function createWorkflowRunAsync(graphqlClient: ExpoGraphqlClient, { appId, workflowRevisionInput, workflowRunInput, }: {
|
|
5
5
|
appId: string;
|
|
@@ -15,6 +15,12 @@ export declare namespace WorkflowRunMutation {
|
|
|
15
15
|
}): Promise<{
|
|
16
16
|
id: string;
|
|
17
17
|
}>;
|
|
18
|
+
function createExpoGoRepackWorkflowRunAsync(graphqlClient: ExpoGraphqlClient, { appId, projectSource, }: {
|
|
19
|
+
appId: string;
|
|
20
|
+
projectSource: WorkflowProjectSourceInput;
|
|
21
|
+
}): Promise<{
|
|
22
|
+
id: string;
|
|
23
|
+
}>;
|
|
18
24
|
function cancelWorkflowRunAsync(graphqlClient: ExpoGraphqlClient, { workflowRunId, }: {
|
|
19
25
|
workflowRunId: string;
|
|
20
26
|
}): Promise<void>;
|
|
@@ -60,6 +60,25 @@ var WorkflowRunMutation;
|
|
|
60
60
|
return { id: data.workflowRun.createWorkflowRunFromGitRef.id };
|
|
61
61
|
}
|
|
62
62
|
WorkflowRunMutation.createWorkflowRunFromGitRefAsync = createWorkflowRunFromGitRefAsync;
|
|
63
|
+
async function createExpoGoRepackWorkflowRunAsync(graphqlClient, { appId, projectSource, }) {
|
|
64
|
+
const data = await (0, client_1.withErrorHandlingAsync)(graphqlClient
|
|
65
|
+
.mutation(
|
|
66
|
+
/* eslint-disable graphql/template-strings */
|
|
67
|
+
(0, graphql_tag_1.default) `
|
|
68
|
+
mutation CreateExpoGoRepackWorkflowRun($appId: ID!, $projectSource: WorkflowProjectSourceInput!) {
|
|
69
|
+
workflowRun {
|
|
70
|
+
createExpoGoRepackWorkflowRun(appId: $appId, projectSource: $projectSource) {
|
|
71
|
+
id
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
`,
|
|
76
|
+
/* eslint-enable graphql/template-strings */
|
|
77
|
+
{ appId, projectSource })
|
|
78
|
+
.toPromise());
|
|
79
|
+
return { id: data.workflowRun.createExpoGoRepackWorkflowRun.id };
|
|
80
|
+
}
|
|
81
|
+
WorkflowRunMutation.createExpoGoRepackWorkflowRunAsync = createExpoGoRepackWorkflowRunAsync;
|
|
63
82
|
async function cancelWorkflowRunAsync(graphqlClient, { workflowRunId, }) {
|
|
64
83
|
await (0, client_1.withErrorHandlingAsync)(graphqlClient
|
|
65
84
|
.mutation((0, graphql_tag_1.default) `
|
package/build/log.d.ts
CHANGED
|
@@ -3,6 +3,12 @@ export default class Log {
|
|
|
3
3
|
static log(...args: any[]): void;
|
|
4
4
|
static newLine(): void;
|
|
5
5
|
static addNewLineIfNone(): void;
|
|
6
|
+
/**
|
|
7
|
+
* Signal that the cursor is already at the start of a fresh line (e.g. after
|
|
8
|
+
* a spinner clears itself), so that the next `addNewLineIfNone()` call knows
|
|
9
|
+
* it doesn't need to emit an extra blank line.
|
|
10
|
+
*/
|
|
11
|
+
static markFreshLine(): void;
|
|
6
12
|
static error(...args: any[]): void;
|
|
7
13
|
static warn(...args: any[]): void;
|
|
8
14
|
static debug(...args: any[]): void;
|
package/build/log.js
CHANGED
|
@@ -23,6 +23,14 @@ class Log {
|
|
|
23
23
|
Log.newLine();
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
|
+
/**
|
|
27
|
+
* Signal that the cursor is already at the start of a fresh line (e.g. after
|
|
28
|
+
* a spinner clears itself), so that the next `addNewLineIfNone()` call knows
|
|
29
|
+
* it doesn't need to emit an extra blank line.
|
|
30
|
+
*/
|
|
31
|
+
static markFreshLine() {
|
|
32
|
+
Log.isLastLineNewLine = true;
|
|
33
|
+
}
|
|
26
34
|
static error(...args) {
|
|
27
35
|
Log.consoleLog(...Log.withTextColor(args, chalk_1.default.red));
|
|
28
36
|
}
|
package/build/update/utils.d.ts
CHANGED
|
@@ -58,3 +58,7 @@ export declare function isBundleDiffingEnabled(exp: ExpoConfig): boolean;
|
|
|
58
58
|
export declare function prewarmDiffingAsync(graphqlClient: ExpoGraphqlClient, appId: string, newUpdates: UpdatePublishMutation['updateBranch']['publishUpdateGroups']): Promise<void>;
|
|
59
59
|
export type UpdatePublishPlatform = 'ios' | 'android';
|
|
60
60
|
export declare const updatePublishPlatformToAppPlatform: Record<UpdatePublishPlatform, AppPlatform>;
|
|
61
|
+
export declare function assertEnvironmentFlagForSdk55OrGreater({ sdkVersion, environment, }: {
|
|
62
|
+
sdkVersion: string | undefined;
|
|
63
|
+
environment: string | undefined;
|
|
64
|
+
}): void;
|
package/build/update/utils.js
CHANGED
|
@@ -15,10 +15,13 @@ exports.getUpdateGroupDescriptionsWithBranch = getUpdateGroupDescriptionsWithBra
|
|
|
15
15
|
exports.getBranchDescription = getBranchDescription;
|
|
16
16
|
exports.isBundleDiffingEnabled = isBundleDiffingEnabled;
|
|
17
17
|
exports.prewarmDiffingAsync = prewarmDiffingAsync;
|
|
18
|
+
exports.assertEnvironmentFlagForSdk55OrGreater = assertEnvironmentFlagForSdk55OrGreater;
|
|
18
19
|
const tslib_1 = require("tslib");
|
|
20
|
+
const core_1 = require("@oclif/core");
|
|
19
21
|
const timeago_js_1 = require("@expo/timeago.js");
|
|
20
22
|
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
21
23
|
const dateformat_1 = tslib_1.__importDefault(require("dateformat"));
|
|
24
|
+
const semver_1 = tslib_1.__importDefault(require("semver"));
|
|
22
25
|
const generated_1 = require("../graphql/generated");
|
|
23
26
|
const AssetQuery_1 = require("../graphql/queries/AssetQuery");
|
|
24
27
|
const BranchQuery_1 = require("../graphql/queries/BranchQuery");
|
|
@@ -240,3 +243,13 @@ exports.updatePublishPlatformToAppPlatform = {
|
|
|
240
243
|
android: generated_1.AppPlatform.Android,
|
|
241
244
|
ios: generated_1.AppPlatform.Ios,
|
|
242
245
|
};
|
|
246
|
+
function assertEnvironmentFlagForSdk55OrGreater({ sdkVersion, environment, }) {
|
|
247
|
+
if (process.env.EAS_BUILD) {
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
if (sdkVersion && semver_1.default.gte(sdkVersion, '55.0.0') && !environment) {
|
|
251
|
+
core_1.Errors.error('--environment flag is required for projects using Expo SDK 55 or greater', {
|
|
252
|
+
exit: 1,
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
}
|
|
@@ -4,65 +4,20 @@ exports.getSessionUsingBrowserAuthFlowAsync = getSessionUsingBrowserAuthFlowAsyn
|
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const assert_1 = tslib_1.__importDefault(require("assert"));
|
|
6
6
|
const better_opn_1 = tslib_1.__importDefault(require("better-opn"));
|
|
7
|
-
const crypto_1 = tslib_1.__importDefault(require("crypto"));
|
|
8
7
|
const http_1 = tslib_1.__importDefault(require("http"));
|
|
8
|
+
const querystring_1 = tslib_1.__importDefault(require("querystring"));
|
|
9
9
|
const api_1 = require("../api");
|
|
10
|
-
const fetch_1 = tslib_1.__importDefault(require("../fetch"));
|
|
11
10
|
const log_1 = tslib_1.__importDefault(require("../log"));
|
|
12
|
-
const CLIENT_ID = 'eas-cli';
|
|
13
|
-
function generateCodeVerifier() {
|
|
14
|
-
return crypto_1.default.randomBytes(32).toString('base64url');
|
|
15
|
-
}
|
|
16
|
-
function generateCodeChallenge(codeVerifier) {
|
|
17
|
-
return crypto_1.default.createHash('sha256').update(codeVerifier).digest('base64url');
|
|
18
|
-
}
|
|
19
|
-
function generateState() {
|
|
20
|
-
return crypto_1.default.randomBytes(32).toString('base64url');
|
|
21
|
-
}
|
|
22
|
-
async function exchangeCodeForSessionSecretAsync({ code, codeVerifier, redirectUri, }) {
|
|
23
|
-
const tokenUrl = `${(0, api_1.getExpoApiBaseUrl)()}/v2/auth/token`;
|
|
24
|
-
const response = await (0, fetch_1.default)(tokenUrl, {
|
|
25
|
-
method: 'POST',
|
|
26
|
-
headers: {
|
|
27
|
-
'Content-Type': 'application/json',
|
|
28
|
-
},
|
|
29
|
-
body: JSON.stringify({
|
|
30
|
-
grant_type: 'authorization_code',
|
|
31
|
-
code,
|
|
32
|
-
redirect_uri: redirectUri,
|
|
33
|
-
code_verifier: codeVerifier,
|
|
34
|
-
client_id: CLIENT_ID,
|
|
35
|
-
}),
|
|
36
|
-
});
|
|
37
|
-
const result = await response.json();
|
|
38
|
-
const sessionSecret = result?.data?.session_secret;
|
|
39
|
-
if (!sessionSecret) {
|
|
40
|
-
throw new Error('Failed to obtain session secret from token exchange.');
|
|
41
|
-
}
|
|
42
|
-
return sessionSecret;
|
|
43
|
-
}
|
|
44
11
|
async function getSessionUsingBrowserAuthFlowAsync({ sso = false }) {
|
|
45
12
|
const scheme = 'http';
|
|
46
13
|
const hostname = 'localhost';
|
|
47
|
-
const
|
|
14
|
+
const path = '/auth/callback';
|
|
48
15
|
const expoWebsiteUrl = (0, api_1.getExpoWebsiteBaseUrl)();
|
|
49
|
-
const codeVerifier = generateCodeVerifier();
|
|
50
|
-
const codeChallenge = generateCodeChallenge(codeVerifier);
|
|
51
|
-
const state = generateState();
|
|
52
|
-
const buildRedirectUri = (port) => `${scheme}://${hostname}:${port}${callbackPath}`;
|
|
53
16
|
const buildExpoLoginUrl = (port, sso) => {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
`client_id=${CLIENT_ID}`,
|
|
59
|
-
`redirect_uri=${buildRedirectUri(port)}`,
|
|
60
|
-
`response_type=code`,
|
|
61
|
-
`code_challenge=${codeChallenge}`,
|
|
62
|
-
`code_challenge_method=S256`,
|
|
63
|
-
`state=${state}`,
|
|
64
|
-
`confirm_account=true`,
|
|
65
|
-
].join('&');
|
|
17
|
+
const params = querystring_1.default.stringify({
|
|
18
|
+
confirm_account: true,
|
|
19
|
+
app_redirect_uri: `${scheme}://${hostname}:${port}${path}`,
|
|
20
|
+
});
|
|
66
21
|
return `${expoWebsiteUrl}${sso ? '/sso-login' : '/login'}?${params}`;
|
|
67
22
|
};
|
|
68
23
|
// Start server and begin auth flow
|
|
@@ -79,34 +34,22 @@ async function getSessionUsingBrowserAuthFlowAsync({ sso = false }) {
|
|
|
79
34
|
connection.destroy();
|
|
80
35
|
}
|
|
81
36
|
};
|
|
82
|
-
|
|
37
|
+
try {
|
|
83
38
|
if (!(request.method === 'GET' && request.url?.includes('/auth/callback'))) {
|
|
84
39
|
throw new Error('Unexpected login response.');
|
|
85
40
|
}
|
|
86
41
|
const url = new URL(request.url, `http:${request.headers.host}`);
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
throw new Error('Request missing code search parameter.');
|
|
91
|
-
}
|
|
92
|
-
if (returnedState !== state) {
|
|
93
|
-
throw new Error('State mismatch. Possible CSRF attack.');
|
|
42
|
+
const sessionSecret = url.searchParams.get('session_secret');
|
|
43
|
+
if (!sessionSecret) {
|
|
44
|
+
throw new Error('Request missing session_secret search parameter.');
|
|
94
45
|
}
|
|
95
|
-
const address = server.address();
|
|
96
|
-
(0, assert_1.default)(address !== null && typeof address === 'object');
|
|
97
|
-
const redirectUri = buildRedirectUri(address.port);
|
|
98
|
-
const sessionSecret = await exchangeCodeForSessionSecretAsync({
|
|
99
|
-
code,
|
|
100
|
-
codeVerifier,
|
|
101
|
-
redirectUri,
|
|
102
|
-
});
|
|
103
46
|
resolve(sessionSecret);
|
|
104
47
|
redirectAndCleanup('success');
|
|
105
|
-
}
|
|
106
|
-
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
107
50
|
redirectAndCleanup('error');
|
|
108
51
|
reject(error);
|
|
109
|
-
}
|
|
52
|
+
}
|
|
110
53
|
});
|
|
111
54
|
server.listen(0, hostname, () => {
|
|
112
55
|
log_1.default.log('Waiting for browser login...');
|
package/oclif.manifest.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "18.0.
|
|
2
|
+
"version": "18.0.5",
|
|
3
3
|
"commands": {
|
|
4
4
|
"analytics": {
|
|
5
5
|
"id": "analytics",
|
|
@@ -93,6 +93,43 @@
|
|
|
93
93
|
"vcsClient": {}
|
|
94
94
|
}
|
|
95
95
|
},
|
|
96
|
+
"go": {
|
|
97
|
+
"id": "go",
|
|
98
|
+
"description": "Create a custom Expo Go and submit to TestFlight",
|
|
99
|
+
"strict": true,
|
|
100
|
+
"pluginName": "eas-cli",
|
|
101
|
+
"pluginAlias": "eas-cli",
|
|
102
|
+
"pluginType": "core",
|
|
103
|
+
"hidden": true,
|
|
104
|
+
"aliases": [],
|
|
105
|
+
"flags": {
|
|
106
|
+
"bundle-id": {
|
|
107
|
+
"name": "bundle-id",
|
|
108
|
+
"type": "option",
|
|
109
|
+
"description": "iOS bundle identifier (auto-generated if not provided)",
|
|
110
|
+
"required": false,
|
|
111
|
+
"multiple": false
|
|
112
|
+
},
|
|
113
|
+
"name": {
|
|
114
|
+
"name": "name",
|
|
115
|
+
"type": "option",
|
|
116
|
+
"description": "App name",
|
|
117
|
+
"multiple": false,
|
|
118
|
+
"default": "My Expo Go"
|
|
119
|
+
},
|
|
120
|
+
"credentials": {
|
|
121
|
+
"name": "credentials",
|
|
122
|
+
"type": "boolean",
|
|
123
|
+
"description": "Interactively select credentials (default: auto-select)",
|
|
124
|
+
"allowNo": false
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
"args": {},
|
|
128
|
+
"contextDefinition": {
|
|
129
|
+
"loggedIn": {},
|
|
130
|
+
"analytics": {}
|
|
131
|
+
}
|
|
132
|
+
},
|
|
96
133
|
"open": {
|
|
97
134
|
"id": "open",
|
|
98
135
|
"description": "open the project page in a web browser",
|
|
@@ -3320,7 +3357,7 @@
|
|
|
3320
3357
|
"environment": {
|
|
3321
3358
|
"name": "environment",
|
|
3322
3359
|
"type": "option",
|
|
3323
|
-
"description": "Environment to use for the server-side defined EAS environment variables during command execution, e.g. \"production\", \"preview\", \"development\"",
|
|
3360
|
+
"description": "Environment to use for the server-side defined EAS environment variables during command execution, e.g. \"production\", \"preview\", \"development\". Required for projects using Expo SDK 55 or greater.",
|
|
3324
3361
|
"required": false,
|
|
3325
3362
|
"multiple": false
|
|
3326
3363
|
},
|
|
@@ -3532,7 +3569,7 @@
|
|
|
3532
3569
|
"environment": {
|
|
3533
3570
|
"name": "environment",
|
|
3534
3571
|
"type": "option",
|
|
3535
|
-
"description": "Environment to use for the server-side defined EAS environment variables during command execution, e.g. \"production\", \"preview\", \"development\"",
|
|
3572
|
+
"description": "Environment to use for the server-side defined EAS environment variables during command execution, e.g. \"production\", \"preview\", \"development\". Required for projects using Expo SDK 55 or greater.",
|
|
3536
3573
|
"required": false,
|
|
3537
3574
|
"multiple": false
|
|
3538
3575
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eas-cli",
|
|
3
|
-
"version": "18.0.
|
|
3
|
+
"version": "18.0.5",
|
|
4
4
|
"description": "EAS command line tool",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cli",
|
|
@@ -243,5 +243,5 @@
|
|
|
243
243
|
"engines": {
|
|
244
244
|
"node": ">=20.0.0"
|
|
245
245
|
},
|
|
246
|
-
"gitHead": "
|
|
246
|
+
"gitHead": "4b3dcda99d326dde374b0f88ebd07846be74ebf9"
|
|
247
247
|
}
|