From 8868de4f2fcf8f15a321a0d4bd4305363f571b74 Mon Sep 17 00:00:00 2001 From: Tyler Ohlsen Date: Tue, 12 Sep 2023 13:09:49 -0700 Subject: [PATCH] Add initial server route; add core & route services (#27) Signed-off-by: Tyler Ohlsen (cherry picked from commit 9991af8d2a0792e0d51c20fca2170a7af2056a0f) --- common/constants.ts | 2 +- opensearch_dashboards.json | 1 + public/app.tsx | 55 +++++++++++----------------- public/core_services.ts | 13 ------- public/index.ts | 2 - public/pages/overview/overview.tsx | 6 +-- public/pages/use_cases/use_cases.tsx | 6 +-- public/pages/workflows/workflows.tsx | 6 +-- public/plugin.ts | 5 +++ public/render_app.tsx | 9 +---- public/route_service.ts | 29 +++++++++++++++ public/services.ts | 14 +++++++ server/plugin.ts | 4 +- server/routes/index.ts | 19 +--------- server/routes/opensearch_routes.ts | 52 ++++++++++++++++++++++++++ 15 files changed, 133 insertions(+), 90 deletions(-) delete mode 100644 public/core_services.ts create mode 100644 public/route_service.ts create mode 100644 public/services.ts create mode 100644 server/routes/opensearch_routes.ts diff --git a/common/constants.ts b/common/constants.ts index ad2fff73..2eabeefc 100644 --- a/common/constants.ts +++ b/common/constants.ts @@ -2,7 +2,7 @@ * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 */ - export const PLUGIN_ID = 'aiFlowDashboards'; export const BASE_NODE_API_PATH = '/api/ai_flow'; +export const SEARCH_PATH = `${BASE_NODE_API_PATH}/search`; diff --git a/opensearch_dashboards.json b/opensearch_dashboards.json index 1f62086b..d865c43b 100644 --- a/opensearch_dashboards.json +++ b/opensearch_dashboards.json @@ -4,6 +4,7 @@ "opensearchDashboardsVersion": "3.0.0", "server": true, "ui": true, + "requiredBundles": ["opensearchDashboardsUtils"], "requiredPlugins": ["navigation"], "optionalPlugins": [] } diff --git a/public/app.tsx b/public/app.tsx index 2e46c62a..bb97f2e6 100644 --- a/public/app.tsx +++ b/public/app.tsx @@ -4,13 +4,10 @@ */ import React from 'react'; -import { I18nProvider } from '@osd/i18n/react'; import { Route, RouteComponentProps, Switch } from 'react-router-dom'; import { EuiPageSideBar, EuiSideNav, EuiPageTemplate } from '@elastic/eui'; -import { CoreStart } from '../../../src/core/public'; import { Navigation, APP_PATH } from './utils'; import { Overview, UseCases, Workflows } from './pages'; -import { CoreServicesConsumer } from './core_services'; // eslint-disable-next-line @typescript-eslint/no-empty-interface interface Props extends RouteComponentProps {} @@ -46,36 +43,26 @@ export const AiFlowDashboardsApp = (props: Props) => { // Render the application DOM. return ( - - {(core: CoreStart | null) => - core && ( - - <> - - - } - /> - } - /> - {/* Defaulting to Overview page */} - } - /> - - - - - ) - } - + + + } + /> + } + /> + {/* Defaulting to Overview page */} + } + /> + + ); }; diff --git a/public/core_services.ts b/public/core_services.ts deleted file mode 100644 index e2e8ced4..00000000 --- a/public/core_services.ts +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Copyright OpenSearch Contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import { createContext } from 'react'; -import { CoreStart } from '../../../src/core/public'; - -const CoreServicesContext = createContext(null); - -const CoreServicesConsumer = CoreServicesContext.Consumer; - -export { CoreServicesContext, CoreServicesConsumer }; diff --git a/public/index.ts b/public/index.ts index 2447574c..9d72d759 100644 --- a/public/index.ts +++ b/public/index.ts @@ -16,5 +16,3 @@ export { AiFlowDashboardsPluginSetup, AiFlowDashboardsPluginStart, } from './types'; - -export * from './core_services'; diff --git a/public/pages/overview/overview.tsx b/public/pages/overview/overview.tsx index 7d8c73d4..5064bab6 100644 --- a/public/pages/overview/overview.tsx +++ b/public/pages/overview/overview.tsx @@ -5,14 +5,12 @@ import React, { useEffect } from 'react'; import { EuiPageHeader, EuiText } from '@elastic/eui'; -import { CoreServicesContext } from '../../core_services'; -import { CoreStart } from '../../../../../src/core/public'; import { BREADCRUMBS } from '../../utils'; +import { getCore } from '../../services'; export function Overview() { - const core = React.useContext(CoreServicesContext) as CoreStart; useEffect(() => { - core.chrome.setBreadcrumbs([BREADCRUMBS.AI_APPLICATION_BUILDER]); + getCore().chrome.setBreadcrumbs([BREADCRUMBS.AI_APPLICATION_BUILDER]); }); return ( diff --git a/public/pages/use_cases/use_cases.tsx b/public/pages/use_cases/use_cases.tsx index efd3c310..d3356fba 100644 --- a/public/pages/use_cases/use_cases.tsx +++ b/public/pages/use_cases/use_cases.tsx @@ -5,14 +5,12 @@ import React, { useEffect } from 'react'; import { EuiPageHeader, EuiText } from '@elastic/eui'; -import { CoreServicesContext } from '../../core_services'; -import { CoreStart } from '../../../../../src/core/public'; import { BREADCRUMBS } from '../../utils'; +import { getCore } from '../../services'; export function UseCases() { - const core = React.useContext(CoreServicesContext) as CoreStart; useEffect(() => { - core.chrome.setBreadcrumbs([ + getCore().chrome.setBreadcrumbs([ BREADCRUMBS.AI_APPLICATION_BUILDER, BREADCRUMBS.USE_CASES, ]); diff --git a/public/pages/workflows/workflows.tsx b/public/pages/workflows/workflows.tsx index 405151d0..e192e8f9 100644 --- a/public/pages/workflows/workflows.tsx +++ b/public/pages/workflows/workflows.tsx @@ -5,14 +5,12 @@ import React, { useEffect } from 'react'; import { EuiPageHeader, EuiText } from '@elastic/eui'; -import { CoreServicesContext } from '../../core_services'; -import { CoreStart } from '../../../../../src/core/public'; import { BREADCRUMBS } from '../../utils'; +import { getCore } from '../../services'; export function Workflows() { - const core = React.useContext(CoreServicesContext) as CoreStart; useEffect(() => { - core.chrome.setBreadcrumbs([ + getCore().chrome.setBreadcrumbs([ BREADCRUMBS.AI_APPLICATION_BUILDER, BREADCRUMBS.WORKFLOWS, ]); diff --git a/public/plugin.ts b/public/plugin.ts index f91ede01..5e19fdcc 100644 --- a/public/plugin.ts +++ b/public/plugin.ts @@ -14,6 +14,8 @@ import { AiFlowDashboardsPluginStart, } from './types'; import { PLUGIN_ID } from '../common'; +import { setCore, setRouteService } from './services'; +import { configureRoutes } from './route_service'; export class AiFlowDashboardsPlugin implements Plugin { @@ -33,6 +35,9 @@ export class AiFlowDashboardsPlugin async mount(params: AppMountParameters) { const { renderApp } = await import('./render_app'); const [coreStart] = await core.getStartServices(); + const routeServices = configureRoutes(coreStart); + setCore(coreStart); + setRouteService(routeServices); return renderApp(coreStart, params); }, }); diff --git a/public/render_app.tsx b/public/render_app.tsx index da187cd2..fb38f110 100644 --- a/public/render_app.tsx +++ b/public/render_app.tsx @@ -8,7 +8,6 @@ import ReactDOM from 'react-dom'; import { BrowserRouter as Router, Route } from 'react-router-dom'; import { AppMountParameters, CoreStart } from '../../../src/core/public'; import { AiFlowDashboardsApp } from './app'; -import { CoreServicesContext } from './core_services'; export const renderApp = ( coreStart: CoreStart, @@ -16,13 +15,7 @@ export const renderApp = ( ) => { ReactDOM.render( - ( - - - - )} - /> + } /> , element ); diff --git a/public/route_service.ts b/public/route_service.ts new file mode 100644 index 00000000..71296e62 --- /dev/null +++ b/public/route_service.ts @@ -0,0 +1,29 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { CoreStart, HttpFetchError } from '../../../src/core/public'; +import { SEARCH_PATH } from '../common'; + +export interface RouteService { + searchIndex: (indexName: string, body: {}) => Promise; +} + +export function configureRoutes(core: CoreStart): RouteService { + return { + searchIndex: async (indexName: string, body: {}) => { + try { + const response = await core.http.post<{ respString: string }>( + `${SEARCH_PATH}/${indexName}`, + { + body: JSON.stringify(body), + } + ); + return response; + } catch (e: any) { + return e as HttpFetchError; + } + }, + }; +} diff --git a/public/services.ts b/public/services.ts new file mode 100644 index 00000000..bd4d85a2 --- /dev/null +++ b/public/services.ts @@ -0,0 +1,14 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { createGetterSetter } from '../../../src/plugins/opensearch_dashboards_utils/public'; +import { CoreStart } from '../../../src/core/public'; +import { RouteService } from './route_service'; + +export const [getCore, setCore] = createGetterSetter('Core'); + +export const [getRouteService, setRouteService] = createGetterSetter< + RouteService +>(''); diff --git a/server/plugin.ts b/server/plugin.ts index 766ea951..02bb37e2 100644 --- a/server/plugin.ts +++ b/server/plugin.ts @@ -15,7 +15,7 @@ import { AiFlowDashboardsPluginSetup, AiFlowDashboardsPluginStart, } from './types'; -import { defineRoutes } from './routes'; +import { registerOpenSearchRoutes } from './routes'; export class AiFlowDashboardsPlugin implements Plugin { @@ -30,7 +30,7 @@ export class AiFlowDashboardsPlugin const router = core.http.createRouter(); // Register server side APIs - defineRoutes(router); + registerOpenSearchRoutes(router); return {}; } diff --git a/server/routes/index.ts b/server/routes/index.ts index 0ae579e8..00b49143 100644 --- a/server/routes/index.ts +++ b/server/routes/index.ts @@ -3,21 +3,4 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { IRouter } from '../../../../src/core/server'; -import { BASE_NODE_API_PATH } from '../../common'; - -export function defineRoutes(router: IRouter) { - router.get( - { - path: BASE_NODE_API_PATH, - validate: false, - }, - async (context, request, response) => { - return response.ok({ - body: { - time: new Date().toISOString(), - }, - }); - } - ); -} +export * from './opensearch_routes'; diff --git a/server/routes/opensearch_routes.ts b/server/routes/opensearch_routes.ts new file mode 100644 index 00000000..2b7f2563 --- /dev/null +++ b/server/routes/opensearch_routes.ts @@ -0,0 +1,52 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { schema } from '@osd/config-schema'; +import { SearchRequest } from '@opensearch-project/opensearch/api/types'; +import { + IRouter, + IOpenSearchDashboardsResponse, +} from '../../../../src/core/server'; +import { SEARCH_PATH } from '../../common'; + +export function registerOpenSearchRoutes(router: IRouter): void { + router.post( + { + path: `${SEARCH_PATH}/{index_name}`, + validate: { + params: schema.object({ + index_name: schema.string(), + }), + body: schema.any(), + }, + }, + async (context, req, res): Promise> => { + const client = context.core.opensearch.client.asCurrentUser; + // eslint-disable-next-line @typescript-eslint/naming-convention + const { index_name } = req.params; + const body = req.body; + + const params = { + index: index_name, + body, + } as SearchRequest; + + try { + const response = await client.search(params); + return res.ok({ body: response }); + } catch (err: any) { + return res.customError({ + statusCode: err.statusCode || 500, + body: { + message: err.message, + attributes: { + error: err.body?.error || err.message, + }, + }, + }); + } + } + ); +}