eas-cli 3.15.0 → 3.16.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.
@@ -19,7 +19,7 @@ const UpdatesModule_2 = require("../../update/ios/UpdatesModule");
19
19
  const vcs_1 = require("../../vcs");
20
20
  class BuildConfigure extends EasCommand_1.default {
21
21
  async runAsync() {
22
- var _b;
22
+ var _b, _c;
23
23
  const { flags } = await this.parse(BuildConfigure);
24
24
  const { privateProjectConfig: { exp, projectId, projectDir }, loggedIn: { graphqlClient }, } = await this.getContextAsync(BuildConfigure, {
25
25
  nonInteractive: false,
@@ -39,6 +39,11 @@ class BuildConfigure extends EasCommand_1.default {
39
39
  nonInteractive: false,
40
40
  });
41
41
  if (didCreateEasJson && (0, projectUtils_1.isUsingEASUpdate)(exp, projectId)) {
42
+ if ((_c = exp.updates) === null || _c === void 0 ? void 0 : _c.useClassicUpdates) {
43
+ // NOTE: this method modifies the Expo config; be sure to use this function's return value
44
+ // if the config object is used later in the future
45
+ await (0, configure_2.ensureUseClassicUpdatesIsRemovedAsync)({ exp, projectDir });
46
+ }
42
47
  await (0, configure_2.ensureEASUpdateIsConfiguredInEasJsonAsync)(projectDir);
43
48
  }
44
49
  // configure expo-updates
@@ -17,7 +17,7 @@ class UpdateConfigure extends EasCommand_1.default {
17
17
  const { privateProjectConfig: { projectId, exp, projectDir }, loggedIn: { graphqlClient }, } = await this.getContextAsync(UpdateConfigure, {
18
18
  nonInteractive: flags['non-interactive'],
19
19
  });
20
- log_1.default.log('💡 The following process will configure your project to run EAS Update. These changes only apply to your local project files and you can safely revert them at any time.');
20
+ log_1.default.log('💡 The following process will configure your project to use EAS Update. These changes only apply to your local project files and you can safely revert them at any time.');
21
21
  await (0, vcs_1.getVcsClient)().ensureRepoExistsAsync();
22
22
  await (0, configure_2.ensureEASUpdateIsConfiguredAsync)(graphqlClient, {
23
23
  exp,
@@ -27,7 +27,7 @@ class UpdateConfigure extends EasCommand_1.default {
27
27
  });
28
28
  await (0, configure_2.ensureEASUpdateIsConfiguredInEasJsonAsync)(projectDir);
29
29
  log_1.default.addNewLineIfNone();
30
- log_1.default.log(`🎉 Your app is configured with EAS Update!`);
30
+ log_1.default.log(`🎉 Your app is configured to use EAS Update!`);
31
31
  log_1.default.newLine();
32
32
  const easJsonExists = await (0, configure_1.easJsonExistsAsync)(projectDir);
33
33
  if (!easJsonExists) {
@@ -8,7 +8,14 @@ const log_1 = tslib_1.__importDefault(require("../log"));
8
8
  async function withErrorHandlingAsync(promise) {
9
9
  const { data, error } = await promise;
10
10
  if (error) {
11
- 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; })) {
11
+ if (error.graphQLErrors.some(e => {
12
+ var _a, _b;
13
+ return ((_a = e === null || e === void 0 ? void 0 : e.extensions) === null || _a === void 0 ? void 0 : _a.isTransient) &&
14
+ ![
15
+ 'EAS_BUILD_FREE_TIER_LIMIT_EXCEEDED',
16
+ 'EAS_BUILD_FREE_TIER_IOS_LIMIT_EXCEEDED',
17
+ ].includes((_b = e === null || e === void 0 ? void 0 : e.extensions) === null || _b === void 0 ? void 0 : _b.errorCode);
18
+ })) {
12
19
  log_1.default.error(`We've encountered a transient error. Try again shortly.`);
13
20
  }
14
21
  throw error;
@@ -14,4 +14,5 @@ export declare function createOrModifyExpoConfigAsync(projectDir: string, exp: P
14
14
  }): ReturnType<typeof modifyConfigAsync>;
15
15
  export declare function getPrivateExpoConfig(projectDir: string, opts?: ExpoConfigOptions): ExpoConfig;
16
16
  export declare function ensureExpoConfigExists(projectDir: string): void;
17
+ export declare function isUsingStaticExpoConfig(projectDir: string): boolean;
17
18
  export declare function getPublicExpoConfig(projectDir: string, opts?: ExpoConfigOptions): PublicExpoConfig;
@@ -1,11 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getPublicExpoConfig = exports.ensureExpoConfigExists = exports.getPrivateExpoConfig = exports.createOrModifyExpoConfigAsync = void 0;
3
+ exports.getPublicExpoConfig = exports.isUsingStaticExpoConfig = exports.ensureExpoConfigExists = exports.getPrivateExpoConfig = exports.createOrModifyExpoConfigAsync = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const config_1 = require("@expo/config");
6
6
  const json_file_1 = tslib_1.__importDefault(require("@expo/json-file"));
7
7
  const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
8
8
  const joi_1 = tslib_1.__importDefault(require("joi"));
9
+ const nullthrows_1 = tslib_1.__importDefault(require("nullthrows"));
9
10
  const path_1 = tslib_1.__importDefault(require("path"));
10
11
  async function createOrModifyExpoConfigAsync(projectDir, exp, readOptions) {
11
12
  ensureExpoConfigExists(projectDir);
@@ -67,18 +68,23 @@ function ensureExpoConfigExists(projectDir) {
67
68
  }
68
69
  exports.ensureExpoConfigExists = ensureExpoConfigExists;
69
70
  async function ensureStaticExpoConfigIsValidAsync(projectDir) {
70
- var _a;
71
- const paths = (0, config_1.getConfigFilePaths)(projectDir);
72
- if (((_a = paths === null || paths === void 0 ? void 0 : paths.staticConfigPath) === null || _a === void 0 ? void 0 : _a.endsWith('app.json')) && !(paths === null || paths === void 0 ? void 0 : paths.dynamicConfigPath)) {
73
- const staticConfig = await json_file_1.default.readAsync(paths.staticConfigPath);
71
+ if (isUsingStaticExpoConfig(projectDir)) {
72
+ const staticConfigPath = (0, nullthrows_1.default)((0, config_1.getConfigFilePaths)(projectDir).staticConfigPath);
73
+ const staticConfig = await json_file_1.default.readAsync(staticConfigPath);
74
74
  // Add the "expo" key if it doesn't exist on app.json yet, such as in
75
75
  // projects initialized with RNC CLI
76
76
  if (!(staticConfig === null || staticConfig === void 0 ? void 0 : staticConfig.expo)) {
77
77
  staticConfig.expo = {};
78
- await json_file_1.default.writeAsync(paths.staticConfigPath, staticConfig);
78
+ await json_file_1.default.writeAsync(staticConfigPath, staticConfig);
79
79
  }
80
80
  }
81
81
  }
82
+ function isUsingStaticExpoConfig(projectDir) {
83
+ var _a;
84
+ const paths = (0, config_1.getConfigFilePaths)(projectDir);
85
+ return !!(((_a = paths.staticConfigPath) === null || _a === void 0 ? void 0 : _a.endsWith('app.json')) && !paths.dynamicConfigPath);
86
+ }
87
+ exports.isUsingStaticExpoConfig = isUsingStaticExpoConfig;
82
88
  function getPublicExpoConfig(projectDir, opts = {}) {
83
89
  ensureExpoConfigExists(projectDir);
84
90
  return getExpoConfigInternal(projectDir, { ...opts, isPublicConfig: true });
@@ -4,6 +4,7 @@ exports.getNativeTargetEntitlementsAsync = exports.getManagedApplicationTargetEn
4
4
  const config_plugins_1 = require("@expo/config-plugins");
5
5
  const prebuild_config_1 = require("@expo/prebuild-config");
6
6
  const plist_1 = require("../../utils/plist");
7
+ const workflow_1 = require("../workflow");
7
8
  async function getManagedApplicationTargetEntitlementsAsync(projectDir, env) {
8
9
  var _a;
9
10
  const originalProcessEnv = process.env;
@@ -17,6 +18,7 @@ async function getManagedApplicationTargetEntitlementsAsync(projectDir, env) {
17
18
  projectRoot: projectDir,
18
19
  platforms: ['ios'],
19
20
  introspect: true,
21
+ ignoreExistingNativeFiles: await (0, workflow_1.hasIgnoredIosProjectAsync)(projectDir),
20
22
  });
21
23
  return ((_a = expWithMods.ios) === null || _a === void 0 ? void 0 : _a.entitlements) || {};
22
24
  }
@@ -452,7 +452,7 @@ async function getRuntimeVersionObjectAsync(exp, platforms, projectDir) {
452
452
  const isManaged = (await (0, workflow_1.resolveWorkflowAsync)(projectDir, platform)) ===
453
453
  eas_build_job_1.Workflow.MANAGED;
454
454
  if (!isManaged) {
455
- throw new Error('Runtime version policies are only supported in the managed workflow. In the bare workflow, runtime version needs to be set manually.');
455
+ throw new Error(`You're currently using the bare workflow, where runtime version policies are not supported. You must set your runtime version manually. For example, define your runtime version as "1.0.0", not {"policy": "appVersion"} in your app config. ${(0, log_1.learnMore)('https://docs.expo.dev/eas-update/runtime-versions')}`);
456
456
  }
457
457
  }
458
458
  }
@@ -1,3 +1,4 @@
1
1
  import { Platform, Workflow } from '@expo/eas-build-job';
2
2
  export declare function resolveWorkflowAsync(projectDir: string, platform: Platform): Promise<Workflow>;
3
3
  export declare function resolveWorkflowPerPlatformAsync(projectDir: string): Promise<Record<Platform, Workflow>>;
4
+ export declare function hasIgnoredIosProjectAsync(projectDir: string): Promise<boolean>;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.resolveWorkflowPerPlatformAsync = exports.resolveWorkflowAsync = void 0;
3
+ exports.hasIgnoredIosProjectAsync = exports.resolveWorkflowPerPlatformAsync = exports.resolveWorkflowAsync = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const config_plugins_1 = require("@expo/config-plugins");
6
6
  const eas_build_job_1 = require("@expo/eas-build-job");
@@ -40,3 +40,15 @@ async function resolveWorkflowPerPlatformAsync(projectDir) {
40
40
  return { android, ios };
41
41
  }
42
42
  exports.resolveWorkflowPerPlatformAsync = resolveWorkflowPerPlatformAsync;
43
+ async function hasIgnoredIosProjectAsync(projectDir) {
44
+ const vcsClient = (0, vcs_1.getVcsClient)();
45
+ const vcsRootPath = path_1.default.normalize(await vcsClient.getRootPathAsync());
46
+ try {
47
+ const pbxProjectPath = config_plugins_1.IOSConfig.Paths.getPBXProjectPath(projectDir);
48
+ return await vcsClient.isFileIgnoredAsync(path_1.default.relative(vcsRootPath, pbxProjectPath));
49
+ }
50
+ finally {
51
+ return false;
52
+ }
53
+ }
54
+ exports.hasIgnoredIosProjectAsync = hasIgnoredIosProjectAsync;
@@ -12,15 +12,20 @@ export declare function ensureEASUpdateIsConfiguredInEasJsonAsync(projectDir: st
12
12
  /**
13
13
  * Make sure EAS Update is fully configured in the current project.
14
14
  * This goes over a checklist and performs the following checks or changes:
15
- * - Enure the `expo-updates` package is currently installed.
15
+ * - Ensure `updates.useClassicUpdates` (SDK 49) is not set in the app config
16
+ * - Ensure the `expo-updates` package is currently installed.
16
17
  * - Ensure `app.json` is configured for EAS Updates
17
18
  * - Sets `runtimeVersion` if not set
18
19
  * - Sets `updates.url` if not set
19
20
  * - Ensure latest changes are reflected in the native config, if any
20
21
  */
21
- export declare function ensureEASUpdateIsConfiguredAsync(graphqlClient: ExpoGraphqlClient, { exp: expWithoutUpdates, projectId, projectDir, platform, }: {
22
+ export declare function ensureEASUpdateIsConfiguredAsync(graphqlClient: ExpoGraphqlClient, { exp: expMaybeWithoutUpdates, projectId, projectDir, platform, }: {
22
23
  exp: ExpoConfig;
23
24
  projectId: string;
24
25
  projectDir: string;
25
26
  platform: RequestedPlatform | null;
26
27
  }): Promise<void>;
28
+ export declare function ensureUseClassicUpdatesIsRemovedAsync({ exp: expMaybeWithoutUpdates, projectDir, }: {
29
+ exp: ExpoConfig;
30
+ projectDir: string;
31
+ }): Promise<ExpoConfig>;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ensureEASUpdateIsConfiguredAsync = exports.ensureEASUpdateIsConfiguredInEasJsonAsync = exports.DEFAULT_BARE_RUNTIME_VERSION = exports.DEFAULT_MANAGED_RUNTIME_VERSION = void 0;
3
+ exports.ensureUseClassicUpdatesIsRemovedAsync = exports.ensureEASUpdateIsConfiguredAsync = exports.ensureEASUpdateIsConfiguredInEasJsonAsync = exports.DEFAULT_BARE_RUNTIME_VERSION = exports.DEFAULT_MANAGED_RUNTIME_VERSION = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const eas_build_job_1 = require("@expo/eas-build-job");
6
6
  const eas_json_1 = require("@expo/eas-json");
@@ -13,6 +13,7 @@ const platform_1 = require("../platform");
13
13
  const expoConfig_1 = require("../project/expoConfig");
14
14
  const projectUtils_1 = require("../project/projectUtils");
15
15
  const workflow_1 = require("../project/workflow");
16
+ const prompts_1 = require("../prompts");
16
17
  const UpdatesModule_1 = require("./android/UpdatesModule");
17
18
  const UpdatesModule_2 = require("./ios/UpdatesModule");
18
19
  exports.DEFAULT_MANAGED_RUNTIME_VERSION = { policy: 'sdkVersion' };
@@ -118,8 +119,16 @@ async function ensureEASUpdatesIsConfiguredInExpoConfigAsync({ exp, projectId, p
118
119
  throw new Error(`Unexpected result type "${result.type}" received when modifying the project config.`);
119
120
  }
120
121
  }
122
+ function serializeRuntimeVersionToString(runtimeVersion) {
123
+ if (typeof runtimeVersion === 'object') {
124
+ return JSON.stringify(runtimeVersion);
125
+ }
126
+ else {
127
+ return runtimeVersion;
128
+ }
129
+ }
121
130
  function logEasUpdatesAutoConfig({ modifyConfig, exp, }) {
122
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
131
+ var _a, _b, _c, _d, _e, _f;
123
132
  if ((_a = modifyConfig.updates) === null || _a === void 0 ? void 0 : _a.url) {
124
133
  log_1.default.withTick(((_b = exp.updates) === null || _b === void 0 ? void 0 : _b.url)
125
134
  ? `Overwrote updates.url "${exp.updates.url}" with "${modifyConfig.updates.url}"`
@@ -128,14 +137,14 @@ function logEasUpdatesAutoConfig({ modifyConfig, exp, }) {
128
137
  const androidRuntime = (_d = (_c = modifyConfig.android) === null || _c === void 0 ? void 0 : _c.runtimeVersion) !== null && _d !== void 0 ? _d : modifyConfig.runtimeVersion;
129
138
  const iosRuntime = (_f = (_e = modifyConfig.ios) === null || _e === void 0 ? void 0 : _e.runtimeVersion) !== null && _f !== void 0 ? _f : modifyConfig.runtimeVersion;
130
139
  if (androidRuntime && iosRuntime && androidRuntime === iosRuntime) {
131
- log_1.default.withTick(`Configured runtimeVersion for ${platform_1.appPlatformDisplayNames[generated_1.AppPlatform.Android]} and ${platform_1.appPlatformDisplayNames[generated_1.AppPlatform.Ios]} with "${(_h = (_g = modifyConfig.android) === null || _g === void 0 ? void 0 : _g.runtimeVersion) !== null && _h !== void 0 ? _h : modifyConfig.runtimeVersion}"`);
140
+ log_1.default.withTick(`Configured runtimeVersion for ${platform_1.appPlatformDisplayNames[generated_1.AppPlatform.Android]} and ${platform_1.appPlatformDisplayNames[generated_1.AppPlatform.Ios]} with "${serializeRuntimeVersionToString(androidRuntime)}"`);
132
141
  }
133
142
  else {
134
143
  if (androidRuntime) {
135
- log_1.default.withTick(`Configured runtimeVersion for ${platform_1.appPlatformDisplayNames[generated_1.AppPlatform.Android]} with "${(_k = (_j = modifyConfig.android) === null || _j === void 0 ? void 0 : _j.runtimeVersion) !== null && _k !== void 0 ? _k : modifyConfig.runtimeVersion}"`);
144
+ log_1.default.withTick(`Configured runtimeVersion for ${platform_1.appPlatformDisplayNames[generated_1.AppPlatform.Android]} with "${serializeRuntimeVersionToString(androidRuntime)}"`);
136
145
  }
137
146
  if (iosRuntime) {
138
- log_1.default.withTick(`Configured runtimeVersion for ${platform_1.appPlatformDisplayNames[generated_1.AppPlatform.Ios]} with "${(_m = (_l = modifyConfig.ios) === null || _l === void 0 ? void 0 : _l.runtimeVersion) !== null && _m !== void 0 ? _m : modifyConfig.runtimeVersion}"`);
147
+ log_1.default.withTick(`Configured runtimeVersion for ${platform_1.appPlatformDisplayNames[generated_1.AppPlatform.Ios]} with "${serializeRuntimeVersionToString(iosRuntime)}"`);
139
148
  }
140
149
  }
141
150
  }
@@ -211,14 +220,23 @@ exports.ensureEASUpdateIsConfiguredInEasJsonAsync = ensureEASUpdateIsConfiguredI
211
220
  /**
212
221
  * Make sure EAS Update is fully configured in the current project.
213
222
  * This goes over a checklist and performs the following checks or changes:
214
- * - Enure the `expo-updates` package is currently installed.
223
+ * - Ensure `updates.useClassicUpdates` (SDK 49) is not set in the app config
224
+ * - Ensure the `expo-updates` package is currently installed.
215
225
  * - Ensure `app.json` is configured for EAS Updates
216
226
  * - Sets `runtimeVersion` if not set
217
227
  * - Sets `updates.url` if not set
218
228
  * - Ensure latest changes are reflected in the native config, if any
219
229
  */
220
- async function ensureEASUpdateIsConfiguredAsync(graphqlClient, { exp: expWithoutUpdates, projectId, projectDir, platform, }) {
221
- const hasExpoUpdates = (0, projectUtils_1.isExpoUpdatesInstalledOrAvailable)(projectDir, expWithoutUpdates.sdkVersion);
230
+ async function ensureEASUpdateIsConfiguredAsync(graphqlClient, { exp: expMaybeWithoutUpdates, projectId, projectDir, platform, }) {
231
+ var _a;
232
+ // EAS Update and SDK 49's "useClassicUpdates" option are mutually exclusive
233
+ if ((_a = expMaybeWithoutUpdates.updates) === null || _a === void 0 ? void 0 : _a.useClassicUpdates) {
234
+ expMaybeWithoutUpdates = await ensureUseClassicUpdatesIsRemovedAsync({
235
+ exp: expMaybeWithoutUpdates,
236
+ projectDir,
237
+ });
238
+ }
239
+ const hasExpoUpdates = (0, projectUtils_1.isExpoUpdatesInstalledOrAvailable)(projectDir, expMaybeWithoutUpdates.sdkVersion);
222
240
  const hasExpoUpdatesInDevDependencies = (0, projectUtils_1.isExpoUpdatesInstalledAsDevDependency)(projectDir);
223
241
  if (!hasExpoUpdates && !hasExpoUpdatesInDevDependencies) {
224
242
  await (0, projectUtils_1.installExpoUpdatesAsync)(projectDir, { silent: false });
@@ -234,7 +252,7 @@ async function ensureEASUpdateIsConfiguredAsync(graphqlClient, { exp: expWithout
234
252
  }
235
253
  const workflows = await (0, workflow_1.resolveWorkflowPerPlatformAsync)(projectDir);
236
254
  const { projectChanged, exp: expWithUpdates } = await ensureEASUpdatesIsConfiguredInExpoConfigAsync({
237
- exp: expWithoutUpdates,
255
+ exp: expMaybeWithoutUpdates,
238
256
  projectDir,
239
257
  projectId,
240
258
  platform,
@@ -256,3 +274,31 @@ async function ensureEASUpdateIsConfiguredAsync(graphqlClient, { exp: expWithout
256
274
  }
257
275
  }
258
276
  exports.ensureEASUpdateIsConfiguredAsync = ensureEASUpdateIsConfiguredAsync;
277
+ async function ensureUseClassicUpdatesIsRemovedAsync({ exp: expMaybeWithoutUpdates, projectDir, }) {
278
+ if (!(0, expoConfig_1.isUsingStaticExpoConfig)(projectDir)) {
279
+ throw new Error(`Your app config sets "updates.useClassicUpdates" but EAS Update does not support classic updates. Remove "useClassicUpdates" from your app config and run this command again.`);
280
+ }
281
+ const shouldEditConfig = await (0, prompts_1.confirmAsync)({
282
+ message: `Your app config sets "updates.useClassicUpdates" but EAS Update does not support classic updates. Remove "updates.useClassicUpdates" from your app config?`,
283
+ });
284
+ if (!shouldEditConfig) {
285
+ throw new Error(`Manually remove "updates.useClassicUpdates" from your app config and run this command again.`);
286
+ }
287
+ const editedExpoConfig = mergeExpoConfig(expMaybeWithoutUpdates, {
288
+ updates: { useClassicUpdates: undefined },
289
+ });
290
+ const result = await (0, expoConfig_1.createOrModifyExpoConfigAsync)(projectDir, editedExpoConfig);
291
+ switch (result.type) {
292
+ case 'success':
293
+ log_1.default.withTick(`Removed "updates.useClassicUpdates"`);
294
+ expMaybeWithoutUpdates = editedExpoConfig;
295
+ break;
296
+ case 'warn':
297
+ case 'fail':
298
+ throw new Error(result.message);
299
+ default:
300
+ throw new Error(`Unexpected result type "${result.type}" received when modifying the project config.`);
301
+ }
302
+ return editedExpoConfig;
303
+ }
304
+ exports.ensureUseClassicUpdatesIsRemovedAsync = ensureUseClassicUpdatesIsRemovedAsync;
@@ -1,4 +1,3 @@
1
- export declare function getSessionUsingBrowserAuthFlowAsync(options: {
1
+ export declare function getSessionUsingBrowserAuthFlowAsync({ expoWebsiteUrl, }: {
2
2
  expoWebsiteUrl: string;
3
- serverPort: number;
4
3
  }): Promise<string>;
@@ -2,22 +2,47 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getSessionUsingBrowserAuthFlowAsync = void 0;
4
4
  const tslib_1 = require("tslib");
5
+ const assert_1 = tslib_1.__importDefault(require("assert"));
5
6
  const better_opn_1 = tslib_1.__importDefault(require("better-opn"));
6
7
  const http_1 = tslib_1.__importDefault(require("http"));
7
8
  const querystring_1 = tslib_1.__importDefault(require("querystring"));
8
9
  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.');
10
+ const successBody = `
11
+ <!DOCTYPE html>
12
+ <html lang="en">
13
+ <head>
14
+ <title>Expo SSO Login</title>
15
+ <meta charset="utf-8">
16
+ <style type="text/css">
17
+ html {
18
+ margin: 0;
19
+ padding: 0
13
20
  }
21
+
22
+ body {
23
+ background-color: #fff;
24
+ font-family: Tahoma,Verdana;
25
+ font-size: 16px;
26
+ color: #000;
27
+ max-width: 100%;
28
+ box-sizing: border-box;
29
+ padding: .5rem;
30
+ margin: 1em;
31
+ overflow-wrap: break-word
32
+ }
33
+ </style>
34
+ </head>
35
+ <body>
36
+ SSO login complete. You may now close this tab and return to the command prompt.
37
+ </body>
38
+ </html>`;
39
+ async function getSessionUsingBrowserAuthFlowAsync({ expoWebsiteUrl, }) {
14
40
  const scheme = 'http';
15
41
  const hostname = 'localhost';
16
42
  const path = '/auth/callback';
17
- const redirectUri = `${scheme}://${hostname}:${serverPort}${path}`;
18
- const buildExpoSsoLoginUrl = () => {
43
+ const buildExpoSsoLoginUrl = (port) => {
19
44
  const data = {
20
- app_redirect_uri: redirectUri,
45
+ app_redirect_uri: `${scheme}://${hostname}:${port}${path}`,
21
46
  };
22
47
  const params = querystring_1.default.stringify(data);
23
48
  return `${expoWebsiteUrl}/sso-login?${params}`;
@@ -38,8 +63,8 @@ async function getSessionUsingBrowserAuthFlowAsync(options) {
38
63
  throw new Error('Request missing session_secret search parameter.');
39
64
  }
40
65
  resolve(sessionSecret);
41
- response.writeHead(200, { 'Content-Type': 'text/plain' });
42
- response.write(`Website login has completed. You can now close this tab.`);
66
+ response.writeHead(200, { 'Content-Type': 'text/html' });
67
+ response.write(successBody);
43
68
  response.end();
44
69
  }
45
70
  catch (error) {
@@ -53,8 +78,13 @@ async function getSessionUsingBrowserAuthFlowAsync(options) {
53
78
  }
54
79
  }
55
80
  });
56
- server.listen(serverPort, hostname, () => {
81
+ server.listen(0, hostname, () => {
57
82
  log_1.default.log('Waiting for browser login...');
83
+ const address = server.address();
84
+ (0, assert_1.default)(address !== null && typeof address === 'object', 'Server address and port should be set after listening has begun');
85
+ const port = address.port;
86
+ const authorizeUrl = buildExpoSsoLoginUrl(port);
87
+ (0, better_opn_1.default)(authorizeUrl);
58
88
  });
59
89
  server.on('connection', connection => {
60
90
  connections.add(connection);
@@ -62,8 +92,6 @@ async function getSessionUsingBrowserAuthFlowAsync(options) {
62
92
  connections.delete(connection);
63
93
  });
64
94
  });
65
- const authorizeUrl = buildExpoSsoLoginUrl();
66
- (0, better_opn_1.default)(authorizeUrl);
67
95
  });
68
96
  };
69
97
  return await executeAuthFlow();
@@ -5,11 +5,9 @@ const api_1 = require("../api");
5
5
  const expoSsoLauncher_1 = require("./expoSsoLauncher");
6
6
  const fetchUser_1 = require("./fetchUser");
7
7
  async function fetchSessionSecretAndSsoUserAsync() {
8
- const config = {
8
+ const sessionSecret = await (0, expoSsoLauncher_1.getSessionUsingBrowserAuthFlowAsync)({
9
9
  expoWebsiteUrl: (0, api_1.getExpoWebsiteBaseUrl)(),
10
- serverPort: await (0, api_1.getSsoLocalServerPortAsync)(),
11
- };
12
- const sessionSecret = await (0, expoSsoLauncher_1.getSessionUsingBrowserAuthFlowAsync)(config);
10
+ });
13
11
  const userData = await (0, fetchUser_1.fetchUserAsync)({ sessionSecret });
14
12
  return {
15
13
  sessionSecret,
@@ -1 +1 @@
1
- export default function capitalize(s: string): string;
1
+ export default function capitalizeFirstLetter(s: string): string;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- function capitalize(s) {
4
- return s ? s.charAt(0).toUpperCase() + s.slice(1).toLowerCase() : '';
3
+ function capitalizeFirstLetter(s) {
4
+ return s ? s.charAt(0).toUpperCase() + s.slice(1) : '';
5
5
  }
6
- exports.default = capitalize;
6
+ exports.default = capitalizeFirstLetter;