eas-cli 3.13.2 → 3.14.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 (59) hide show
  1. package/README.md +55 -55
  2. package/build/api.d.ts +1 -0
  3. package/build/api.js +14 -1
  4. package/build/build/build.js +8 -5
  5. package/build/build/configure.d.ts +1 -0
  6. package/build/build/configure.js +8 -4
  7. package/build/build/local.js +1 -1
  8. package/build/build/runBuildAndSubmit.js +29 -0
  9. package/build/commandUtils/EasCommand.js +3 -1
  10. package/build/commandUtils/context/contextUtils/getProjectIdAsync.js +3 -3
  11. package/build/commands/account/login.d.ts +3 -0
  12. package/build/commands/account/login.js +12 -1
  13. package/build/commands/build/configure.js +5 -1
  14. package/build/commands/project/init.js +1 -1
  15. package/build/commands/update/configure.js +14 -15
  16. package/build/commands/update/index.js +40 -3
  17. package/build/credentials/android/api/GraphqlClient.d.ts +1 -0
  18. package/build/credentials/android/api/GraphqlClient.js +5 -7
  19. package/build/credentials/android/api/graphql/mutations/AndroidAppBuildCredentialsMutation.d.ts +1 -0
  20. package/build/credentials/android/api/graphql/mutations/AndroidAppBuildCredentialsMutation.js +23 -0
  21. package/build/credentials/ios/appstore/bundleIdCapabilities.js +43 -0
  22. package/build/credentials/manager/Actions.d.ts +11 -10
  23. package/build/credentials/manager/Actions.js +11 -10
  24. package/build/credentials/manager/AndroidActions.js +5 -0
  25. package/build/credentials/manager/CreateAndroidBuildCredentials.d.ts +8 -0
  26. package/build/credentials/manager/CreateAndroidBuildCredentials.js +33 -0
  27. package/build/credentials/manager/ManageAndroid.js +6 -15
  28. package/build/credentials/manager/SetDefaultAndroidKeystore.d.ts +8 -0
  29. package/build/credentials/manager/SetDefaultAndroidKeystore.js +41 -0
  30. package/build/graphql/generated.d.ts +76 -12
  31. package/build/graphql/generated.js +13 -2
  32. package/build/graphql/queries/UserQuery.js +2 -5
  33. package/build/project/expoConfig.d.ts +5 -1
  34. package/build/project/expoConfig.js +58 -1
  35. package/build/project/projectUtils.d.ts +2 -0
  36. package/build/project/projectUtils.js +14 -3
  37. package/build/project/publish.d.ts +8 -1
  38. package/build/project/publish.js +19 -5
  39. package/build/update/android/UpdatesModule.d.ts +3 -0
  40. package/build/update/android/UpdatesModule.js +11 -0
  41. package/build/update/configure.js +9 -5
  42. package/build/user/SessionManager.d.ts +3 -1
  43. package/build/user/SessionManager.js +16 -2
  44. package/build/user/User.d.ts +1 -1
  45. package/build/user/User.js +1 -1
  46. package/build/user/actions.js +1 -1
  47. package/build/user/expoSsoLauncher.d.ts +4 -0
  48. package/build/user/expoSsoLauncher.js +71 -0
  49. package/build/user/fetchSessionSecretAndSsoUser.d.ts +5 -0
  50. package/build/user/fetchSessionSecretAndSsoUser.js +20 -0
  51. package/build/user/fetchSessionSecretAndUser.js +4 -24
  52. package/build/user/fetchUser.d.ts +6 -0
  53. package/build/user/fetchUser.js +27 -0
  54. package/build/utils/expoCli.js +12 -2
  55. package/build/utils/port.d.ts +2 -0
  56. package/build/utils/port.js +14 -0
  57. package/build/vcs/clients/git.js +1 -1
  58. package/oclif.manifest.json +1 -1
  59. package/package.json +5 -4
@@ -39,10 +39,12 @@ export default class SessionManager {
39
39
  *
40
40
  * @deprecated Should not be used outside of context functions, except in the AccountLogin command.
41
41
  */
42
- showLoginPromptAsync({ nonInteractive, printNewLine, }?: {
42
+ showLoginPromptAsync({ nonInteractive, printNewLine, sso, }?: {
43
43
  nonInteractive?: boolean | undefined;
44
44
  printNewLine?: boolean | undefined;
45
+ sso?: boolean | undefined;
45
46
  }): Promise<void>;
47
+ private ssoLoginAsync;
46
48
  private loginAsync;
47
49
  /**
48
50
  * Prompt for an OTP with the option to cancel the question by answering empty (pressing return key).
@@ -14,6 +14,7 @@ const UserQuery_1 = require("../graphql/queries/UserQuery");
14
14
  const log_1 = tslib_1.__importStar(require("../log"));
15
15
  const prompts_1 = require("../prompts");
16
16
  const paths_1 = require("../utils/paths");
17
+ const fetchSessionSecretAndSsoUser_1 = require("./fetchSessionSecretAndSsoUser");
17
18
  const fetchSessionSecretAndUser_1 = require("./fetchSessionSecretAndUser");
18
19
  var UserSecondFactorDeviceMethod;
19
20
  (function (UserSecondFactorDeviceMethod) {
@@ -102,14 +103,18 @@ class SessionManager {
102
103
  *
103
104
  * @deprecated Should not be used outside of context functions, except in the AccountLogin command.
104
105
  */
105
- async showLoginPromptAsync({ nonInteractive = false, printNewLine = false, } = {}) {
106
+ async showLoginPromptAsync({ nonInteractive = false, printNewLine = false, sso = false, } = {}) {
106
107
  if (nonInteractive) {
107
108
  core_1.Errors.error(`Either log in with ${chalk_1.default.bold('eas login')} or set the ${chalk_1.default.bold('EXPO_TOKEN')} environment variable if you're using EAS CLI on CI (${(0, log_1.learnMore)('https://docs.expo.dev/accounts/programmatic-access/', { dim: false })})`);
108
109
  }
109
110
  if (printNewLine) {
110
111
  log_1.default.newLine();
111
112
  }
112
- log_1.default.log('Log in to EAS');
113
+ if (sso) {
114
+ await this.ssoLoginAsync();
115
+ return;
116
+ }
117
+ log_1.default.log(`Log in to EAS with email or username (exit and run ${chalk_1.default.bold('eas login')} for other options)`);
113
118
  const { username, password } = await (0, prompts_1.promptAsync)([
114
119
  {
115
120
  type: 'text',
@@ -137,6 +142,15 @@ class SessionManager {
137
142
  }
138
143
  }
139
144
  }
145
+ async ssoLoginAsync() {
146
+ const { sessionSecret, id, username } = await (0, fetchSessionSecretAndSsoUser_1.fetchSessionSecretAndSsoUserAsync)();
147
+ await this.setSessionAsync({
148
+ sessionSecret,
149
+ userId: id,
150
+ username,
151
+ currentConnection: 'Browser-Flow-Authentication',
152
+ });
153
+ }
140
154
  async loginAsync(input) {
141
155
  const { sessionSecret, id, username } = await (0, fetchSessionSecretAndUser_1.fetchSessionSecretAndUserAsync)(input);
142
156
  await this.setSessionAsync({
@@ -1,7 +1,7 @@
1
1
  import { CurrentUserQuery, Robot, SsoUser, User } from '../graphql/generated';
2
2
  export type Actor = NonNullable<CurrentUserQuery['meActor']>;
3
3
  /**
4
- * Resolve the name of the actor, either normal user or robot user.
4
+ * Resolve the name of the actor, either normal user, sso user or robot user.
5
5
  * This should be used whenever the "current user" needs to be displayed.
6
6
  * The display name CANNOT be used as project owner.
7
7
  */
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getActorUsername = exports.getActorDisplayName = void 0;
4
4
  /**
5
- * Resolve the name of the actor, either normal user or robot user.
5
+ * Resolve the name of the actor, either normal user, sso user or robot user.
6
6
  * This should be used whenever the "current user" needs to be displayed.
7
7
  * The display name CANNOT be used as project owner.
8
8
  */
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ensureActorHasPrimaryAccount = void 0;
4
4
  function ensureActorHasPrimaryAccount(user) {
5
- if (user.__typename === 'User') {
5
+ if (user.__typename === 'User' || user.__typename === 'SSOUser') {
6
6
  return user.primaryAccount;
7
7
  }
8
8
  throw new Error('This action is not supported for robot users.');
@@ -0,0 +1,4 @@
1
+ export declare function getSessionUsingBrowserAuthFlowAsync(options: {
2
+ expoWebsiteUrl: string;
3
+ serverPort: number;
4
+ }): Promise<string>;
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getSessionUsingBrowserAuthFlowAsync = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const better_opn_1 = tslib_1.__importDefault(require("better-opn"));
6
+ const http_1 = tslib_1.__importDefault(require("http"));
7
+ const querystring_1 = tslib_1.__importDefault(require("querystring"));
8
+ const log_1 = tslib_1.__importDefault(require("../log"));
9
+ async function getSessionUsingBrowserAuthFlowAsync(options) {
10
+ const { expoWebsiteUrl, serverPort } = options;
11
+ if (!expoWebsiteUrl || !serverPort) {
12
+ throw new Error('Expo website URL and local server port are required.');
13
+ }
14
+ const scheme = 'http';
15
+ const hostname = 'localhost';
16
+ const path = '/auth/callback';
17
+ const redirectUri = `${scheme}://${hostname}:${serverPort}${path}`;
18
+ const buildExpoSsoLoginUrl = () => {
19
+ const data = {
20
+ app_redirect_uri: redirectUri,
21
+ };
22
+ const params = querystring_1.default.stringify(data);
23
+ return `${expoWebsiteUrl}/sso-login?${params}`;
24
+ };
25
+ // Start server and begin auth flow
26
+ const executeAuthFlow = () => {
27
+ return new Promise(async (resolve, reject) => {
28
+ const connections = new Set();
29
+ const server = http_1.default.createServer((request, response) => {
30
+ var _a;
31
+ try {
32
+ if (!(request.method === 'GET' && ((_a = request.url) === null || _a === void 0 ? void 0 : _a.includes('/auth/callback')))) {
33
+ throw new Error('Unexpected SSO login response.');
34
+ }
35
+ const url = new URL(request.url, `http:${request.headers.host}`);
36
+ const sessionSecret = url.searchParams.get('session_secret');
37
+ if (!sessionSecret) {
38
+ throw new Error('Request missing session_secret search parameter.');
39
+ }
40
+ resolve(sessionSecret);
41
+ response.writeHead(200, { 'Content-Type': 'text/plain' });
42
+ response.write(`Website login has completed. You can now close this tab.`);
43
+ response.end();
44
+ }
45
+ catch (error) {
46
+ reject(error);
47
+ }
48
+ finally {
49
+ server.close();
50
+ // Ensure that the server shuts down
51
+ for (const connection of connections) {
52
+ connection.destroy();
53
+ }
54
+ }
55
+ });
56
+ server.listen(serverPort, hostname, () => {
57
+ log_1.default.log('Waiting for browser login...');
58
+ });
59
+ server.on('connection', connection => {
60
+ connections.add(connection);
61
+ connection.on('close', () => {
62
+ connections.delete(connection);
63
+ });
64
+ });
65
+ const authorizeUrl = buildExpoSsoLoginUrl();
66
+ (0, better_opn_1.default)(authorizeUrl);
67
+ });
68
+ };
69
+ return await executeAuthFlow();
70
+ }
71
+ exports.getSessionUsingBrowserAuthFlowAsync = getSessionUsingBrowserAuthFlowAsync;
@@ -0,0 +1,5 @@
1
+ export declare function fetchSessionSecretAndSsoUserAsync(): Promise<{
2
+ sessionSecret: string;
3
+ id: string;
4
+ username: string;
5
+ }>;
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.fetchSessionSecretAndSsoUserAsync = void 0;
4
+ const api_1 = require("../api");
5
+ const expoSsoLauncher_1 = require("./expoSsoLauncher");
6
+ const fetchUser_1 = require("./fetchUser");
7
+ async function fetchSessionSecretAndSsoUserAsync() {
8
+ const config = {
9
+ expoWebsiteUrl: (0, api_1.getExpoWebsiteBaseUrl)(),
10
+ serverPort: await (0, api_1.getSsoLocalServerPortAsync)(),
11
+ };
12
+ const sessionSecret = await (0, expoSsoLauncher_1.getSessionUsingBrowserAuthFlowAsync)(config);
13
+ const userData = await (0, fetchUser_1.fetchUserAsync)({ sessionSecret });
14
+ return {
15
+ sessionSecret,
16
+ id: userData.id,
17
+ username: userData.username,
18
+ };
19
+ }
20
+ exports.fetchSessionSecretAndSsoUserAsync = fetchSessionSecretAndSsoUserAsync;
@@ -1,10 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.fetchSessionSecretAndUserAsync = void 0;
4
- const tslib_1 = require("tslib");
5
- const graphql_tag_1 = tslib_1.__importDefault(require("graphql-tag"));
6
4
  const api_1 = require("../api");
7
- const createGraphqlClient_1 = require("../commandUtils/context/contextUtils/createGraphqlClient");
5
+ const fetchUser_1 = require("./fetchUser");
8
6
  async function fetchSessionSecretAndUserAsync({ username, password, otp, }) {
9
7
  // this is a logged-out endpoint
10
8
  const apiV2Client = new api_1.ApiV2Client({
@@ -15,29 +13,11 @@ async function fetchSessionSecretAndUserAsync({ username, password, otp, }) {
15
13
  body: { username, password, otp },
16
14
  });
17
15
  const { sessionSecret } = body.data;
18
- const graphqlClient = (0, createGraphqlClient_1.createGraphqlClient)({ accessToken: null, sessionSecret: null });
19
- const result = await graphqlClient
20
- .query((0, graphql_tag_1.default) `
21
- query UserQuery {
22
- viewer {
23
- id
24
- username
25
- }
26
- }
27
- `, {}, {
28
- fetchOptions: {
29
- headers: {
30
- 'expo-session': sessionSecret,
31
- },
32
- },
33
- additionalTypenames: [] /* UserQuery has immutable fields */,
34
- })
35
- .toPromise();
36
- const { data } = result;
16
+ const userData = await (0, fetchUser_1.fetchUserAsync)({ sessionSecret });
37
17
  return {
38
18
  sessionSecret,
39
- id: data.viewer.id,
40
- username: data.viewer.username,
19
+ id: userData.id,
20
+ username: userData.username,
41
21
  };
42
22
  }
43
23
  exports.fetchSessionSecretAndUserAsync = fetchSessionSecretAndUserAsync;
@@ -0,0 +1,6 @@
1
+ export declare function fetchUserAsync({ sessionSecret, }: {
2
+ sessionSecret: string;
3
+ }): Promise<{
4
+ id: string;
5
+ username: string;
6
+ }>;
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.fetchUserAsync = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const graphql_tag_1 = tslib_1.__importDefault(require("graphql-tag"));
6
+ const createGraphqlClient_1 = require("../commandUtils/context/contextUtils/createGraphqlClient");
7
+ async function fetchUserAsync({ sessionSecret, }) {
8
+ const graphqlClient = (0, createGraphqlClient_1.createGraphqlClient)({ accessToken: null, sessionSecret });
9
+ const result = await graphqlClient
10
+ .query((0, graphql_tag_1.default) `
11
+ query UserQuery {
12
+ meUserActor {
13
+ id
14
+ username
15
+ }
16
+ }
17
+ `, {}, {
18
+ additionalTypenames: [] /* UserQuery has immutable fields */,
19
+ })
20
+ .toPromise();
21
+ const { data } = result;
22
+ return {
23
+ id: data.meUserActor.id,
24
+ username: data.meUserActor.username,
25
+ };
26
+ }
27
+ exports.fetchUserAsync = fetchUserAsync;
@@ -7,7 +7,7 @@ const chalk_1 = tslib_1.__importDefault(require("chalk"));
7
7
  const getenv_1 = require("getenv");
8
8
  const resolve_from_1 = tslib_1.__importStar(require("resolve-from"));
9
9
  const semver_1 = tslib_1.__importDefault(require("semver"));
10
- const log_1 = tslib_1.__importDefault(require("../log"));
10
+ const log_1 = tslib_1.__importStar(require("../log"));
11
11
  const memoize_1 = require("./expodash/memoize");
12
12
  // Aggressively returns `true` (UNVERSIONED, invalid SDK version format) to push users towards the versioned CLI.
13
13
  function gteSdkVersion(fromSdkVersion, sdkVersion) {
@@ -53,7 +53,17 @@ exports.shouldUseVersionedExpoCLIExpensive = shouldUseVersionedExpoCLIExpensive;
53
53
  exports.shouldUseVersionedExpoCLI = (0, memoize_1.memoize)(shouldUseVersionedExpoCLIExpensive);
54
54
  async function expoCommandAsync(projectDir, args, { silent = false } = {}) {
55
55
  var _a;
56
- const expoCliPath = (_a = (0, resolve_from_1.silent)(projectDir, 'expo/bin/cli')) !== null && _a !== void 0 ? _a : (0, resolve_from_1.default)(projectDir, 'expo/bin/cli.js');
56
+ let expoCliPath;
57
+ try {
58
+ expoCliPath =
59
+ (_a = (0, resolve_from_1.silent)(projectDir, 'expo/bin/cli')) !== null && _a !== void 0 ? _a : (0, resolve_from_1.default)(projectDir, 'expo/bin/cli.js');
60
+ }
61
+ catch (e) {
62
+ if (e.code === 'MODULE_NOT_FOUND') {
63
+ throw new Error(`The \`expo\` package was not found. Follow the installation directions at ${(0, log_1.link)('https://docs.expo.dev/bare/installing-expo-modules/')}`);
64
+ }
65
+ throw e;
66
+ }
57
67
  const spawnPromise = (0, spawn_async_1.default)(expoCliPath, args, {
58
68
  stdio: ['inherit', 'pipe', 'pipe'], // inherit stdin so user can install a missing expo-cli from inside this command
59
69
  });
@@ -0,0 +1,2 @@
1
+ /** Get a free port or throw an error. */
2
+ export declare function getFreePortAsync(rangeStart: number): Promise<number>;
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getFreePortAsync = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const freeport_async_1 = tslib_1.__importDefault(require("freeport-async"));
6
+ /** Get a free port or throw an error. */
7
+ async function getFreePortAsync(rangeStart) {
8
+ const port = await (0, freeport_async_1.default)(rangeStart, { hostnames: [null, 'localhost'] });
9
+ if (!port) {
10
+ throw new Error('No available port found');
11
+ }
12
+ return port;
13
+ }
14
+ exports.getFreePortAsync = getFreePortAsync;
@@ -35,7 +35,7 @@ class GitClient extends vcs_1.Client {
35
35
  return;
36
36
  }
37
37
  log_1.default.warn("It looks like you haven't initialized the git repository yet.");
38
- log_1.default.warn('EAS Build requires you to use a git repository for your project.');
38
+ log_1.default.warn('EAS requires you to use a git repository for your project.');
39
39
  const cwd = process.cwd();
40
40
  const repoRoot = (_a = PackageManagerUtils.findWorkspaceRoot(cwd)) !== null && _a !== void 0 ? _a : cwd;
41
41
  const confirmInit = await (0, prompts_1.confirmAsync)({