Skip to content

Commit

Permalink
[eas-cli] Create dynamic logged in context field and clean up erroneo…
Browse files Browse the repository at this point in the history
…us SessionManager context field uses (#2648)
  • Loading branch information
wschurman authored Oct 23, 2024
1 parent 3139124 commit a212662
Show file tree
Hide file tree
Showing 12 changed files with 78 additions and 26 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ This is the log of notable changes to EAS CLI and related packages.

### 🧹 Chores

- Create dynamic logged in context field and clean up erroneous SessionManager context field uses. ([#2648](https://github.com/expo/eas-cli/pull/2648) by [@wschurman](https://github.com/wschurman))

## [12.6.0](https://github.com/expo/eas-cli/releases/tag/v12.6.0) - 2024-10-21

### 🎉 New features
Expand Down
9 changes: 9 additions & 0 deletions packages/eas-cli/src/commandUtils/EasCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import nullthrows from 'nullthrows';

import AnalyticsContextField from './context/AnalyticsContextField';
import ContextField from './context/ContextField';
import DynamicLoggedInContextField from './context/DynamicLoggedInContextField';
import {
DynamicPrivateProjectConfigContextField,
DynamicPublicProjectConfigContextField,
Expand Down Expand Up @@ -61,8 +62,16 @@ export default abstract class EasCommand extends Command {
MaybeLoggedIn: {
maybeLoggedIn: new MaybeLoggedInContextField(),
},
/**
* Specify this context if the logged-in requirement is only necessary in a particular execution of the command.
*/
DynamicLoggedIn: {
// eslint-disable-next-line async-protect/async-suffix
getDynamicLoggedInAsync: new DynamicLoggedInContextField(),
},
/**
* Specify this context requirement if the command needs to mutate the user session.
* @deprecated Should not be used outside of session management commands, which currently only includes `login` and `logout`.
*/
SessionManagment: {
sessionManager: new SessionManagementContextField(),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import ContextField, { ContextOptions } from './ContextField';
import { ExpoGraphqlClient, createGraphqlClient } from './contextUtils/createGraphqlClient';
import { LoggedInAuthenticationInfo } from '../../user/SessionManager';
import { Actor } from '../../user/User';
import FeatureGateEnvOverrides from '../gating/FeatureGateEnvOverrides';
import FeatureGating from '../gating/FeatureGating';

export type DynamicLoggedInContextFn = () => Promise<{
actor: Actor;
featureGating: FeatureGating;
graphqlClient: ExpoGraphqlClient;
authenticationInfo: LoggedInAuthenticationInfo;
}>;

export default class DynamicLoggedInContextField extends ContextField<DynamicLoggedInContextFn> {
async getValueAsync({
nonInteractive,
sessionManager,
}: ContextOptions): Promise<DynamicLoggedInContextFn> {
return async () => {
const { actor, authenticationInfo } = await sessionManager.ensureLoggedInAsync({
nonInteractive,
});
const featureGateServerValues: { [key: string]: boolean } = actor?.featureGates ?? {};

const graphqlClient = createGraphqlClient(authenticationInfo);

return {
actor,
featureGating: new FeatureGating(featureGateServerValues, new FeatureGateEnvOverrides()),
graphqlClient,
authenticationInfo,
};
};
}
}
18 changes: 11 additions & 7 deletions packages/eas-cli/src/commandUtils/context/LoggedInContextField.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
import ContextField, { ContextOptions } from './ContextField';
import { ExpoGraphqlClient, createGraphqlClient } from './contextUtils/createGraphqlClient';
import { LoggedInAuthenticationInfo } from '../../user/SessionManager';
import { Actor } from '../../user/User';
import FeatureGateEnvOverrides from '../gating/FeatureGateEnvOverrides';
import FeatureGating from '../gating/FeatureGating';

export default class LoggedInContextField extends ContextField<{
type LoggedInContextType = {
actor: Actor;
featureGating: FeatureGating;
graphqlClient: ExpoGraphqlClient;
}> {
async getValueAsync({ nonInteractive, sessionManager }: ContextOptions): Promise<{
actor: Actor;
featureGating: FeatureGating;
graphqlClient: ExpoGraphqlClient;
}> {
authenticationInfo: LoggedInAuthenticationInfo;
};

export default class LoggedInContextField extends ContextField<LoggedInContextType> {
async getValueAsync({
nonInteractive,
sessionManager,
}: ContextOptions): Promise<LoggedInContextType> {
const { actor, authenticationInfo } = await sessionManager.ensureLoggedInAsync({
nonInteractive,
});
Expand All @@ -25,6 +28,7 @@ export default class LoggedInContextField extends ContextField<{
actor,
featureGating: new FeatureGating(featureGateServerValues, new FeatureGateEnvOverrides()),
graphqlClient,
authenticationInfo,
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,18 @@ import { Actor } from '../../user/User';
import FeatureGateEnvOverrides from '../gating/FeatureGateEnvOverrides';
import FeatureGating from '../gating/FeatureGating';

export default class MaybeLoggedInContextField extends ContextField<{
type MaybeLoggedInContextType = {
actor: Actor | null;
featureGating: FeatureGating;
graphqlClient: ExpoGraphqlClient;
}> {
async getValueAsync({ sessionManager }: ContextOptions): Promise<{
actor: Actor | null;
featureGating: FeatureGating;
graphqlClient: ExpoGraphqlClient;
}> {
authenticationInfo: {
accessToken: string | null;
sessionSecret: string | null;
};
};

export default class MaybeLoggedInContextField extends ContextField<MaybeLoggedInContextType> {
async getValueAsync({ sessionManager }: ContextOptions): Promise<MaybeLoggedInContextType> {
const authenticationInfo = {
accessToken: sessionManager.getAccessToken(),
sessionSecret: sessionManager.getSessionSecret(),
Expand All @@ -27,6 +29,7 @@ export default class MaybeLoggedInContextField extends ContextField<{
actor: actor ?? null,
featureGating: new FeatureGating(featureGateServerValues, new FeatureGateEnvOverrides()),
graphqlClient,
authenticationInfo,
};
}
}
6 changes: 2 additions & 4 deletions packages/eas-cli/src/commands/account/view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,14 @@ export default class AccountView extends EasCommand {

static override contextDefinition = {
...this.ContextOptions.MaybeLoggedIn,
...this.ContextOptions.SessionManagment,
};

async runAsync(): Promise<void> {
const {
maybeLoggedIn: { actor },
sessionManager,
maybeLoggedIn: { actor, authenticationInfo },
} = await this.getContextAsync(AccountView, { nonInteractive: true });
if (actor) {
const loggedInAs = sessionManager.getAccessToken()
const loggedInAs = authenticationInfo.accessToken
? `${getActorDisplayName(actor)} (authenticated using EXPO_TOKEN)`
: getActorDisplayName(actor);
Log.log(chalk.green(loggedInAs));
Expand Down
10 changes: 3 additions & 7 deletions packages/eas-cli/src/commands/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import chalk from 'chalk';

import { evaluateConfigWithEnvVarsAsync } from '../build/evaluateConfigWithEnvVarsAsync';
import EasCommand from '../commandUtils/EasCommand';
import { createGraphqlClient } from '../commandUtils/context/contextUtils/createGraphqlClient';
import { EasNonInteractiveAndJsonFlags } from '../commandUtils/flags';
import { toAppPlatform } from '../graphql/types/AppPlatform';
import Log from '../log';
Expand Down Expand Up @@ -35,7 +34,7 @@ export default class Config extends EasCommand {
static override contextDefinition = {
...this.ContextOptions.DynamicProjectConfig,
...this.ContextOptions.ProjectDir,
...this.ContextOptions.SessionManagment,
...this.ContextOptions.DynamicLoggedIn,
};

async runAsync(): Promise<void> {
Expand All @@ -48,7 +47,7 @@ export default class Config extends EasCommand {
profile: maybeProfile,
'non-interactive': nonInteractive,
} = flags;
const { getDynamicPublicProjectConfigAsync, projectDir, sessionManager } =
const { getDynamicPublicProjectConfigAsync, projectDir, getDynamicLoggedInAsync } =
await this.getContextAsync(Config, {
nonInteractive,
});
Expand Down Expand Up @@ -88,10 +87,7 @@ export default class Config extends EasCommand {
Log.log(JSON.stringify(profile, null, 2));
}
} else {
const { authenticationInfo } = await sessionManager.ensureLoggedInAsync({
nonInteractive,
});
const graphqlClient = createGraphqlClient(authenticationInfo);
const { graphqlClient } = await getDynamicLoggedInAsync();
const { exp: appConfig } = await evaluateConfigWithEnvVarsAsync({
buildProfile: profile,
buildProfileName: profileName,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ function mockTestProject(options: {
actor: jester,
featureGating: new FeatureGating({}, new FeatureGateEnvOverrides()),
graphqlClient,
authenticationInfo: { accessToken: null, sessionSecret: '1234' },
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,7 @@ function mockTestProject({
actor: jester,
featureGating: new FeatureGating({}, new FeatureGateEnvOverrides()),
graphqlClient,
authenticationInfo: { accessToken: null, sessionSecret: '1234' },
});
jest
.spyOn(VcsClientContextField.prototype, 'getValueAsync')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,7 @@ function mockTestProject({
actor: jester,
featureGating: new FeatureGating({}, new FeatureGateEnvOverrides()),
graphqlClient,
authenticationInfo: { accessToken: null, sessionSecret: '1234' },
});

jest.mocked(AppQuery.byIdAsync).mockResolvedValue({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,7 @@ function mockTestProject({
actor: jester,
featureGating: new FeatureGating({}, new FeatureGateEnvOverrides()),
graphqlClient,
authenticationInfo: { accessToken: null, sessionSecret: '1234' },
});
jest
.spyOn(VcsClientContextField.prototype, 'getValueAsync')
Expand Down
2 changes: 1 addition & 1 deletion packages/eas-cli/src/user/SessionManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ type SecondFactorDevice = {
is_primary: boolean;
};

type LoggedInAuthenticationInfo =
export type LoggedInAuthenticationInfo =
| {
accessToken: string;
sessionSecret: null;
Expand Down

0 comments on commit a212662

Please sign in to comment.