Skip to content

Commit

Permalink
chore(generative-ai): move ai sign in modal to gen ai package from at…
Browse files Browse the repository at this point in the history
…las-service COMPASS-8459 (#6448)
  • Loading branch information
Anemy authored Nov 8, 2024
1 parent fac4f9d commit 06999d8
Show file tree
Hide file tree
Showing 33 changed files with 657 additions and 232 deletions.
12 changes: 9 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion packages/atlas-service/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,6 @@
"hadron-ipc": "^3.2.25",
"lodash": "^4.17.21",
"react": "^17.0.2",
"react-redux": "^8.1.3",
"redux": "^4.2.1",
"redux-thunk": "^2.4.2"
}
Expand Down
2 changes: 1 addition & 1 deletion packages/atlas-service/src/atlas-auth-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import type { AtlasUserInfo } from './util';
export type ArgsWithSignal<T = Record<string, unknown>> = T & {
signal?: AbortSignal;
};
export type SignInPrompt = 'none' | 'ai-promo-modal';
export type SignInPrompt = 'none';

type AtlasAuthServiceEvents = {
'signed-in': [];
Expand Down
7 changes: 1 addition & 6 deletions packages/atlas-service/src/compass-atlas-auth-service.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
import { ipcRenderer } from 'hadron-ipc';
import type { CompassAuthService as AtlasServiceMain } from './main';
import {
signInWithModalPrompt,
signInWithoutPrompt,
} from './store/atlas-signin-reducer';
import { signInWithoutPrompt } from './store/atlas-signin-reducer';
import { getStore } from './store/atlas-signin-store';
import { AtlasAuthService } from './atlas-auth-service';
import type { ArgsWithSignal, SignInPrompt } from './atlas-auth-service';
Expand Down Expand Up @@ -46,8 +43,6 @@ export class CompassAtlasAuthService extends AtlasAuthService {
switch (promptType) {
case 'none':
return getStore().dispatch(signInWithoutPrompt({ signal }));
case 'ai-promo-modal':
return getStore().dispatch(signInWithModalPrompt({ signal }));
default:
return this.ipc.signIn({ signal });
}
Expand Down
3 changes: 1 addition & 2 deletions packages/atlas-service/src/renderer.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import { registerHadronPlugin } from 'hadron-app-registry';
import { activatePlugin } from './store/atlas-signin-store';
import { atlasAuthServiceLocator } from './provider';
import { AtlasSignIn } from './components';

export const AtlasAuthPlugin = registerHadronPlugin(
{
name: 'AtlasAuth',
component: AtlasSignIn,
component: () => null,
activate: activatePlugin,
},
{
Expand Down
99 changes: 1 addition & 98 deletions packages/atlas-service/src/store/atlas-signin-reducer.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import {
cancelSignIn,
attemptId,
AttemptStateMap,
signInWithModalPrompt,
closeSignInModal,
signInWithoutPrompt,
} from './atlas-signin-reducer';
import { expect } from 'chai';
Expand Down Expand Up @@ -176,7 +174,7 @@ describe('atlasSignInReducer', function () {
atlasAuthService: mockAtlasService as any,
});

void store.dispatch(signInWithModalPrompt()).catch(() => {});
void store.dispatch(signInWithoutPrompt()).catch(() => {});

await Promise.all([
store.dispatch(signIn()),
Expand All @@ -186,101 +184,6 @@ describe('atlasSignInReducer', function () {
});
});

describe('signInWithModalPrompt', function () {
it('should resolve when user finishes sign in with prompt flow', async function () {
const mockAtlasService = {
isAuthenticated: sandbox.stub().resolves(false),
signIn: sandbox.stub().resolves({ sub: '1234' }),
getUserInfo: sandbox.stub().resolves({ sub: '1234' }),
emit: sandbox.stub(),
};
const store = configureStore({
atlasAuthService: mockAtlasService as any,
});

const signInPromise = store.dispatch(signInWithModalPrompt());
await store.dispatch(signIn());
await signInPromise;

expect(store.getState()).to.have.property('state', 'success');
});

it('should reject if sign in flow fails', async function () {
const mockAtlasService = {
isAuthenticated: sandbox.stub().resolves(false),
signIn: sandbox.stub().rejects(new Error('Whoops!')),
getUserInfo: sandbox.stub().resolves({ sub: '1234' }),
emit: sandbox.stub(),
};
const store = configureStore({
atlasAuthService: mockAtlasService as any,
});

const signInPromise = store.dispatch(signInWithModalPrompt());
await store.dispatch(signIn());

try {
await signInPromise;
throw new Error('Expected signInPromise to throw');
} catch (err) {
expect(err).to.have.property('message', 'Whoops!');
}

expect(store.getState()).to.have.property('state', 'error');
});

it('should reject if user dismissed the modal', async function () {
const mockAtlasService = {
isAuthenticated: sandbox.stub().resolves(false),
signIn: sandbox.stub().resolves({ sub: '1234' }),
getUserInfo: sandbox.stub().resolves({ sub: '1234' }),
emit: sandbox.stub(),
};
const store = configureStore({
atlasAuthService: mockAtlasService as any,
});

const signInPromise = store.dispatch(signInWithModalPrompt());
store.dispatch(closeSignInModal());

try {
await signInPromise;
throw new Error('Expected signInPromise to throw');
} catch (err) {
expect(err).to.have.property('message', 'This operation was aborted');
}

expect(store.getState()).to.have.property('state', 'canceled');
});

it('should reject if provided signal was aborted', async function () {
const mockAtlasService = {
isAuthenticated: sandbox.stub().resolves(false),
signIn: sandbox.stub().resolves({ sub: '1234' }),
getUserInfo: sandbox.stub().resolves({ sub: '1234' }),
emit: sandbox.stub(),
};
const store = configureStore({
atlasAuthService: mockAtlasService as any,
});

const c = new AbortController();
const signInPromise = store.dispatch(
signInWithModalPrompt({ signal: c.signal })
);
c.abort(new Error('Aborted from outside'));

try {
await signInPromise;
throw new Error('Expected signInPromise to throw');
} catch (err) {
expect(err).to.have.property('message', 'Aborted from outside');
}

expect(store.getState()).to.have.property('state', 'canceled');
});
});

describe('signInWithoutPrompt', function () {
it('should resolve when sign in flow finishes', async function () {
const mockAtlasService = {
Expand Down
67 changes: 1 addition & 66 deletions packages/atlas-service/src/store/atlas-signin-reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ export function isAction<A extends AnyAction>(

export type AtlasSignInState = {
error: string | null;
isModalOpen: boolean;
// For managing attempt state that doesn't belong in the store
currentAttemptId: number | null;
} & (
Expand All @@ -37,8 +36,6 @@ export type AtlasSignInThunkAction<
> = ThunkAction<R, AtlasSignInState, { atlasAuthService: AtlasAuthService }, A>;

export const enum AtlasSignInActions {
OpenSignInModal = 'atlas-service/atlas-signin/OpenSignInModal',
CloseSignInModal = 'atlas-service/atlas-signin/CloseSignInModal',
RestoringStart = 'atlas-service/atlas-signin/StartRestoring',
RestoringFailed = 'atlas-service/atlas-signin/RestoringFailed',
RestoringSuccess = 'atlas-service/atlas-signin/RestoringSuccess',
Expand All @@ -52,14 +49,6 @@ export const enum AtlasSignInActions {
SignedOut = 'atlas-service/atlas-signin/SignedOut',
}

export type AtlasSignInOpenModalAction = {
type: AtlasSignInActions.OpenSignInModal;
};

export type AtlasSignInCloseModalAction = {
type: AtlasSignInActions.CloseSignInModal;
};

export type AtlasSignInRestoringStartAction = {
type: AtlasSignInActions.RestoringStart;
};
Expand Down Expand Up @@ -250,24 +239,6 @@ const reducer: Reducer<AtlasSignInState, Action> = (
return { ...INITIAL_STATE, state: 'canceled' };
}

if (
isAction<AtlasSignInOpenModalAction>(
action,
AtlasSignInActions.OpenSignInModal
)
) {
return { ...state, isModalOpen: true };
}

if (
isAction<AtlasSignInCloseModalAction>(
action,
AtlasSignInActions.CloseSignInModal
)
) {
return { ...state, isModalOpen: false };
}

if (
isAction<AtlasSignInTokenRefreshFailedAction>(
action,
Expand Down Expand Up @@ -337,29 +308,6 @@ const startAttempt = (fn: () => void): AtlasSignInThunkAction<AttemptState> => {
};
};

export const signInWithModalPrompt = ({
signal,
}: { signal?: AbortSignal } = {}): AtlasSignInThunkAction<
Promise<AtlasUserInfo>
> => {
return async (dispatch, getState) => {
// Nothing to do if we already signed in
const { state, userInfo } = getState();
if (state === 'success') {
return userInfo;
}
const attempt = dispatch(
startAttempt(() => {
dispatch(openSignInModal());
})
);
signal?.addEventListener('abort', () => {
dispatch(closeSignInModal(signal.reason));
});
return attempt.promise;
};
};

export const signInWithoutPrompt = ({
signal,
}: { signal?: AbortSignal } = {}): AtlasSignInThunkAction<
Expand All @@ -383,12 +331,8 @@ export const signInWithoutPrompt = ({
};
};

export const openSignInModal = () => {
return { type: AtlasSignInActions.OpenSignInModal };
};

/**
* Sign in from the opt in window
* Sign into Atlas. To be called when the user isn't signed in yet.
*/
export const signIn = (): AtlasSignInThunkAction<Promise<void>> => {
return async (dispatch, getState, { atlasAuthService }) => {
Expand Down Expand Up @@ -434,15 +378,6 @@ export const signIn = (): AtlasSignInThunkAction<Promise<void>> => {
};
};

export const closeSignInModal = (
reason?: any
): AtlasSignInThunkAction<void> => {
return (dispatch) => {
dispatch(cancelSignIn(reason));
dispatch({ type: AtlasSignInActions.CloseSignInModal });
};
};

export const cancelSignIn = (reason?: any): AtlasSignInThunkAction<void> => {
return (dispatch, getState) => {
// Can't cancel sign in after the flow was finished indicated by current
Expand Down
2 changes: 0 additions & 2 deletions packages/compass-aggregations/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import {
} from '@mongodb-js/compass-app-stores/provider';
import { workspacesServiceLocator } from '@mongodb-js/compass-workspaces/provider';
import { preferencesLocator } from 'compass-preferences-model/provider';
import { atlasAuthServiceLocator } from '@mongodb-js/atlas-service/provider';
import { atlasAiServiceLocator } from '@mongodb-js/compass-generative-ai/provider';
import { pipelineStorageLocator } from '@mongodb-js/my-queries-storage/provider';
import { connectionRepositoryAccessLocator } from '@mongodb-js/compass-connections/provider';
Expand All @@ -49,7 +48,6 @@ const CompassAggregationsHadronPlugin = registerHadronPlugin(
preferences: preferencesLocator,
logger: createLoggerLocator('COMPASS-AGGREGATIONS-UI'),
track: telemetryLocator,
atlasAuthService: atlasAuthServiceLocator,
atlasAiService: atlasAiServiceLocator,
pipelineStorage: pipelineStorageLocator,
connectionInfoRef: connectionInfoRefLocator,
Expand Down
2 changes: 0 additions & 2 deletions packages/compass-aggregations/src/modules/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ import type { PreferencesAccess } from 'compass-preferences-model';
import type { Logger } from '@mongodb-js/compass-logging/provider';
import type AppRegistry from 'hadron-app-registry';
import type { AtlasAiService } from '@mongodb-js/compass-generative-ai/provider';
import type { AtlasAuthService } from '@mongodb-js/atlas-service/provider';
import type { MongoDBInstance } from 'mongodb-instance-model';
import type { DataService } from '../modules/data-service';
import type {
Expand Down Expand Up @@ -100,7 +99,6 @@ export type PipelineBuilderExtraArgs = {
localAppRegistry: AppRegistry;
pipelineBuilder: PipelineBuilder;
pipelineStorage: PipelineStorage;
atlasAuthService: AtlasAuthService;
workspaces: WorkspacesService;
preferences: PreferencesAccess;
logger: Logger;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -447,10 +447,10 @@ export const resetIsAggregationGeneratedFromQuery =
};

export const showInput = (): PipelineBuilderThunkAction<Promise<void>> => {
return async (dispatch, _getState, { atlasAuthService }) => {
return async (dispatch, _getState, { atlasAiService }) => {
try {
if (process.env.COMPASS_E2E_SKIP_ATLAS_SIGNIN !== 'true') {
await atlasAuthService.signIn({ promptType: 'ai-promo-modal' });
await atlasAiService.ensureAiFeatureAccess();
}
dispatch({
type: AIPipelineActionTypes.ShowInput,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,6 @@ function createStore({
thunk.withExtraArgument({
globalAppRegistry: new AppRegistry(),
localAppRegistry: new AppRegistry(),
atlasAuthService: {} as any,
atlasAiService: {} as any,
pipelineBuilder,
pipelineStorage: new CompassPipelineStorage(),
Expand Down
Loading

0 comments on commit 06999d8

Please sign in to comment.