@@ -4,12 +4,18 @@ import { analyzeDocuments } from 'mongodb-schema';
44import type { CollectionMetadata } from 'mongodb-collection-model' ;
55import type { ThunkAction } from 'redux-thunk' ;
66import type AppRegistry from '@mongodb-js/compass-app-registry' ;
7+ import type { ConnectionInfo } from '@mongodb-js/connection-info' ;
78import type { workspacesServiceLocator } from '@mongodb-js/compass-workspaces/provider' ;
8- import type { CollectionSubtab } from '@mongodb-js/compass-workspaces' ;
99import type { DataService } from '@mongodb-js/compass-connections/provider' ;
10+ import type { CollectionSubtab } from '@mongodb-js/compass-workspaces' ;
11+ import type { AtlasAiService } from '@mongodb-js/compass-generative-ai/provider' ;
1012import type { experimentationServiceLocator } from '@mongodb-js/compass-telemetry/provider' ;
1113import { type Logger , mongoLogId } from '@mongodb-js/compass-logging/provider' ;
1214import { type PreferencesAccess } from 'compass-preferences-model/provider' ;
15+ import {
16+ MockDataSchemaRequestShape ,
17+ type MockDataSchemaResponse ,
18+ } from '@mongodb-js/compass-generative-ai' ;
1319import { isInternalFieldPath } from 'hadron-document' ;
1420import toNS from 'mongodb-ns' ;
1521import {
@@ -24,11 +30,18 @@ import {
2430import { calculateSchemaDepth } from '../calculate-schema-depth' ;
2531import { processSchema } from '../transform-schema-to-field-info' ;
2632import type { Document , MongoError } from 'mongodb' ;
33+ import { MockDataGeneratorStep } from '../components/mock-data-generator-modal/types' ;
34+ import {
35+ MOCK_DATA_GENERATOR_STATE_IDLE ,
36+ MOCK_DATA_GENERATOR_STATE_GENERATING ,
37+ MOCK_DATA_GENERATOR_STATE_COMPLETED ,
38+ MOCK_DATA_GENERATOR_STATE_ERROR ,
39+ } from '../mock-data-generator-types' ;
40+ import type { MockDataGeneratorState } from '../mock-data-generator-types' ;
2741
2842const DEFAULT_SAMPLE_SIZE = 100 ;
2943
3044const NO_DOCUMENTS_ERROR = 'No documents found in the collection to analyze.' ;
31- import { MockDataGeneratorStep } from '../components/mock-data-generator-modal/types' ;
3245
3346function isAction < A extends AnyAction > (
3447 action : AnyAction ,
@@ -61,6 +74,7 @@ type CollectionThunkAction<R, A extends AnyAction = AnyAction> = ThunkAction<
6174 {
6275 localAppRegistry : AppRegistry ;
6376 dataService : DataService ;
77+ atlasAiService : AtlasAiService ;
6478 workspaces : ReturnType < typeof workspacesServiceLocator > ;
6579 experimentationServices : ReturnType < typeof experimentationServiceLocator > ;
6680 logger : Logger ;
@@ -79,6 +93,7 @@ export type CollectionState = {
7993 isModalOpen : boolean ;
8094 currentStep : MockDataGeneratorStep ;
8195 } ;
96+ fakerSchemaGeneration : MockDataGeneratorState ;
8297} ;
8398
8499enum CollectionActions {
@@ -91,6 +106,9 @@ enum CollectionActions {
91106 MockDataGeneratorModalClosed = 'compass-collection/MockDataGeneratorModalClosed' ,
92107 MockDataGeneratorNextButtonClicked = 'compass-collection/MockDataGeneratorNextButtonClicked' ,
93108 MockDataGeneratorPreviousButtonClicked = 'compass-collection/MockDataGeneratorPreviousButtonClicked' ,
109+ FakerMappingGenerationStarted = 'compass-collection/FakerMappingGenerationStarted' ,
110+ FakerMappingGenerationCompleted = 'compass-collection/FakerMappingGenerationCompleted' ,
111+ FakerMappingGenerationFailed = 'compass-collection/FakerMappingGenerationFailed' ,
94112}
95113
96114interface CollectionMetadataFetchedAction {
@@ -137,6 +155,23 @@ interface MockDataGeneratorPreviousButtonClickedAction {
137155 type : CollectionActions . MockDataGeneratorPreviousButtonClicked ;
138156}
139157
158+ interface FakerMappingGenerationStartedAction {
159+ type : CollectionActions . FakerMappingGenerationStarted ;
160+ requestId : string ;
161+ }
162+
163+ interface FakerMappingGenerationCompletedAction {
164+ type : CollectionActions . FakerMappingGenerationCompleted ;
165+ fakerSchema : MockDataSchemaResponse ;
166+ requestId : string ;
167+ }
168+
169+ interface FakerMappingGenerationFailedAction {
170+ type : CollectionActions . FakerMappingGenerationFailed ;
171+ error : string ;
172+ requestId : string ;
173+ }
174+
140175const reducer : Reducer < CollectionState , Action > = (
141176 state = {
142177 // TODO(COMPASS-7782): use hook to get the workspace tab id instead
@@ -150,6 +185,9 @@ const reducer: Reducer<CollectionState, Action> = (
150185 isModalOpen : false ,
151186 currentStep : MockDataGeneratorStep . AI_DISCLAIMER ,
152187 } ,
188+ fakerSchemaGeneration : {
189+ status : MOCK_DATA_GENERATOR_STATE_IDLE ,
190+ } ,
153191 } ,
154192 action
155193) => {
@@ -332,6 +370,53 @@ const reducer: Reducer<CollectionState, Action> = (
332370 } ;
333371 }
334372
373+ if (
374+ isAction < FakerMappingGenerationStartedAction > (
375+ action ,
376+ CollectionActions . FakerMappingGenerationStarted
377+ )
378+ ) {
379+ return {
380+ ...state ,
381+ fakerSchemaGeneration : {
382+ status : MOCK_DATA_GENERATOR_STATE_GENERATING ,
383+ requestId : action . requestId ,
384+ } ,
385+ } ;
386+ }
387+
388+ if (
389+ isAction < FakerMappingGenerationCompletedAction > (
390+ action ,
391+ CollectionActions . FakerMappingGenerationCompleted
392+ )
393+ ) {
394+ return {
395+ ...state ,
396+ fakerSchemaGeneration : {
397+ status : MOCK_DATA_GENERATOR_STATE_COMPLETED ,
398+ fakerSchema : action . fakerSchema ,
399+ requestId : action . requestId ,
400+ } ,
401+ } ;
402+ }
403+
404+ if (
405+ isAction < FakerMappingGenerationFailedAction > (
406+ action ,
407+ CollectionActions . FakerMappingGenerationFailed
408+ )
409+ ) {
410+ return {
411+ ...state ,
412+ fakerSchemaGeneration : {
413+ status : MOCK_DATA_GENERATOR_STATE_ERROR ,
414+ error : action . error ,
415+ requestId : action . requestId ,
416+ } ,
417+ } ;
418+ }
419+
335420 return state ;
336421} ;
337422
@@ -458,6 +543,65 @@ export const analyzeCollectionSchema = (): CollectionThunkAction<
458543 } ;
459544} ;
460545
546+ export const generateFakerMappings = (
547+ connectionInfo : ConnectionInfo
548+ ) : CollectionThunkAction < Promise < void > > => {
549+ return async ( dispatch , getState , { logger, atlasAiService } ) => {
550+ const { schemaAnalysis, fakerSchemaGeneration } = getState ( ) ;
551+ if ( schemaAnalysis . status !== SCHEMA_ANALYSIS_STATE_COMPLETE ) {
552+ logger . log . error (
553+ mongoLogId ( 1_001_000_305 ) ,
554+ 'Collection' ,
555+ 'Cannot call `generateFakeMappings` unless schema analysis is complete'
556+ ) ;
557+ return ;
558+ }
559+
560+ if ( fakerSchemaGeneration . status === MOCK_DATA_GENERATOR_STATE_GENERATING ) {
561+ logger . debug (
562+ 'Faker mapping generation is already in progress, skipping new generation.'
563+ ) ;
564+ return ;
565+ }
566+
567+ // todo: dedup/abort around requestId
568+ const requestId = 'some-request-id' ;
569+ try {
570+ logger . debug ( 'Generating faker mappings' ) ;
571+
572+ dispatch ( {
573+ type : CollectionActions . FakerMappingGenerationStarted ,
574+ requestId : requestId ,
575+ } ) ;
576+
577+ const mockDataSchemaRequest = MockDataSchemaRequestShape . parse (
578+ schemaAnalysis . processedSchema
579+ ) ;
580+
581+ const response = await atlasAiService . getMockDataSchema (
582+ mockDataSchemaRequest ,
583+ connectionInfo
584+ ) ;
585+ dispatch ( {
586+ type : CollectionActions . FakerMappingGenerationCompleted ,
587+ fakerSchema : response ,
588+ requestId : requestId ,
589+ } ) ;
590+ } catch {
591+ logger . log . error (
592+ mongoLogId ( 1_001_000_312 ) ,
593+ 'Collection' ,
594+ 'Failed to generate faker mappings'
595+ ) ;
596+ dispatch ( {
597+ type : CollectionActions . FakerMappingGenerationFailed ,
598+ error : 'Failed to generate faker mappings' ,
599+ requestId : requestId ,
600+ } ) ;
601+ }
602+ } ;
603+ } ;
604+
461605export type CollectionTabPluginMetadata = CollectionMetadata & {
462606 /**
463607 * Initial query for the query bar
0 commit comments