Skip to content
Merged
Show file tree
Hide file tree
Changes from 39 commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
910c1af
feat(generative-ai): add method to get mock data schema CLOUDP-333849
kpamaran Aug 22, 2025
5034086
Merge branch 'main' into atlas-ai-service-get-mock-data-schema
kpamaran Aug 22, 2025
8a2a096
nit
kpamaran Aug 22, 2025
b7c5461
add exports
kpamaran Aug 22, 2025
cc950ca
Merge branch 'main' into atlas-ai-service-get-mock-data-schema
kpamaran Aug 22, 2025
0f56ee3
address linter err
kpamaran Aug 22, 2025
99c2881
draft redux integration for requesting fakerjs mappings
kpamaran Aug 22, 2025
f7d352d
test thunk behavior
kpamaran Aug 23, 2025
77af388
pass collection name, db name, and validation rules
kpamaran Aug 23, 2025
6e1bb35
nit
kpamaran Aug 23, 2025
051f90e
supply err attrs
kpamaran Aug 26, 2025
1e05219
Merge branch 'main' into atlas-ai-service-get-mock-data-schema
kpamaran Aug 26, 2025
e5fc781
Revert compass-collection diffs
kpamaran Aug 26, 2025
a3d3f98
clean up diffs for review
kpamaran Aug 26, 2025
aebff92
Merge branch 'main' into atlas-ai-service-get-mock-data-schema
kpamaran Aug 27, 2025
0de12bc
type state machine of mock data generator request
kpamaran Aug 27, 2025
203ee82
manage request state in redux store
kpamaran Aug 27, 2025
47c1f3b
unit test thunk
kpamaran Aug 27, 2025
549d838
rename request status enum
kpamaran Aug 27, 2025
b65be4b
update lock file
kpamaran Aug 27, 2025
95d94b8
remove pnpm-lock.yaml
kpamaran Aug 27, 2025
b91a1b6
Merge branch 'atlas-ai-service-get-mock-data-schema' into compass-col…
kpamaran Aug 27, 2025
5d39dee
unit test reducer transitions for fakerSchemaGeneration state
kpamaran Aug 27, 2025
ca06674
Merge branch 'main' into compass-collection-redux-integrates-mock-dat…
kpamaran Aug 28, 2025
d630729
simplify typing
kpamaran Aug 28, 2025
e88a7f7
nit
kpamaran Aug 28, 2025
a444035
handle modal closed action on fakerSchemaGeneration state
kpamaran Aug 28, 2025
8f9aaf9
Pass requestId for tracking
kpamaran Aug 28, 2025
44fa4c0
respect user config for using sample docs on gen ai
kpamaran Aug 28, 2025
3e43c3f
fix
kpamaran Aug 28, 2025
4a5dc46
adapt unit test
kpamaran Aug 28, 2025
5d0f7c5
preserve stack trace on err
kpamaran Aug 28, 2025
e539d11
rename status val
kpamaran Aug 28, 2025
d840ffc
add @mongodb-js/compass-generative-ai as a dep to compass-collection
kpamaran Aug 29, 2025
6d022af
Merge branch 'main' into compass-collection-redux-integrates-mock-dat…
kpamaran Aug 29, 2025
01372f5
remove thunk isolation test
kpamaran Sep 2, 2025
2e1ca5c
address feedback
kpamaran Sep 2, 2025
7206585
Merge branch 'main' into compass-collection-redux-integrates-mock-dat…
kpamaran Sep 2, 2025
d2182b0
Merge branch 'main' into compass-collection-redux-integrates-mock-dat…
kpamaran Sep 2, 2025
21ef538
resolve
kpamaran Sep 2, 2025
5716285
control modal steps with redux
kpamaran Sep 3, 2025
7a56c6e
revert nit
kpamaran Sep 3, 2025
b17d1f2
Merge branch 'main' into compass-collection-redux-integrates-mock-dat…
kpamaran Sep 3, 2025
ef2652f
adapt atlas-ai-service tests
kpamaran Sep 3, 2025
c0a306e
add compass-utils as dep to compass-collection
kpamaran Sep 3, 2025
025d2fe
nit
kpamaran Sep 3, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/compass-collection/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
"@mongodb-js/compass-workspaces": "^0.52.0",
"@mongodb-js/connection-info": "^0.17.2",
"@mongodb-js/mongodb-constants": "^0.14.0",
"bson": "^6.10.1",
"compass-preferences-model": "^2.51.0",
"hadron-document": "^8.9.6",
"mongodb": "^6.17.0",
Expand All @@ -67,8 +68,7 @@
"react": "^17.0.2",
"react-redux": "^8.1.3",
"redux": "^4.2.1",
"redux-thunk": "^2.4.2",
"bson": "^6.10.1"
"redux-thunk": "^2.4.2"
},
"devDependencies": {
"@mongodb-js/eslint-config-compass": "^1.4.7",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,36 @@
import type { MockDataSchemaResponse } from '@mongodb-js/compass-generative-ai';

export enum MockDataGeneratorStep {
SCHEMA_CONFIRMATION = 'SCHEMA_CONFIRMATION',
SCHEMA_EDITOR = 'SCHEMA_EDITOR',
DOCUMENT_COUNT = 'DOCUMENT_COUNT',
PREVIEW_DATA = 'PREVIEW_DATA',
GENERATE_DATA = 'GENERATE_DATA',
}

type MockDataGeneratorIdleState = {
status: 'idle';
};

type MockDataGeneratorInProgressState = {
status: 'in-progress';
requestId: string;
};

type MockDataGeneratorCompletedState = {
status: 'completed';
fakerSchema: MockDataSchemaResponse;
requestId: string;
};

type MockDataGeneratorErrorState = {
status: 'error';
error: unknown;
requestId: string;
};

export type MockDataGeneratorState =
| MockDataGeneratorIdleState
| MockDataGeneratorInProgressState
| MockDataGeneratorCompletedState
| MockDataGeneratorErrorState;
2 changes: 2 additions & 0 deletions packages/compass-collection/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { workspacesServiceLocator } from '@mongodb-js/compass-workspaces/provide
import { experimentationServiceLocator } from '@mongodb-js/compass-telemetry/provider';
import { createLoggerLocator } from '@mongodb-js/compass-logging/provider';
import { preferencesLocator } from 'compass-preferences-model/provider';
import { atlasAiServiceLocator } from '@mongodb-js/compass-generative-ai/provider';
import {
CollectionWorkspaceTitle,
CollectionPluginTitleComponent,
Expand All @@ -33,6 +34,7 @@ export const WorkspaceTab: WorkspacePlugin<typeof CollectionWorkspaceTitle> = {
{
dataService: dataServiceLocator as DataServiceLocator<keyof DataService>,
collection: collectionModelLocator,
atlasAiService: atlasAiServiceLocator,
workspaces: workspacesServiceLocator,
experimentationServices: experimentationServiceLocator,
connectionInfoRef: connectionInfoRefLocator,
Expand Down
192 changes: 187 additions & 5 deletions packages/compass-collection/src/modules/collection-tab.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
import type { Reducer, AnyAction, Action } from 'redux';
import { analyzeDocuments } from 'mongodb-schema';
import { UUID } from 'bson';

import type { CollectionMetadata } from 'mongodb-collection-model';
import type { ThunkAction } from 'redux-thunk';
import type AppRegistry from '@mongodb-js/compass-app-registry';
import type { ConnectionInfo } from '@mongodb-js/connection-info';
import type { workspacesServiceLocator } from '@mongodb-js/compass-workspaces/provider';
import type { CollectionSubtab } from '@mongodb-js/compass-workspaces';
import type { DataService } from '@mongodb-js/compass-connections/provider';
import type { CollectionSubtab } from '@mongodb-js/compass-workspaces';
import type { AtlasAiService } from '@mongodb-js/compass-generative-ai/provider';
import type { experimentationServiceLocator } from '@mongodb-js/compass-telemetry/provider';
import { type Logger, mongoLogId } from '@mongodb-js/compass-logging/provider';
import { type PreferencesAccess } from 'compass-preferences-model/provider';
import type { AtlasAiService } from '@mongodb-js/compass-generative-ai/provider';

import type {
MockDataSchemaRequest,
MockDataSchemaResponse,
} from '@mongodb-js/compass-generative-ai';
import { isInternalFieldPath } from 'hadron-document';
import toNS from 'mongodb-ns';
import {
Expand All @@ -27,6 +32,7 @@ import { calculateSchemaDepth } from '../calculate-schema-depth';
import { processSchema } from '../transform-schema-to-field-info';
import type { Document, MongoError } from 'mongodb';
import { MockDataGeneratorStep } from '../components/mock-data-generator-modal/types';
import type { MockDataGeneratorState } from '../components/mock-data-generator-modal/types';

const DEFAULT_SAMPLE_SIZE = 100;

Expand Down Expand Up @@ -63,11 +69,11 @@ type CollectionThunkAction<R, A extends AnyAction = AnyAction> = ThunkAction<
{
localAppRegistry: AppRegistry;
dataService: DataService;
atlasAiService: AtlasAiService;
workspaces: ReturnType<typeof workspacesServiceLocator>;
experimentationServices: ReturnType<typeof experimentationServiceLocator>;
logger: Logger;
preferences: PreferencesAccess;
atlasAiService: AtlasAiService;
},
A
>;
Expand All @@ -82,9 +88,10 @@ export type CollectionState = {
isModalOpen: boolean;
currentStep: MockDataGeneratorStep;
};
fakerSchemaGeneration: MockDataGeneratorState;
};

enum CollectionActions {
export enum CollectionActions {
CollectionMetadataFetched = 'compass-collection/CollectionMetadataFetched',
SchemaAnalysisStarted = 'compass-collection/SchemaAnalysisStarted',
SchemaAnalysisFinished = 'compass-collection/SchemaAnalysisFinished',
Expand All @@ -94,6 +101,9 @@ enum CollectionActions {
MockDataGeneratorModalClosed = 'compass-collection/MockDataGeneratorModalClosed',
MockDataGeneratorNextButtonClicked = 'compass-collection/MockDataGeneratorNextButtonClicked',
MockDataGeneratorPreviousButtonClicked = 'compass-collection/MockDataGeneratorPreviousButtonClicked',
FakerMappingGenerationStarted = 'compass-collection/FakerMappingGenerationStarted',
FakerMappingGenerationCompleted = 'compass-collection/FakerMappingGenerationCompleted',
FakerMappingGenerationFailed = 'compass-collection/FakerMappingGenerationFailed',
}

interface CollectionMetadataFetchedAction {
Expand Down Expand Up @@ -140,6 +150,23 @@ interface MockDataGeneratorPreviousButtonClickedAction {
type: CollectionActions.MockDataGeneratorPreviousButtonClicked;
}

export interface FakerMappingGenerationStartedAction {
type: CollectionActions.FakerMappingGenerationStarted;
requestId: string;
}

export interface FakerMappingGenerationCompletedAction {
type: CollectionActions.FakerMappingGenerationCompleted;
fakerSchema: MockDataSchemaResponse;
requestId: string;
}

export interface FakerMappingGenerationFailedAction {
type: CollectionActions.FakerMappingGenerationFailed;
error: string;
requestId: string;
}

const reducer: Reducer<CollectionState, Action> = (
state = {
// TODO(COMPASS-7782): use hook to get the workspace tab id instead
Expand All @@ -153,6 +180,9 @@ const reducer: Reducer<CollectionState, Action> = (
isModalOpen: false,
currentStep: MockDataGeneratorStep.SCHEMA_CONFIRMATION,
},
fakerSchemaGeneration: {
status: 'idle',
},
},
action
) => {
Expand Down Expand Up @@ -256,6 +286,9 @@ const reducer: Reducer<CollectionState, Action> = (
...state.mockDataGenerator,
isModalOpen: false,
},
fakerSchemaGeneration: {
status: 'idle',
},
};
}

Expand Down Expand Up @@ -333,6 +366,75 @@ const reducer: Reducer<CollectionState, Action> = (
};
}

if (
isAction<FakerMappingGenerationStartedAction>(
action,
CollectionActions.FakerMappingGenerationStarted
)
) {
if (
state.mockDataGenerator.currentStep !==
MockDataGeneratorStep.SCHEMA_CONFIRMATION
) {
return state;
}

if (
state.fakerSchemaGeneration.status === 'in-progress' ||
state.fakerSchemaGeneration.status === 'completed'
) {
return state;
}

return {
...state,
fakerSchemaGeneration: {
status: 'in-progress',
requestId: action.requestId,
},
};
}

if (
isAction<FakerMappingGenerationCompletedAction>(
action,
CollectionActions.FakerMappingGenerationCompleted
)
) {
if (state.fakerSchemaGeneration.status !== 'in-progress') {
return state;
}

return {
...state,
fakerSchemaGeneration: {
status: 'completed',
fakerSchema: action.fakerSchema,
requestId: action.requestId,
},
};
}

if (
isAction<FakerMappingGenerationFailedAction>(
action,
CollectionActions.FakerMappingGenerationFailed
)
) {
if (state.fakerSchemaGeneration.status !== 'in-progress') {
return state;
}

return {
...state,
fakerSchemaGeneration: {
status: 'error',
error: action.error,
requestId: action.requestId,
},
};
}

return state;
};

Expand Down Expand Up @@ -480,6 +582,86 @@ export const analyzeCollectionSchema = (): CollectionThunkAction<
};
};

export const generateFakerMappings = (
connectionInfo: ConnectionInfo
): CollectionThunkAction<Promise<void>> => {
return async (
dispatch,
getState,
{ logger, atlasAiService, preferences }
) => {
const { schemaAnalysis, fakerSchemaGeneration, namespace } = getState();
if (schemaAnalysis.status !== SCHEMA_ANALYSIS_STATE_COMPLETE) {
logger.log.warn(
mongoLogId(1_001_000_305),
'Collection',
'Cannot call `generateFakeMappings` unless schema analysis is complete'
);
return;
}

if (fakerSchemaGeneration.status === 'in-progress') {
logger.debug(
'Faker mapping generation is already in progress, skipping new generation.'
);
return;
}

const includeSampleValues =
preferences.getPreferences().enableGenAISampleDocumentPassing;

// todo: dedup/abort requests using requestId (CLOUDP-333850)
const requestId = new UUID().toString();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For controlling the abort flow we usually use the thunk arg to keep the reference to the abort controller, see compass-indexes plugin for example

Copy link
Collaborator Author

@kpamaran kpamaran Sep 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

didn't see one there but I think this ref in compass-schema-validation that Nataly shared with me works as an example too


try {
logger.debug('Generating faker mappings');

const { database, collection } = toNS(namespace);

dispatch({
type: CollectionActions.FakerMappingGenerationStarted,
requestId: requestId,
});

const mockDataSchemaRequest: MockDataSchemaRequest = {
databaseName: database,
collectionName: collection,
schema: schemaAnalysis.processedSchema,
validationRules: schemaAnalysis.schemaMetadata.validationRules,
includeSampleValues,
requestId,
};

const response = await atlasAiService.getMockDataSchema(
mockDataSchemaRequest,
connectionInfo
);
dispatch({
type: CollectionActions.FakerMappingGenerationCompleted,
fakerSchema: response,
requestId: requestId,
});
} catch (e) {
const errorMessage = e instanceof Error ? e.stack : String(e);

logger.log.error(
mongoLogId(1_001_000_312),
'Collection',
'Failed to generate faker.js mappings',
{
message: errorMessage,
namespace,
}
);
dispatch({
type: CollectionActions.FakerMappingGenerationFailed,
error: 'faker mapping request failed',
requestId,
});
}
};
};

export type CollectionTabPluginMetadata = CollectionMetadata & {
/**
* Initial query for the query bar
Expand Down
Loading
Loading