@@ -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 {
34+ MockDataGeneratorStep ,
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 '../components/mock-data-generator-modal/types' ;
40+ import type { MockDataGeneratorState } from '../components/mock-data-generator-modal/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,9 +93,10 @@ export type CollectionState = {
7993 isModalOpen : boolean ;
8094 currentStep : MockDataGeneratorStep ;
8195 } ;
96+ fakerSchemaGeneration : MockDataGeneratorState ;
8297} ;
8398
84- enum CollectionActions {
99+ export enum CollectionActions {
85100 CollectionMetadataFetched = 'compass-collection/CollectionMetadataFetched' ,
86101 SchemaAnalysisStarted = 'compass-collection/SchemaAnalysisStarted' ,
87102 SchemaAnalysisFinished = 'compass-collection/SchemaAnalysisFinished' ,
@@ -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,77 @@ 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, namespace } = 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+
570+ try {
571+ logger . debug ( 'Generating faker mappings' ) ;
572+
573+ const { database, collection } = toNS ( namespace ) ;
574+
575+ dispatch ( {
576+ type : CollectionActions . FakerMappingGenerationStarted ,
577+ requestId : requestId ,
578+ } ) ;
579+
580+ const mockDataSchemaRequest = MockDataSchemaRequestShape . parse ( {
581+ databaseName : database ,
582+ collectionName : collection ,
583+ schema : schemaAnalysis . processedSchema ,
584+ validationRules : schemaAnalysis . schemaMetadata . validationRules ,
585+ } ) ;
586+
587+ const response = await atlasAiService . getMockDataSchema (
588+ mockDataSchemaRequest ,
589+ connectionInfo
590+ ) ;
591+ dispatch ( {
592+ type : CollectionActions . FakerMappingGenerationCompleted ,
593+ fakerSchema : response ,
594+ requestId : requestId ,
595+ } ) ;
596+ } catch ( e ) {
597+ const errorMessage = e instanceof Error ? e . message : String ( e ) ;
598+
599+ logger . log . error (
600+ mongoLogId ( 1_001_000_312 ) ,
601+ 'Collection' ,
602+ 'Failed to generate faker.js mappings' ,
603+ {
604+ error : errorMessage ,
605+ namespace,
606+ }
607+ ) ;
608+ dispatch ( {
609+ type : CollectionActions . FakerMappingGenerationFailed ,
610+ error : 'Experienced an issue generating faker.js mappings' ,
611+ requestId,
612+ } ) ;
613+ }
614+ } ;
615+ } ;
616+
461617export type CollectionTabPluginMetadata = CollectionMetadata & {
462618 /**
463619 * Initial query for the query bar
0 commit comments