Skip to content

Commit 5444b83

Browse files
authored
chore(hadron-app-registry): make serviceLocator stricter to limit the potential misuse (#5535)
* chore(hadron-app-registry): make serviceLocator stricter to limit the potential misuse * chore(app-registry): reset the inProgress flag in finally to make sure that runtime check state is correct when it's done running even if it throws
1 parent 0581c27 commit 5444b83

File tree

24 files changed

+310
-129
lines changed

24 files changed

+310
-129
lines changed

package-lock.json

Lines changed: 17 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/atlas-service/src/provider.tsx

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,36 @@ import type { AtlasAuthService } from './atlas-auth-service';
33
import { AtlasService, type AtlasServiceOptions } from './atlas-service';
44
import { preferencesLocator } from 'compass-preferences-model/provider';
55
import { useLoggerAndTelemetry } from '@mongodb-js/compass-logging/provider';
6+
import {
7+
createServiceLocator,
8+
createServiceProvider,
9+
} from 'hadron-app-registry';
610

711
const AtlasAuthServiceContext = createContext<AtlasAuthService | null>(null);
12+
813
export const AtlasAuthServiceProvider = AtlasAuthServiceContext.Provider;
9-
function useAtlasAuthServiceLocator(): AtlasAuthService {
14+
15+
function useAtlasAuthServiceContext(): AtlasAuthService {
1016
const service = useContext(AtlasAuthServiceContext);
1117
if (!service) {
1218
throw new Error('No AtlasAuthService available in this context');
1319
}
1420
return service;
1521
}
16-
export const atlasAuthServiceLocator = useAtlasAuthServiceLocator;
22+
23+
export const atlasAuthServiceLocator = createServiceLocator(
24+
useAtlasAuthServiceContext,
25+
'atlasAuthServiceLocator'
26+
);
1727

1828
const AtlasServiceContext = createContext<AtlasService | null>(null);
29+
1930
export const AtlasServiceProvider: React.FC<{
2031
options?: AtlasServiceOptions;
21-
}> = ({ options, children }) => {
32+
}> = createServiceProvider(function AtlasServiceProvider({
33+
options,
34+
children,
35+
}) {
2236
const logger = useLoggerAndTelemetry('ATLAS-SERVICE');
2337
const preferences = preferencesLocator();
2438
const authService = atlasAuthServiceLocator();
@@ -32,15 +46,20 @@ export const AtlasServiceProvider: React.FC<{
3246
{children}
3347
</AtlasServiceContext.Provider>
3448
);
35-
};
36-
function useAtlasServiceLocator(): AtlasService {
49+
});
50+
51+
function useAtlasServiceContext(): AtlasService {
3752
const service = useContext(AtlasServiceContext);
3853
if (!service) {
3954
throw new Error('No AtlasService available in this context');
4055
}
4156
return service;
4257
}
43-
export const atlasServiceLocator = useAtlasServiceLocator;
58+
59+
export const atlasServiceLocator = createServiceLocator(
60+
useAtlasServiceContext,
61+
'atlasServiceLocator'
62+
);
4463

4564
export { AtlasAuthService } from './atlas-auth-service';
4665
export type { AtlasService } from './atlas-service';
Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
1+
import { createServiceLocator } from 'hadron-app-registry';
12
import type { MongoDBInstance } from 'mongodb-instance-model';
23
import { createContext, useContext } from 'react';
34

45
export const InstanceContext = createContext<MongoDBInstance | null>(null);
56

67
export const MongoDBInstanceProvider = InstanceContext.Provider;
78

8-
export const mongoDBInstanceLocator = (): MongoDBInstance => {
9-
const instance = useContext(InstanceContext);
10-
if (!instance) {
11-
throw new Error('No MongoDBInstance available in this context');
9+
export const mongoDBInstanceLocator = createServiceLocator(
10+
function mongoDBInstanceLocator(): MongoDBInstance {
11+
const instance = useContext(InstanceContext);
12+
if (!instance) {
13+
throw new Error('No MongoDBInstance available in this context');
14+
}
15+
return instance;
1216
}
13-
return instance;
14-
};
17+
);
1518

1619
export type { MongoDBInstance };

packages/compass-connections/src/components/connections.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import {
1515
import { useLoggerAndTelemetry } from '@mongodb-js/compass-logging/provider';
1616
import ConnectionForm from '@mongodb-js/connection-form';
1717
import { type ConnectionInfo } from '@mongodb-js/connection-storage/renderer';
18-
import { connectionStorageLocator } from '@mongodb-js/connection-storage/provider';
18+
import { useConnectionStorageContext } from '@mongodb-js/connection-storage/provider';
1919
import type AppRegistry from 'hadron-app-registry';
2020
import type { DataService } from 'mongodb-data-service';
2121
import { connect } from 'mongodb-data-service';
@@ -102,8 +102,10 @@ function Connections({
102102
connectFn?: ConnectFn;
103103
}): React.ReactElement {
104104
const { log, mongoLogId } = useLoggerAndTelemetry('COMPASS-CONNECTIONS');
105-
// @TODO: Extract to a prop COMPASS-7397
106-
const connectionStorage = connectionStorageLocator();
105+
// TODO(COMPASS-7397): services should not be used directly in render method,
106+
// when this code is refactored to use the hadron plugin interface, storage
107+
// should be handled through the plugin activation lifecycle
108+
const connectionStorage = useConnectionStorageContext();
107109

108110
const {
109111
state,

packages/compass-connections/src/stores/connections-store.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {
1212
type ConnectionRepository,
1313
type PartialConnectionInfo,
1414
} from '@mongodb-js/connection-storage/main';
15-
import { connectionRepositoryLocator } from '@mongodb-js/connection-storage/provider';
15+
import { useConnectionRepositoryContext } from '@mongodb-js/connection-storage/provider';
1616
import { cloneDeep, merge } from 'lodash';
1717
import { v4 as uuidv4 } from 'uuid';
1818
import type { ConnectionAttempt } from 'mongodb-data-service';
@@ -285,7 +285,10 @@ export function useConnections({
285285
removeConnection: (connectionInfo: ConnectionInfo) => void;
286286
reloadConnections: () => void;
287287
} {
288-
const connectionRepository = connectionRepositoryLocator();
288+
// TODO(COMPASS-7397): services should not be used directly in render method,
289+
// when this code is refactored to use the hadron plugin interface, storage
290+
// should be handled through the plugin activation lifecycle
291+
const connectionRepository = useConnectionRepositoryContext();
289292

290293
const { openToast } = useToast('compass-connections');
291294
const persistOIDCTokens = usePreference('persistOIDCTokens');

packages/compass-generative-ai/package.json

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -61,19 +61,21 @@
6161
"reformat": "npm run eslint . -- --fix && npm run prettier -- --write ."
6262
},
6363
"peerDependencies": {
64-
"@mongodb-js/compass-components": "^1.22.1",
65-
"compass-preferences-model": "^2.18.1",
66-
"@mongodb-js/compass-logging": "^1.2.14",
6764
"@mongodb-js/atlas-service": "^0.15.1",
65+
"@mongodb-js/compass-components": "^1.22.1",
6866
"@mongodb-js/compass-intercom": "^0.2.1",
69-
"react": "*"
67+
"@mongodb-js/compass-logging": "^1.2.14",
68+
"compass-preferences-model": "^2.18.1",
69+
"hadron-app-registry": "^9.1.8",
70+
"react": "^17.0.2"
7071
},
7172
"dependencies": {
73+
"@mongodb-js/atlas-service": "^0.15.1",
7274
"@mongodb-js/compass-components": "^1.22.1",
75+
"@mongodb-js/compass-intercom": "^0.2.1",
7376
"@mongodb-js/compass-logging": "^1.2.14",
74-
"@mongodb-js/atlas-service": "^0.15.1",
7577
"compass-preferences-model": "^2.18.1",
76-
"@mongodb-js/compass-intercom": "^0.2.1"
78+
"hadron-app-registry": "^9.1.8"
7779
},
7880
"devDependencies": {
7981
"@mongodb-js/eslint-config-compass": "^1.0.17",

packages/compass-generative-ai/src/provider.tsx

Lines changed: 30 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,38 +6,47 @@ import {
66
atlasAuthServiceLocator,
77
atlasServiceLocator,
88
} from '@mongodb-js/atlas-service/provider';
9+
import {
10+
createServiceLocator,
11+
createServiceProvider,
12+
} from 'hadron-app-registry';
913

1014
const AtlasAiServiceContext = createContext<AtlasAiService | null>(null);
1115

12-
export const AtlasAiServiceProvider: React.FC = ({ children }) => {
13-
const logger = useLoggerAndTelemetry('ATLAS-AI-SERVICE');
14-
const preferences = preferencesLocator();
15-
const atlasAuthService = atlasAuthServiceLocator();
16-
const atlasService = atlasServiceLocator();
16+
export const AtlasAiServiceProvider: React.FC = createServiceProvider(
17+
function AtlasAiServiceProvider({ children }) {
18+
const logger = useLoggerAndTelemetry('ATLAS-AI-SERVICE');
19+
const preferences = preferencesLocator();
20+
const atlasAuthService = atlasAuthServiceLocator();
21+
const atlasService = atlasServiceLocator();
1722

18-
const aiService = useMemo(() => {
19-
return new AtlasAiService(
20-
atlasService,
21-
atlasAuthService,
22-
preferences,
23-
logger
24-
);
25-
}, [atlasAuthService, preferences, logger, atlasService]);
23+
const aiService = useMemo(() => {
24+
return new AtlasAiService(
25+
atlasService,
26+
atlasAuthService,
27+
preferences,
28+
logger
29+
);
30+
}, [atlasAuthService, preferences, logger, atlasService]);
2631

27-
return (
28-
<AtlasAiServiceContext.Provider value={aiService}>
29-
{children}
30-
</AtlasAiServiceContext.Provider>
31-
);
32-
};
32+
return (
33+
<AtlasAiServiceContext.Provider value={aiService}>
34+
{children}
35+
</AtlasAiServiceContext.Provider>
36+
);
37+
}
38+
);
3339

34-
function useAtlasServiceLocator(): AtlasAiService {
40+
function useAtlasAiServiceContext(): AtlasAiService {
3541
const service = useContext(AtlasAiServiceContext);
3642
if (!service) {
3743
throw new Error('No AtlasAiService available in this context');
3844
}
3945
return service;
4046
}
4147

42-
export const atlasAiServiceLocator = useAtlasServiceLocator;
48+
export const atlasAiServiceLocator = createServiceLocator(
49+
useAtlasAiServiceContext,
50+
'atlasAiServiceLocator'
51+
);
4352
export { AtlasAiService } from './atlas-ai-service';

0 commit comments

Comments
 (0)