From 6fc825cae85b2f424d99942bb672906f2c32f50f Mon Sep 17 00:00:00 2001
From: An Phi <aphi@skidmore.edu>
Date: Mon, 23 Dec 2024 02:18:27 -0500
Subject: [PATCH] datacube: cleanup fetch config method in engine

---
 .../src/components/PureIDEStoreProvider.tsx   |  7 +--
 .../src/components/LegendREPLApplication.tsx  | 43 +++++++++++--------
 .../src/stores/LegendREPLBaseStore.tsx        | 24 +++++++++++
 .../src/stores/LegendREPLDataCubeEngine.ts    | 10 -----
 .../ProjectReviewStoreProvider.tsx            |  7 ++-
 .../ApplicationFrameworkProvider.tsx          |  5 +--
 .../components/ApplicationStoreProvider.tsx   |  8 ++--
 .../src/components/DataCube.tsx               |  4 +-
 .../src/stores/DataCubeOptions.ts             |  1 +
 .../src/stores/DataCubeSettings.ts            |  1 +
 .../src/stores/DataCubeState.tsx              |  1 +
 .../src/stores/core/DataCubeEngine.tsx        | 20 +++------
 12 files changed, 71 insertions(+), 60 deletions(-)

diff --git a/packages/legend-application-pure-ide/src/components/PureIDEStoreProvider.tsx b/packages/legend-application-pure-ide/src/components/PureIDEStoreProvider.tsx
index 4214c6e2477..8e3b0f236c6 100644
--- a/packages/legend-application-pure-ide/src/components/PureIDEStoreProvider.tsx
+++ b/packages/legend-application-pure-ide/src/components/PureIDEStoreProvider.tsx
@@ -24,11 +24,8 @@ import type { LegendPureIDEPluginManager } from '../application/LegendPureIDEPlu
 
 const EditorStoreContext = createContext<PureIDEStore | undefined>(undefined);
 
-export const PureIDEStoreProvider = ({
-  children,
-}: {
-  children: React.ReactNode;
-}): React.ReactElement => {
+export const PureIDEStoreProvider = (props: { children: React.ReactNode }) => {
+  const { children } = props;
   const applicationStore = useApplicationStore<
     LegendPureIDEApplicationConfig,
     LegendPureIDEPluginManager
diff --git a/packages/legend-application-repl/src/components/LegendREPLApplication.tsx b/packages/legend-application-repl/src/components/LegendREPLApplication.tsx
index 4527f1bc81a..b1efbf890a1 100644
--- a/packages/legend-application-repl/src/components/LegendREPLApplication.tsx
+++ b/packages/legend-application-repl/src/components/LegendREPLApplication.tsx
@@ -33,12 +33,9 @@ import {
 } from './LegendREPLFramworkProvider.js';
 
 const LegendREPLDataCube = observer(() => {
-  const baseStore = useLegendREPLBaseStore();
-  const engine = useMemo(
-    () => new LegendREPLDataCubeEngine(baseStore),
-    [baseStore],
-  );
-  const application = baseStore.application;
+  const store = useLegendREPLBaseStore();
+  const engine = useMemo(() => new LegendREPLDataCubeEngine(store), [store]);
+  const application = store.application;
 
   useEffect(() => {
     engine.blockNavigation(
@@ -74,10 +71,10 @@ const LegendREPLDataCube = observer(() => {
         onSettingChanged(key, value) {
           engine.persistSettingValue(key, value);
         },
-
         enableDebugMode: application.settingService.getBooleanValue(
           DataCubeSettingKey.ENABLE_DEBUG_MODE,
         ),
+        gridClientLicense: store.gridClientLicense,
         gridClientRowBuffer: application.settingService.getNumericValue(
           DataCubeSettingKey.GRID_CLIENT_ROW_BUFFER,
         ),
@@ -101,16 +98,28 @@ export const LEGEND_REPL_GRID_CLIENT_ROUTE_PATTERN = Object.freeze({
   DATA_CUBE: `/dataCube`,
 });
 
-export const LegendREPLRouter = observer(() => (
-  <div className="h-full">
-    <Routes>
-      <Route
-        path={LEGEND_REPL_GRID_CLIENT_ROUTE_PATTERN.DATA_CUBE}
-        element={<LegendREPLDataCube />}
-      />
-    </Routes>
-  </div>
-));
+export const LegendREPLRouter = observer(() => {
+  const store = useLegendREPLBaseStore();
+
+  useEffect(() => {
+    store
+      .initialize()
+      .catch((error) => store.application.alertUnhandledError(error));
+  }, [store]);
+
+  return (
+    <div className="h-full">
+      {store.initState.hasSucceeded && (
+        <Routes>
+          <Route
+            path={LEGEND_REPL_GRID_CLIENT_ROUTE_PATTERN.DATA_CUBE}
+            element={<LegendREPLDataCube />}
+          />
+        </Routes>
+      )}
+    </div>
+  );
+});
 
 export const LegendREPLWebApplication = (props: { baseUrl: string }) => {
   const { baseUrl } = props;
diff --git a/packages/legend-application-repl/src/stores/LegendREPLBaseStore.tsx b/packages/legend-application-repl/src/stores/LegendREPLBaseStore.tsx
index 44443ec3956..60b02eecdc1 100644
--- a/packages/legend-application-repl/src/stores/LegendREPLBaseStore.tsx
+++ b/packages/legend-application-repl/src/stores/LegendREPLBaseStore.tsx
@@ -16,6 +16,7 @@
 
 import {
   ActionState,
+  LogEvent,
   NetworkClient,
   assertErrorThrown,
   guaranteeNonNullable,
@@ -34,14 +35,17 @@ import {
 import { LegendREPLDataCubeSource } from './LegendREPLDataCubeSource.js';
 import { PersistentDataCubeQuery } from '@finos/legend-graph';
 import { LegendREPLPublishDataCubeAlert } from '../components/LegendREPLPublishDataCubeAlert.js';
+import { APPLICATION_EVENT } from '@finos/legend-application';
 
 export class LegendREPLBaseStore {
   readonly application: LegendREPLApplicationStore;
   readonly client: LegendREPLServerClient;
+  readonly initState = ActionState.create();
   readonly publishState = ActionState.create();
 
   sourceQuery?: string | undefined;
   currentUser?: string | undefined;
+  gridClientLicense?: string | undefined;
   queryServerBaseUrl?: string | undefined;
   hostedApplicationBaseUrl?: string | undefined;
 
@@ -60,6 +64,26 @@ export class LegendREPLBaseStore {
     );
   }
 
+  async initialize() {
+    this.initState.inProgress();
+    try {
+      const info = await this.client.getInfrastructureInfo();
+      this.currentUser = info.currentUser;
+      this.queryServerBaseUrl = info.queryServerBaseUrl;
+      this.hostedApplicationBaseUrl = info.hostedApplicationBaseUrl;
+      this.gridClientLicense = info.gridClientLicense;
+      this.initState.pass();
+    } catch (error) {
+      assertErrorThrown(error);
+      this.application.logService.error(
+        LogEvent.create(APPLICATION_EVENT.APPLICATION_LOAD__FAILURE),
+        `Can't initialize REPL`,
+        error,
+      );
+      this.initState.fail();
+    }
+  }
+
   async publishDataCube(dataCube: DataCubeState) {
     if (
       !this.sourceQuery ||
diff --git a/packages/legend-application-repl/src/stores/LegendREPLDataCubeEngine.ts b/packages/legend-application-repl/src/stores/LegendREPLDataCubeEngine.ts
index e1b7108175b..d758a829ec5 100644
--- a/packages/legend-application-repl/src/stores/LegendREPLDataCubeEngine.ts
+++ b/packages/legend-application-repl/src/stores/LegendREPLDataCubeEngine.ts
@@ -97,16 +97,6 @@ export class LegendREPLDataCubeEngine extends DataCubeEngine {
 
   // ---------------------------------- IMPLEMENTATION ----------------------------------
 
-  override async fetchConfiguration() {
-    const info = await this.client.getInfrastructureInfo();
-    this.baseStore.currentUser = info.currentUser;
-    this.baseStore.queryServerBaseUrl = info.queryServerBaseUrl;
-    this.baseStore.hostedApplicationBaseUrl = info.hostedApplicationBaseUrl;
-    return {
-      gridClientLicense: info.gridClientLicense,
-    };
-  }
-
   async getBaseQuery() {
     return DataCubeQuery.serialization.fromJson(
       await this.client.getBaseQuery(),
diff --git a/packages/legend-application-studio/src/components/project-reviewer/ProjectReviewStoreProvider.tsx b/packages/legend-application-studio/src/components/project-reviewer/ProjectReviewStoreProvider.tsx
index 77c699e6456..199a0521176 100644
--- a/packages/legend-application-studio/src/components/project-reviewer/ProjectReviewStoreProvider.tsx
+++ b/packages/legend-application-studio/src/components/project-reviewer/ProjectReviewStoreProvider.tsx
@@ -25,11 +25,10 @@ const ProjectReviewerStoreContext = createContext<
   ProjectReviewerStore | undefined
 >(undefined);
 
-export const ProjectReviewerStoreProvider = ({
-  children,
-}: {
+export const ProjectReviewerStoreProvider = (props: {
   children: React.ReactNode;
-}): React.ReactElement => {
+}) => {
+  const { children } = props;
   const editorStore = useEditorStore();
   editorStore.setMode(EDITOR_MODE.REVIEW);
   const store = useLocalObservable(() => new ProjectReviewerStore(editorStore));
diff --git a/packages/legend-application/src/components/ApplicationFrameworkProvider.tsx b/packages/legend-application/src/components/ApplicationFrameworkProvider.tsx
index 6d17e63c305..b059a466e4c 100644
--- a/packages/legend-application/src/components/ApplicationFrameworkProvider.tsx
+++ b/packages/legend-application/src/components/ApplicationFrameworkProvider.tsx
@@ -24,10 +24,7 @@ import { useApplicationStore } from './ApplicationStoreProvider.js';
 import { useApplicationPlatform } from './ApplicationPlatformProvider.js';
 
 export const ApplicationFrameworkProvider = observer(
-  (props: {
-    children: React.ReactNode;
-    simple?: boolean | undefined;
-  }): React.ReactElement => {
+  (props: { children: React.ReactNode; simple?: boolean | undefined }) => {
     const { children, simple } = props;
     const platform = useApplicationPlatform();
     const applicationStore = useApplicationStore();
diff --git a/packages/legend-application/src/components/ApplicationStoreProvider.tsx b/packages/legend-application/src/components/ApplicationStoreProvider.tsx
index 5a31e86d631..295adeff4f3 100644
--- a/packages/legend-application/src/components/ApplicationStoreProvider.tsx
+++ b/packages/legend-application/src/components/ApplicationStoreProvider.tsx
@@ -41,13 +41,11 @@ export const useApplicationStore = <
 export const ApplicationStoreProvider = <
   T extends LegendApplicationConfig,
   V extends LegendApplicationPluginManager<LegendApplicationPlugin>,
->({
-  children,
-  store,
-}: {
+>(props: {
   children: React.ReactNode;
   store: ApplicationStore<T, V>;
-}): React.ReactElement => {
+}) => {
+  const { children, store } = props;
   const applicationStore = useLocalObservable(() => store);
   return (
     <ApplicationStoreContext.Provider value={applicationStore}>
diff --git a/packages/legend-data-cube/src/components/DataCube.tsx b/packages/legend-data-cube/src/components/DataCube.tsx
index 4f4b0505e7c..a93abe3b31d 100644
--- a/packages/legend-data-cube/src/components/DataCube.tsx
+++ b/packages/legend-data-cube/src/components/DataCube.tsx
@@ -30,6 +30,7 @@ import type { DataCubeEngine } from '../stores/core/DataCubeEngine.js';
 import { DataCubeState } from '../stores/DataCubeState.js';
 import { type DataCubeOptions } from '../stores/DataCubeOptions.js';
 import { DataCubeContextProvider, useDataCube } from './DataCubeProvider.js';
+import type { DataCubeQuery } from '../stores/core/models/DataCubeQuery.js';
 
 const DataCubeTitleBar = observer(() => {
   const dataCube = useDataCube();
@@ -119,8 +120,9 @@ const DataCubeRoot = observer(() => {
 export const DataCube = observer(
   (props: {
     engine: DataCubeEngine;
+    query?: DataCubeQuery | undefined;
     options?: DataCubeOptions | undefined;
-  }): React.ReactElement => {
+  }) => {
     const { engine, options } = props;
     const state = useLocalObservable(() => new DataCubeState(engine, options));
 
diff --git a/packages/legend-data-cube/src/stores/DataCubeOptions.ts b/packages/legend-data-cube/src/stores/DataCubeOptions.ts
index b6183fdc328..7d7f5e43b7e 100644
--- a/packages/legend-data-cube/src/stores/DataCubeOptions.ts
+++ b/packages/legend-data-cube/src/stores/DataCubeOptions.ts
@@ -19,6 +19,7 @@ import type { DataCubeState } from './DataCubeState.js';
 
 export type DataCubeOptions = {
   enableDebugMode?: boolean | undefined;
+  gridClientLicense?: string | undefined;
   gridClientRowBuffer?: number | undefined;
   gridClientPurgeClosedRowNodes?: boolean | undefined;
   gridClientSuppressLargeDatasetWarning?: boolean | undefined;
diff --git a/packages/legend-data-cube/src/stores/DataCubeSettings.ts b/packages/legend-data-cube/src/stores/DataCubeSettings.ts
index 8882a45ea33..be7e0924922 100644
--- a/packages/legend-data-cube/src/stores/DataCubeSettings.ts
+++ b/packages/legend-data-cube/src/stores/DataCubeSettings.ts
@@ -61,6 +61,7 @@ export class DataCubeSettings {
     DEFAULT_SETTINGS[
       DataCubeSettingKey.GRID_CLIENT_SUPPRESS_LARGE_DATASET_WARNING
     ];
+  gridClientLicense?: string | undefined;
 
   setEnableDebugMode(value: boolean) {
     this.enableDebugMode = value;
diff --git a/packages/legend-data-cube/src/stores/DataCubeState.tsx b/packages/legend-data-cube/src/stores/DataCubeState.tsx
index 90679fd2858..924307ff8a9 100644
--- a/packages/legend-data-cube/src/stores/DataCubeState.tsx
+++ b/packages/legend-data-cube/src/stores/DataCubeState.tsx
@@ -118,6 +118,7 @@ export class DataCubeState implements DataCubeAPI {
       options?.gridClientSuppressLargeDatasetWarning !== undefined
         ? options.gridClientSuppressLargeDatasetWarning
         : this.settings.gridClientSuppressLargeDatasetWarning;
+    this.settings.gridClientLicense = options?.gridClientLicense;
   }
 
   getSettings() {
diff --git a/packages/legend-data-cube/src/stores/core/DataCubeEngine.tsx b/packages/legend-data-cube/src/stores/core/DataCubeEngine.tsx
index e5d5181ae28..8a6eaf8b5e5 100644
--- a/packages/legend-data-cube/src/stores/core/DataCubeEngine.tsx
+++ b/packages/legend-data-cube/src/stores/core/DataCubeEngine.tsx
@@ -122,10 +122,6 @@ type DataCubeExecutionResult = {
   executedSQL: string;
 };
 
-export type DataCubeEngineConfiguration = {
-  gridClientLicense?: string | undefined;
-};
-
 export abstract class DataCubeEngine {
   readonly layout = new LayoutManagerState();
   readonly filterOperations = [
@@ -176,16 +172,13 @@ export abstract class DataCubeEngine {
     new DataCubeQueryAggregateOperation__JoinStrings(),
   ];
 
-  protected async fetchConfiguration(): Promise<DataCubeEngineConfiguration> {
-    return {
-      gridClientLicense: undefined,
-    };
-  }
+  abstract getBaseQuery(): Promise<DataCubeQuery | undefined>;
 
-  async initialize(): Promise<void> {
-    const config = await this.fetchConfiguration();
-    if (config.gridClientLicense) {
-      LicenseManager.setLicenseKey(config.gridClientLicense);
+  async initialize(options?: {
+    gridClientLicense?: string | undefined;
+  }): Promise<void> {
+    if (options?.gridClientLicense) {
+      LicenseManager.setLicenseKey(options.gridClientLicense);
     }
     await configureCodeEditor(DataCubeFont.ROBOTO_MONO, (error) => {
       throw error;
@@ -203,7 +196,6 @@ export abstract class DataCubeEngine {
     return getAggregateOperation(value, this.aggregateOperations);
   }
 
-  abstract getBaseQuery(): Promise<DataCubeQuery | undefined>;
   abstract processQuerySource(value: PlainObject): Promise<DataCubeSource>;
 
   abstract parseValueSpecification(