Skip to content

Commit

Permalink
chore(hadron-ipc): move ipcExpose / ipcHandle to hadron-ipc package (#…
Browse files Browse the repository at this point in the history
…5035)

* chore(hadron-ipc): move ipcExpose / ipcHandle to hadron-ipc package

* chore(hadron-ipc): add tests and better types

* chore(atlas-signin): remove block

* chore(compass): account for browserwindow being null or undefined

* chore(connections, import-export): propagate connectionStorage mock to the import-export plugin; remove hadron-ipc global mock from tests

* chore(compass): update ipcMain mock in autoupdate test
  • Loading branch information
gribnoysup authored Oct 31, 2023
1 parent e30f24b commit d0fe8cf
Show file tree
Hide file tree
Showing 36 changed files with 601 additions and 434 deletions.
6 changes: 4 additions & 2 deletions package-lock.json

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

1 change: 1 addition & 0 deletions packages/atlas-service/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@
"@mongodb-js/oidc-plugin": "^0.3.0",
"compass-preferences-model": "^2.15.3",
"electron": "^25.8.4",
"hadron-ipc": "^3.2.2",
"keytar": "^7.9.0",
"node-fetch": "^2.6.7",
"react": "^17.0.2",
Expand Down
6 changes: 5 additions & 1 deletion packages/atlas-service/src/main.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,11 @@ describe('AtlasServiceMain', function () {
let cloudFeatureRolloutAccess: UserPreferences['cloudFeatureRolloutAccess'];

beforeEach(async function () {
AtlasService['ipcMain'] = { handle: sandbox.stub() };
AtlasService['ipcMain'] = {
handle: sandbox.stub(),
broadcast: sandbox.stub(),
createHandle: sandbox.stub(),
};
AtlasService['fetch'] = mockFetch as any;
AtlasService['createMongoDBOIDCPlugin'] = () => mockOidcPlugin;
AtlasService['atlasUserConfigStore'] =
Expand Down
33 changes: 15 additions & 18 deletions packages/atlas-service/src/main.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ipcMain, shell, app } from 'electron';
import { shell, app } from 'electron';
import { URL, URLSearchParams } from 'url';
import { createHash } from 'crypto';
import type { AuthFlowType, MongoDBOIDCPlugin } from '@mongodb-js/oidc-plugin';
Expand Down Expand Up @@ -28,11 +28,9 @@ import {
validateAIAggregationResponse,
validateAIFeatureEnablementResponse,
} from './util';
import {
broadcast,
ipcExpose,
throwIfAborted,
} from '@mongodb-js/compass-utils';
import { throwIfAborted } from '@mongodb-js/compass-utils';
import type { HadronIpcMain } from 'hadron-ipc';
import { ipcMain } from 'hadron-ipc';
import {
createLoggerAndTelemetry,
mongoLogId,
Expand Down Expand Up @@ -165,7 +163,9 @@ export class AtlasService {

private static atlasUserConfigStore = new AtlasUserConfigStore();

private static ipcMain: Pick<typeof ipcMain, 'handle'> = ipcMain;
private static ipcMain:
| Pick<HadronIpcMain, 'createHandle' | 'handle' | 'broadcast'>
| undefined = ipcMain;

private static config: AtlasServiceConfig;

Expand Down Expand Up @@ -232,10 +232,8 @@ export class AtlasService {
static init(config: AtlasServiceConfig): Promise<void> {
this.config = config;
return (this.initPromise ??= (async () => {
ipcExpose(
'AtlasService',
this,
[
if (this.ipcMain) {
this.ipcMain.createHandle('AtlasService', this, [
'getUserInfo',
'introspect',
'isAuthenticated',
Expand All @@ -244,9 +242,8 @@ export class AtlasService {
'getAggregationFromUserInput',
'getQueryFromUserInput',
'updateAtlasUserConfig',
],
this.ipcMain
);
]);
}
this.attachOidcPluginLoggerEvents();
log.info(
mongoLogId(1_001_000_210),
Expand Down Expand Up @@ -306,19 +303,19 @@ export class AtlasService {
this.oidcPluginLogger.on('mongodb-oidc-plugin:refresh-failed', () => {
this.currentUser = null;
this.oidcPluginLogger.emit('atlas-service-token-refresh-failed');
broadcast('atlas-service-token-refresh-failed');
this.ipcMain?.broadcast('atlas-service-token-refresh-failed');
});
this.oidcPluginLogger.on('mongodb-oidc-plugin:refresh-succeeded', () => {
this.oidcPluginLogger.emit('atlas-service-token-refreshed');
broadcast('atlas-service-token-refreshed');
this.ipcMain?.broadcast('atlas-service-token-refreshed');
});
this.oidcPluginLogger.on('atlas-service-signed-out', () => {
broadcast('atlas-service-signed-out');
this.ipcMain?.broadcast('atlas-service-signed-out');
});
this.oidcPluginLogger.on(
'atlas-service-user-config-changed',
(newConfig) => {
broadcast('atlas-service-user-config-changed', newConfig);
this.ipcMain?.broadcast('atlas-service-user-config-changed', newConfig);
}
);
}
Expand Down
40 changes: 30 additions & 10 deletions packages/atlas-service/src/renderer.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { EventEmitter } from 'events';
import { ipcRenderer } from 'electron';
import { ipcInvoke } from '@mongodb-js/compass-utils';
import { ipcRenderer } from 'hadron-ipc';
import type { AtlasService as AtlasServiceMain } from './main';
import {
disableAIFeature,
Expand All @@ -26,7 +25,7 @@ type AtlasServiceEvents = {
export class AtlasService {
private emitter = new EventEmitter();

private ipc = ipcInvoke<
private _ipc = ipcRenderer?.createInvoke<
typeof AtlasServiceMain,
| 'getUserInfo'
| 'introspect'
Expand All @@ -47,13 +46,34 @@ export class AtlasService {
'updateAtlasUserConfig',
]);

getUserInfo = this.ipc.getUserInfo;
introspect = this.ipc.introspect;
isAuthenticated = this.ipc.isAuthenticated;
getAggregationFromUserInput = this.ipc.getAggregationFromUserInput;
getQueryFromUserInput = this.ipc.getQueryFromUserInput;
signOut = this.ipc.signOut;
updateAtlasUserConfig = this.ipc.updateAtlasUserConfig;
private get ipc() {
if (!this._ipc) {
throw new Error('IPC not available');
}
return this._ipc;
}

get getUserInfo() {
return this.ipc.getUserInfo;
}
get introspect() {
return this.ipc.introspect;
}
get isAuthenticated() {
return this.ipc.isAuthenticated;
}
get getAggregationFromUserInput() {
return this.ipc.getAggregationFromUserInput;
}
get getQueryFromUserInput() {
return this.ipc.getQueryFromUserInput;
}
get signOut() {
return this.ipc.signOut;
}
get updateAtlasUserConfig() {
return this.ipc.updateAtlasUserConfig;
}

on<T extends keyof AtlasServiceEvents>(
evt: T,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ import { SelectTable } from './select-table';
import type { ImportExportResult } from '../hooks/common';
import { useOpenModalThroughIpc } from '../hooks/common';
import { useExportConnections } from '../hooks/use-export';
import type { ConnectionInfo } from '@mongodb-js/connection-storage/renderer';
import type {
ConnectionInfo,
ConnectionStorage,
} from '@mongodb-js/connection-storage/renderer';
import { usePreference } from 'compass-preferences-model';

const TOAST_TIMEOUT_MS = 5000;
Expand All @@ -30,12 +33,14 @@ export function ExportConnectionsModal({
favoriteConnections,
afterExport,
trackingProps,
connectionStorage,
}: {
open: boolean;
setOpen: (newOpen: boolean) => void;
favoriteConnections: Pick<ConnectionInfo, 'favorite' | 'id'>[];
afterExport?: () => void;
trackingProps?: Record<string, unknown>;
connectionStorage?: typeof ConnectionStorage;
}): React.ReactElement {
const { openToast } = useToast('compass-connection-import-export');
const finish = useCallback(
Expand Down Expand Up @@ -75,12 +80,15 @@ export function ExportConnectionsModal({
removeSecrets,
passphrase,
},
} = useExportConnections({
finish,
open,
favoriteConnections,
trackingProps,
});
} = useExportConnections(
{
finish,
open,
favoriteConnections,
trackingProps,
},
connectionStorage?.exportConnections.bind(connectionStorage)
);

return (
<FormModal
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@ import { SelectTable } from './select-table';
import type { ImportExportResult } from '../hooks/common';
import { useOpenModalThroughIpc } from '../hooks/common';
import { useImportConnections } from '../hooks/use-import';
import type { ConnectionInfo } from '@mongodb-js/connection-storage/renderer';
import type {
ConnectionInfo,
ConnectionStorage,
} from '@mongodb-js/connection-storage/renderer';

const TOAST_TIMEOUT_MS = 5000;

Expand All @@ -35,12 +38,14 @@ export function ImportConnectionsModal({
favoriteConnections,
afterImport,
trackingProps,
connectionStorage,
}: {
open: boolean;
setOpen: (newOpen: boolean) => void;
favoriteConnections: Pick<ConnectionInfo, 'favorite' | 'id'>[];
afterImport?: () => void;
trackingProps?: Record<string, unknown>;
connectionStorage?: typeof ConnectionStorage;
}): React.ReactElement {
const { openToast } = useToast('compass-connection-import-export');
const finish = useCallback(
Expand Down Expand Up @@ -75,12 +80,16 @@ export function ImportConnectionsModal({
filename,
passphrase,
},
} = useImportConnections({
finish,
open,
favoriteConnections,
trackingProps,
});
} = useImportConnections(
{
finish,
open,
favoriteConnections,
trackingProps,
},
connectionStorage?.importConnections.bind(connectionStorage),
connectionStorage?.deserializeConnections.bind(connectionStorage)
);

const [displayConnectionList, hasSelectedDuplicates] = useMemo(() => {
return [
Expand Down
18 changes: 5 additions & 13 deletions packages/compass-connection-import-export/src/hooks/common.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import type { Dispatch, SetStateAction } from 'react';
import { useEffect } from 'react';
import { useCallback } from 'react';
import type { HadronIpcRenderer } from 'hadron-ipc';
import { ipcRenderer } from 'hadron-ipc';

export type ImportExportResult = 'canceled' | 'succeeded';

Expand Down Expand Up @@ -54,26 +56,16 @@ export function useImportExportConnectionsCommon<S>(
return { onCancel, onChangeConnectionList, onChangePassphrase };
}

// eslint-disable-next-line @typescript-eslint/consistent-type-imports
let ipc_: import('hadron-ipc').HadronIpcRenderer | Record<string, never>;
export function useOpenModalThroughIpc(
open: boolean,
setOpen: (newValue: boolean) => void,
ipcEvent: string,
ipcForTesting: typeof ipc_ | undefined = undefined
ipcForTesting: HadronIpcRenderer | undefined = undefined
): void {
try {
// eslint-disable-next-line @typescript-eslint/no-var-requires
ipc_ ??= require('hadron-ipc').ipcRenderer;
} catch (err) {
ipc_ ??= {};
// eslint-disable-next-line no-console
console.warn('could not load hadron-ipc', err);
}
const ipc = ipcForTesting ?? ipc_;
const ipc = ipcForTesting ?? ipcRenderer;

useEffect(() => {
if (ipc.on && !open) {
if (ipc?.on && !open) {
const listener = () => {
setOpen(true);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ export function useImportConnections(
favoriteConnections: Pick<ConnectionInfo, 'favorite' | 'id'>[];
open: boolean;
trackingProps?: Record<string, unknown>;
connectionStorage?: typeof ConnectionStorage;
},
importConnections = ConnectionStorage.importConnections.bind(
ConnectionStorage
Expand Down
7 changes: 1 addition & 6 deletions packages/compass-connections/.mocharc.js
Original file line number Diff line number Diff line change
@@ -1,6 +1 @@
const base = require('@mongodb-js/mocha-config-compass/compass-plugin');

module.exports = {
...base,
require: base.require.concat(['./test/mocha-plugins.ts']),
};
module.exports = require('@mongodb-js/mocha-config-compass/compass-plugin');
14 changes: 14 additions & 0 deletions packages/compass-connections/src/components/connections.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import sinon from 'sinon';

import Connections from './connections';
import { ToastArea } from '@mongodb-js/compass-components';
import preferencesAccess from 'compass-preferences-model';

function getMockConnectionStorage(mockConnections: ConnectionInfo[]) {
return {
Expand All @@ -29,6 +30,9 @@ function getMockConnectionStorage(mockConnections: ConnectionInfo[]) {
delete: () => Promise.resolve(),
load: (id: string) =>
Promise.resolve(mockConnections.find((conn) => conn.id === id)),
importConnections: () => Promise.resolve([]),
exportConnections: () => Promise.resolve('{}'),
deserializeConnections: () => Promise.resolve([]),
} as unknown as ConnectionStorage;
}

Expand All @@ -53,8 +57,18 @@ async function loadSavedConnectionAndConnect(connectionInfo: ConnectionInfo) {
}

describe('Connections Component', function () {
let persistOIDCTokens: boolean | undefined;
let onConnectedSpy: sinon.SinonSpy;

before(async function () {
persistOIDCTokens = preferencesAccess.getPreferences().persistOIDCTokens;
await preferencesAccess.savePreferences({ persistOIDCTokens: false });
});

after(async function () {
await preferencesAccess.savePreferences({ persistOIDCTokens });
});

beforeEach(function () {
onConnectedSpy = sinon.spy();
});
Expand Down
Loading

0 comments on commit d0fe8cf

Please sign in to comment.