From 642290b0f11a6647aef0170648b1a24da712ba56 Mon Sep 17 00:00:00 2001
From: Nathan Reese <reese.nathan@elastic.co>
Date: Fri, 20 May 2022 15:11:15 -0600
Subject: [PATCH] [maps] convert ESPewPewSource to typescript (#132656)

* [maps] convert ESPewPewSource to typescript

* move @ts-expect-error moved by fix
---
 .../security/create_layer_descriptors.ts      |   2 -
 ...ew_pew_source.js => es_pew_pew_source.tsx} | 102 ++++++++++++------
 .../es_pew_pew_source/{index.js => index.ts}  |   0
 .../point_2_point_layer_wizard.tsx            |   9 +-
 4 files changed, 73 insertions(+), 40 deletions(-)
 rename x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/{es_pew_pew_source.js => es_pew_pew_source.tsx} (67%)
 rename x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/{index.js => index.ts} (100%)

diff --git a/x-pack/plugins/maps/public/classes/layers/wizards/solution_layers/security/create_layer_descriptors.ts b/x-pack/plugins/maps/public/classes/layers/wizards/solution_layers/security/create_layer_descriptors.ts
index 5792d861f6f5c..f295464126c96 100644
--- a/x-pack/plugins/maps/public/classes/layers/wizards/solution_layers/security/create_layer_descriptors.ts
+++ b/x-pack/plugins/maps/public/classes/layers/wizards/solution_layers/security/create_layer_descriptors.ts
@@ -24,9 +24,7 @@ import {
 } from '../../../../../../common/constants';
 import { GeoJsonVectorLayer } from '../../../vector_layer';
 import { VectorStyle } from '../../../../styles/vector/vector_style';
-// @ts-ignore
 import { ESSearchSource } from '../../../../sources/es_search_source';
-// @ts-ignore
 import { ESPewPewSource } from '../../../../sources/es_pew_pew_source';
 import { getDefaultDynamicProperties } from '../../../../styles/vector/vector_style_defaults';
 import { APM_INDEX_PATTERN_TITLE } from '../observability';
diff --git a/x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/es_pew_pew_source.js b/x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/es_pew_pew_source.tsx
similarity index 67%
rename from x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/es_pew_pew_source.js
rename to x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/es_pew_pew_source.tsx
index a38c769205304..910181d6a2868 100644
--- a/x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/es_pew_pew_source.js
+++ b/x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/es_pew_pew_source.tsx
@@ -8,17 +8,35 @@
 import React from 'react';
 import turfBbox from '@turf/bbox';
 import { multiPoint } from '@turf/helpers';
+import { Adapters } from '@kbn/inspector-plugin/common/adapters';
+import { type Filter, buildExistsFilter } from '@kbn/es-query';
+import { lastValueFrom } from 'rxjs';
+import type {
+  AggregationsGeoBoundsAggregate,
+  LatLonGeoLocation,
+  TopLeftBottomRightGeoBounds,
+} from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
 
-import { UpdateSourceEditor } from './update_source_editor';
 import { i18n } from '@kbn/i18n';
+// @ts-expect-error
+import { UpdateSourceEditor } from './update_source_editor';
 import { SOURCE_TYPES, VECTOR_SHAPE_TYPE } from '../../../../common/constants';
 import { getDataSourceLabel, getDataViewLabel } from '../../../../common/i18n_getters';
+// @ts-expect-error
 import { convertToLines } from './convert_to_lines';
 import { AbstractESAggSource } from '../es_agg_source';
 import { registerSource } from '../source_registry';
 import { turfBboxToBounds } from '../../../../common/elasticsearch_util';
 import { DataRequestAbortError } from '../../util/data_request';
 import { makePublicExecutionContext } from '../../../util';
+import { SourceEditorArgs } from '../source';
+import {
+  ESPewPewSourceDescriptor,
+  MapExtent,
+  VectorSourceRequestMeta,
+} from '../../../../common/descriptor_types';
+import { isValidStringConfig } from '../../util/valid_string_config';
+import { BoundsRequestMeta, GeoJsonWithMeta } from '../vector_source';
 
 const MAX_GEOTILE_LEVEL = 29;
 
@@ -27,20 +45,30 @@ export const sourceTitle = i18n.translate('xpack.maps.source.pewPewTitle', {
 });
 
 export class ESPewPewSource extends AbstractESAggSource {
-  static type = SOURCE_TYPES.ES_PEW_PEW;
+  readonly _descriptor: ESPewPewSourceDescriptor;
 
-  static createDescriptor(descriptor) {
+  static createDescriptor(descriptor: Partial<ESPewPewSourceDescriptor>): ESPewPewSourceDescriptor {
     const normalizedDescriptor = AbstractESAggSource.createDescriptor(descriptor);
+    if (!isValidStringConfig(descriptor.sourceGeoField)) {
+      throw new Error('Cannot create ESPewPewSourceDescriptor, sourceGeoField is not provided');
+    }
+    if (!isValidStringConfig(descriptor.destGeoField)) {
+      throw new Error('Cannot create ESPewPewSourceDescriptor, destGeoField is not provided');
+    }
     return {
       ...normalizedDescriptor,
-      type: ESPewPewSource.type,
-      indexPatternId: descriptor.indexPatternId,
-      sourceGeoField: descriptor.sourceGeoField,
-      destGeoField: descriptor.destGeoField,
+      type: SOURCE_TYPES.ES_PEW_PEW,
+      sourceGeoField: descriptor.sourceGeoField!,
+      destGeoField: descriptor.destGeoField!,
     };
   }
 
-  renderSourceSettingsEditor({ onChange }) {
+  constructor(descriptor: ESPewPewSourceDescriptor) {
+    super(descriptor);
+    this._descriptor = descriptor;
+  }
+
+  renderSourceSettingsEditor({ onChange }: SourceEditorArgs) {
     return (
       <UpdateSourceEditor
         indexPatternId={this.getIndexPatternId()}
@@ -100,18 +128,18 @@ export class ESPewPewSource extends AbstractESAggSource {
     ];
   }
 
-  getGeoGridPrecision(zoom) {
+  getGeoGridPrecision(zoom: number) {
     const targetGeotileLevel = Math.ceil(zoom) + 2;
     return Math.min(targetGeotileLevel, MAX_GEOTILE_LEVEL);
   }
 
   async getGeoJsonWithMeta(
-    layerName,
-    searchFilters,
-    registerCancelCallback,
-    isRequestStillActive,
-    inspectorAdapters
-  ) {
+    layerName: string,
+    searchFilters: VectorSourceRequestMeta,
+    registerCancelCallback: (callback: () => void) => void,
+    isRequestStillActive: () => boolean,
+    inspectorAdapters: Adapters
+  ): Promise<GeoJsonWithMeta> {
     const indexPattern = await this.getIndexPattern();
     const searchSource = await this.makeSearchSource(searchFilters, 0);
     searchSource.setField('trackTotalHits', false);
@@ -151,14 +179,10 @@ export class ESPewPewSource extends AbstractESAggSource {
     // Some underlying indices may not contain geo fields
     // Filter out documents without geo fields to avoid shard failures for those indices
     searchSource.setField('filter', [
-      ...searchSource.getField('filter'),
+      ...(searchSource.getField('filter') as Filter[]),
       // destGeoField exists ensured by buffer filter
       // so only need additional check for sourceGeoField
-      {
-        exists: {
-          field: this._descriptor.sourceGeoField,
-        },
-      },
+      buildExistsFilter({ name: this._descriptor.sourceGeoField, type: 'geo_point' }, indexPattern),
     ]);
 
     const esResponse = await this._runEsQuery({
@@ -188,7 +212,10 @@ export class ESPewPewSource extends AbstractESAggSource {
     return this._descriptor.destGeoField;
   }
 
-  async getBoundsForFilters(boundsFilters, registerCancelCallback) {
+  async getBoundsForFilters(
+    boundsFilters: BoundsRequestMeta,
+    registerCancelCallback: (callback: () => void) => void
+  ): Promise<MapExtent | null> {
     const searchSource = await this.makeSearchSource(boundsFilters, 0);
     searchSource.setField('trackTotalHits', false);
     searchSource.setField('aggs', {
@@ -208,31 +235,36 @@ export class ESPewPewSource extends AbstractESAggSource {
     try {
       const abortController = new AbortController();
       registerCancelCallback(() => abortController.abort());
-      const { rawResponse: esResp } = await searchSource
-        .fetch$({
+      const { rawResponse: esResp } = await lastValueFrom(
+        searchSource.fetch$({
           abortSignal: abortController.signal,
           legacyHitsTotal: false,
           executionContext: makePublicExecutionContext('es_pew_pew_source:bounds'),
         })
-        .toPromise();
-      if (esResp.aggregations.destFitToBounds.bounds) {
+      );
+      const destBounds = (esResp.aggregations?.destFitToBounds as AggregationsGeoBoundsAggregate)
+        .bounds as TopLeftBottomRightGeoBounds;
+      if (destBounds) {
         corners.push([
-          esResp.aggregations.destFitToBounds.bounds.top_left.lon,
-          esResp.aggregations.destFitToBounds.bounds.top_left.lat,
+          (destBounds.top_left as LatLonGeoLocation).lon,
+          (destBounds.top_left as LatLonGeoLocation).lat,
         ]);
         corners.push([
-          esResp.aggregations.destFitToBounds.bounds.bottom_right.lon,
-          esResp.aggregations.destFitToBounds.bounds.bottom_right.lat,
+          (destBounds.bottom_right as LatLonGeoLocation).lon,
+          (destBounds.bottom_right as LatLonGeoLocation).lat,
         ]);
       }
-      if (esResp.aggregations.sourceFitToBounds.bounds) {
+      const sourceBounds = (
+        esResp.aggregations?.sourceFitToBounds as AggregationsGeoBoundsAggregate
+      ).bounds as TopLeftBottomRightGeoBounds;
+      if (sourceBounds) {
         corners.push([
-          esResp.aggregations.sourceFitToBounds.bounds.top_left.lon,
-          esResp.aggregations.sourceFitToBounds.bounds.top_left.lat,
+          (sourceBounds.top_left as LatLonGeoLocation).lon,
+          (sourceBounds.top_left as LatLonGeoLocation).lat,
         ]);
         corners.push([
-          esResp.aggregations.sourceFitToBounds.bounds.bottom_right.lon,
-          esResp.aggregations.sourceFitToBounds.bounds.bottom_right.lat,
+          (sourceBounds.bottom_right as LatLonGeoLocation).lon,
+          (sourceBounds.bottom_right as LatLonGeoLocation).lat,
         ]);
       }
     } catch (error) {
diff --git a/x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/index.js b/x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/index.ts
similarity index 100%
rename from x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/index.js
rename to x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/index.ts
diff --git a/x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/point_2_point_layer_wizard.tsx b/x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/point_2_point_layer_wizard.tsx
index 37ecbfdebab11..aa128e3c7d8ff 100644
--- a/x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/point_2_point_layer_wizard.tsx
+++ b/x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/point_2_point_layer_wizard.tsx
@@ -9,7 +9,6 @@ import React from 'react';
 import { i18n } from '@kbn/i18n';
 import { getDefaultDynamicProperties } from '../../styles/vector/vector_style_defaults';
 import { GeoJsonVectorLayer } from '../../layers/vector_layer';
-// @ts-ignore
 import { ESPewPewSource, sourceTitle } from './es_pew_pew_source';
 import { VectorStyle } from '../../styles/vector/vector_style';
 import {
@@ -24,7 +23,11 @@ import { NUMERICAL_COLOR_PALETTES } from '../../styles/color_palettes';
 // @ts-ignore
 import { CreateSourceEditor } from './create_source_editor';
 import { LayerWizard, RenderWizardArguments } from '../../layers';
-import { ColorDynamicOptions, SizeDynamicOptions } from '../../../../common/descriptor_types';
+import {
+  ColorDynamicOptions,
+  ESPewPewSourceDescriptor,
+  SizeDynamicOptions,
+} from '../../../../common/descriptor_types';
 import { Point2PointLayerIcon } from '../../layers/wizards/icons/point_2_point_layer_icon';
 
 export const point2PointLayerWizardConfig: LayerWizard = {
@@ -36,7 +39,7 @@ export const point2PointLayerWizardConfig: LayerWizard = {
   }),
   icon: Point2PointLayerIcon,
   renderWizard: ({ previewLayers }: RenderWizardArguments) => {
-    const onSourceConfigChange = (sourceConfig: unknown) => {
+    const onSourceConfigChange = (sourceConfig: Partial<ESPewPewSourceDescriptor>) => {
       if (!sourceConfig) {
         previewLayers([]);
         return;